]> OCCT Git - occt.git/blob - src/ViewerTest/ViewerTest_ViewerCommands.cxx
0029169: Configuration - fix compilation with undefined UNICODE on Windows
[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 << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4659   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4660   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4661   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4662   {
4663     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4664   }
4665 }
4666
4667 //==============================================================================
4668 //function : VZLayer
4669 //purpose  : Test z layer operations for v3d viewer
4670 //==============================================================================
4671 static int VZLayer (Draw_Interpretor& theDI,
4672                     Standard_Integer  theArgNb,
4673                     const char**      theArgVec)
4674 {
4675   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4676   if (aContextAIS.IsNull())
4677   {
4678     std::cout << "No active viewer!\n";
4679     return 1;
4680   }
4681
4682   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4683   if (theArgNb < 2)
4684   {
4685     TColStd_SequenceOfInteger aLayers;
4686     aViewer->GetAllZLayers (aLayers);
4687     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4688     {
4689       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4690       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4691       printZLayerInfo (theDI, aSettings);
4692     }
4693     return 1;
4694   }
4695
4696   Standard_Integer anArgIter = 1;
4697   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4698   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4699   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4700   {
4701     ++anArgIter;
4702   }
4703
4704   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4705   if (aFirstArg.IsIntegerValue())
4706   {
4707     ++anArgIter;
4708     aLayerId = aFirstArg.IntegerValue();
4709   }
4710   else
4711   {
4712     aFirstArg.LowerCase();
4713     if (aFirstArg == "default"
4714      || aFirstArg == "def")
4715     {
4716       aLayerId = Graphic3d_ZLayerId_Default;
4717       ++anArgIter;
4718     }
4719     else if (aFirstArg == "top")
4720     {
4721       aLayerId = Graphic3d_ZLayerId_Top;
4722       ++anArgIter;
4723     }
4724     else if (aFirstArg == "topmost")
4725     {
4726       aLayerId = Graphic3d_ZLayerId_Topmost;
4727       ++anArgIter;
4728     }
4729     else if (aFirstArg == "overlay"
4730           || aFirstArg == "toposd")
4731     {
4732       aLayerId = Graphic3d_ZLayerId_TopOSD;
4733       ++anArgIter;
4734     }
4735     else if (aFirstArg == "underlay"
4736           || aFirstArg == "botosd")
4737     {
4738       aLayerId = Graphic3d_ZLayerId_BotOSD;
4739       ++anArgIter;
4740     }
4741     else
4742     {
4743       TColStd_SequenceOfInteger aLayers;
4744       aViewer->GetAllZLayers (aLayers);
4745       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4746       {
4747         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4748         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4749         {
4750           aLayerId = aLayeriter.Value();
4751           ++anArgIter;
4752           break;
4753         }
4754       }
4755     }
4756   }
4757
4758   for (; anArgIter < theArgNb; ++anArgIter)
4759   {
4760     // perform operation
4761     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4762     anArg.LowerCase();
4763     if (anUpdateTool.parseRedrawMode (anArg))
4764     {
4765       //
4766     }
4767     else if (anArg == "-add"
4768           || anArg == "add")
4769     {
4770       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4771       if (!aViewer->AddZLayer (aLayerId))
4772       {
4773         std::cout << "Error: can not add a new z layer!\n";
4774         return 0;
4775       }
4776
4777       theDI << aLayerId;
4778     }
4779     else if (anArg == "-del"
4780           || anArg == "-delete"
4781           || anArg == "del")
4782     {
4783       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4784       {
4785         if (++anArgIter >= theArgNb)
4786         {
4787           std::cout << "Syntax error: id of z layer to remove is missing\n";
4788           return 1;
4789         }
4790
4791         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4792       }
4793
4794       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4795        || aLayerId == Graphic3d_ZLayerId_Default
4796        || aLayerId == Graphic3d_ZLayerId_Top
4797        || aLayerId == Graphic3d_ZLayerId_Topmost
4798        || aLayerId == Graphic3d_ZLayerId_TopOSD
4799        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4800       {
4801         std::cout << "Syntax error: standard Z layer can not be removed\n";
4802         return 1;
4803       }
4804
4805       // move all object displayed in removing layer to default layer
4806       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4807            anObjIter.More(); anObjIter.Next())
4808       {
4809         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4810         if (aPrs.IsNull()
4811          || aPrs->ZLayer() != aLayerId)
4812         {
4813           continue;
4814         }
4815         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4816       }
4817
4818       if (!aViewer->RemoveZLayer (aLayerId))
4819       {
4820         std::cout << "Z layer can not be removed!\n";
4821       }
4822       else
4823       {
4824         theDI << aLayerId << " ";
4825       }
4826     }
4827     else if (anArg == "-get"
4828           || anArg == "get")
4829     {
4830       TColStd_SequenceOfInteger aLayers;
4831       aViewer->GetAllZLayers (aLayers);
4832       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4833       {
4834         theDI << aLayeriter.Value() << " ";
4835       }
4836
4837       theDI << "\n";
4838     }
4839     else if (anArg == "-name")
4840     {
4841       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4842       {
4843         std::cout << "Syntax error: id of Z layer is missing\n";
4844         return 1;
4845       }
4846
4847       if (++anArgIter >= theArgNb)
4848       {
4849         std::cout << "Syntax error: name is missing\n";
4850         return 1;
4851       }
4852
4853       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4854       aSettings.SetName (theArgVec[anArgIter]);
4855       aViewer->SetZLayerSettings (aLayerId, aSettings);
4856     }
4857     else if (anArg == "-origin")
4858     {
4859       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4860       {
4861         std::cout << "Syntax error: id of Z layer is missing\n";
4862         return 1;
4863       }
4864
4865       if (anArgIter + 2 >= theArgNb)
4866       {
4867         std::cout << "Syntax error: origin coordinates are missing\n";
4868         return 1;
4869       }
4870
4871       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4872       gp_XYZ anOrigin;
4873       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4874       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4875       anOrigin.SetZ (0.0);
4876       if (anArgIter + 3 < theArgNb)
4877       {
4878         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4879         anArgIter += 3;
4880       }
4881       else
4882       {
4883         anArgIter += 2;
4884       }
4885       aSettings.SetOrigin (anOrigin);
4886       aViewer->SetZLayerSettings (aLayerId, aSettings);
4887     }
4888     else if (anArg == "-settings"
4889           || anArg == "settings")
4890     {
4891       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4892       {
4893         if (++anArgIter >= theArgNb)
4894         {
4895           std::cout << "Syntax error: id of Z layer is missing\n";
4896           return 1;
4897         }
4898
4899         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4900       }
4901
4902       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4903       printZLayerInfo (theDI, aSettings);
4904     }
4905     else if (anArg == "-enable"
4906           || anArg == "enable"
4907           || anArg == "-disable"
4908           || anArg == "disable")
4909     {
4910       const Standard_Boolean toEnable = anArg == "-enable"
4911                                      || anArg == "enable";
4912       if (++anArgIter >= theArgNb)
4913       {
4914         std::cout << "Syntax error: option name is missing\n";
4915         return 1;
4916       }
4917
4918       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4919       aSubOp.LowerCase();
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       if (aSubOp == "depthtest"
4933        || aSubOp == "test")
4934       {
4935         aSettings.SetEnableDepthTest (toEnable);
4936       }
4937       else if (aSubOp == "depthwrite"
4938             || aSubOp == "write")
4939       {
4940         aSettings.SetEnableDepthWrite (toEnable);
4941       }
4942       else if (aSubOp == "depthclear"
4943             || aSubOp == "clear")
4944       {
4945         aSettings.SetClearDepth (toEnable);
4946       }
4947       else if (aSubOp == "depthoffset"
4948             || aSubOp == "offset")
4949       {
4950         Graphic3d_PolygonOffset aParams;
4951         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4952         if (toEnable)
4953         {
4954           if (anArgIter + 2 >= theArgNb)
4955           {
4956             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4957             return 1;
4958           }
4959
4960           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4961           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4962         }
4963         aSettings.SetPolygonOffset (aParams);
4964       }
4965       else if (aSubOp == "positiveoffset"
4966             || aSubOp == "poffset")
4967       {
4968         if (toEnable)
4969         {
4970           aSettings.SetDepthOffsetPositive();
4971         }
4972         else
4973         {
4974           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4975         }
4976       }
4977       else if (aSubOp == "negativeoffset"
4978             || aSubOp == "noffset")
4979       {
4980         if (toEnable)
4981         {
4982           aSettings.SetDepthOffsetNegative();
4983         }
4984         else
4985         {
4986           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4987         }
4988       }
4989       else if (aSubOp == "textureenv")
4990       {
4991         aSettings.SetEnvironmentTexture (toEnable);
4992       }
4993
4994       aViewer->SetZLayerSettings (aLayerId, aSettings);
4995     }
4996     else
4997     {
4998       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4999       return 1;
5000     }
5001   }
5002
5003   return 0;
5004 }
5005
5006 // The interactive presentation of 2d layer item
5007 // for "vlayerline" command it provides a presentation of
5008 // line with user-defined linewidth, linetype and transparency.
5009 class V3d_LineItem : public AIS_InteractiveObject
5010 {
5011 public:
5012   // CASCADE RTTI
5013   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5014
5015   // constructor
5016   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5017                                Standard_Real X2, Standard_Real Y2,
5018                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5019                                Standard_Real theWidth    = 0.5,
5020                                Standard_Real theTransp   = 1.0);
5021
5022   private:
5023
5024   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5025                 const Handle(Prs3d_Presentation)& thePresentation,
5026                 const Standard_Integer theMode) Standard_OVERRIDE;
5027
5028   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5029                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5030   {}
5031
5032 private:
5033
5034   Standard_Real       myX1, myY1, myX2, myY2;
5035   Aspect_TypeOfLine   myType;
5036   Standard_Real       myWidth;
5037 };
5038
5039 // default constructor for line item
5040 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5041                            Standard_Real X2, Standard_Real Y2,
5042                            Aspect_TypeOfLine theType,
5043                            Standard_Real theWidth,
5044                            Standard_Real theTransp) :
5045   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5046   myType(theType), myWidth(theWidth)
5047 {
5048   SetTransparency (1-theTransp);
5049 }
5050
5051 // render line
5052 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5053                             const Handle(Prs3d_Presentation)& thePresentation,
5054                             const Standard_Integer /*theMode*/)
5055 {
5056   thePresentation->Clear();
5057   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5058   Standard_Integer aWidth, aHeight;
5059   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5060   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5061   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5062   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5063   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5064   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5065   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5066   aGroup->AddPrimitiveArray (aPrim);
5067 }
5068
5069 //=============================================================================
5070 //function : VLayerLine
5071 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5072 //         : linewidth, transparency coefficient
5073 //============================================================================
5074 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5075 {
5076   // get the active view
5077   Handle(V3d_View) aView = ViewerTest::CurrentView();
5078   if (aView.IsNull())
5079   {
5080     di << "Call vinit before!\n";
5081     return 1;
5082   }
5083   else if (argc < 5)
5084   {
5085     di << "Use: " << argv[0];
5086     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5087     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5088     di << "              0 - solid  \n";
5089     di << "              1 - dashed \n";
5090     di << "              2 - dot    \n";
5091     di << "              3 - dashdot\n";
5092     di << " transparency : { 0.0 - 1.0 } \n";
5093     di << "                  0.0 - transparent\n";
5094     di << "                  1.0 - visible    \n";
5095     return 1;
5096   }
5097
5098   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5099   // get the input params
5100   Standard_Real X1 = Draw::Atof(argv[1]);
5101   Standard_Real Y1 = Draw::Atof(argv[2]);
5102   Standard_Real X2 = Draw::Atof(argv[3]);
5103   Standard_Real Y2 = Draw::Atof(argv[4]);
5104
5105   Standard_Real aWidth = 0.5;
5106   Standard_Real aTransparency = 1.0;
5107
5108   // has width
5109   if (argc > 5)
5110     aWidth = Draw::Atof(argv[5]);
5111
5112   // select appropriate line type
5113   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5114   if (argc > 6
5115   && !ViewerTest::ParseLineType (argv[6], aLineType))
5116   {
5117     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5118     return 1;
5119   }
5120
5121   // has transparency
5122   if (argc > 7)
5123   {
5124     aTransparency = Draw::Atof(argv[7]);
5125     if (aTransparency < 0 || aTransparency > 1.0)
5126       aTransparency = 1.0;
5127   }
5128
5129   static Handle (V3d_LineItem) aLine;
5130   if (!aLine.IsNull())
5131   {
5132     aContext->Erase (aLine, Standard_False);
5133   }
5134   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5135                             aLineType, aWidth,
5136                             aTransparency);
5137
5138   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5139   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5140   aLine->SetToUpdate();
5141   aContext->Display (aLine, Standard_True);
5142
5143   return 0;
5144 }
5145
5146
5147 //==============================================================================
5148 //function : VGrid
5149 //purpose  :
5150 //==============================================================================
5151
5152 static int VGrid (Draw_Interpretor& /*theDI*/,
5153                   Standard_Integer  theArgNb,
5154                   const char**      theArgVec)
5155 {
5156   // get the active view
5157   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5158   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5159   if (aView.IsNull() || aViewer.IsNull())
5160   {
5161     std::cerr << "No active view. Please call vinit.\n";
5162     return 1;
5163   }
5164
5165   Aspect_GridType     aType = aViewer->GridType();
5166   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5167   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5168   Standard_Integer anIter = 1;
5169   for (; anIter < theArgNb; ++anIter)
5170   {
5171     const char* aValue = theArgVec[anIter];
5172     if (anUpdateTool.parseRedrawMode (aValue))
5173     {
5174       continue;
5175     }
5176     else if (*aValue == 'r')
5177     {
5178       aType = Aspect_GT_Rectangular;
5179     }
5180     else if (*aValue == 'c')
5181     {
5182       aType = Aspect_GT_Circular;
5183     }
5184     else if (*aValue == 'l')
5185     {
5186       aMode = Aspect_GDM_Lines;
5187     }
5188     else if (*aValue == 'p')
5189     {
5190       aMode = Aspect_GDM_Points;
5191     }
5192     else if (strcmp (aValue, "off" ) == 0)
5193     {
5194       aViewer->DeactivateGrid();
5195       return 0;
5196     }
5197     else
5198     {
5199       break;
5200     }
5201   }
5202
5203   Standard_Integer aTail = (theArgNb - anIter);
5204   if (aTail == 0)
5205   {
5206     aViewer->ActivateGrid (aType, aMode);
5207     return 0;
5208   }
5209   else if (aTail != 2 && aTail != 5)
5210   {
5211     std::cerr << "Incorrect arguments number! Usage:\n"
5212               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5213     return 1;
5214   }
5215
5216   Standard_Real anOriginX, anOriginY, aRotAngle;
5217   if (aType == Aspect_GT_Rectangular)
5218   {
5219     Standard_Real aRStepX, aRStepY;
5220     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5221
5222     anOriginX = Draw::Atof (theArgVec[anIter++]);
5223     anOriginY = Draw::Atof (theArgVec[anIter++]);
5224     if (aTail == 5)
5225     {
5226       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5227       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5228       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5229     }
5230     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5231     aViewer->ActivateGrid (aType, aMode);
5232   }
5233   else if (aType == Aspect_GT_Circular)
5234   {
5235     Standard_Real aRadiusStep;
5236     Standard_Integer aDivisionNumber;
5237     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5238
5239     anOriginX = Draw::Atof (theArgVec[anIter++]);
5240     anOriginY = Draw::Atof (theArgVec[anIter++]);
5241     if (aTail == 5)
5242     {
5243       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5244       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5245       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5246     }
5247
5248     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5249     aViewer->ActivateGrid (aType, aMode);
5250   }
5251
5252   return 0;
5253 }
5254
5255 //==============================================================================
5256 //function : VPriviledgedPlane
5257 //purpose  :
5258 //==============================================================================
5259
5260 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5261                               Standard_Integer  theArgNb,
5262                               const char**      theArgVec)
5263 {
5264   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5265   {
5266     std::cerr << "Error: wrong number of arguments! See usage:\n";
5267     theDI.PrintHelp (theArgVec[0]);
5268     return 1;
5269   }
5270
5271   // get the active viewer
5272   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5273   if (aViewer.IsNull())
5274   {
5275     std::cerr << "Error: no active viewer. Please call vinit.\n";
5276     return 1;
5277   }
5278
5279   if (theArgNb == 1)
5280   {
5281     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5282     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5283     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5284     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5285     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5286           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5287           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5288     return 0;
5289   }
5290
5291   Standard_Integer anArgIdx = 1;
5292   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5293   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5294   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5295   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5296   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5297   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5298
5299   gp_Ax3 aPriviledgedPlane;
5300   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5301   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5302   if (theArgNb > 7)
5303   {
5304     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5305     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5306     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5307     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5308     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5309   }
5310   else
5311   {
5312     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5313   }
5314
5315   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5316
5317   return 0;
5318 }
5319
5320 //==============================================================================
5321 //function : VConvert
5322 //purpose  :
5323 //==============================================================================
5324
5325 static int VConvert (Draw_Interpretor& theDI,
5326                      Standard_Integer  theArgNb,
5327                      const char**      theArgVec)
5328 {
5329   // get the active view
5330   Handle(V3d_View) aView = ViewerTest::CurrentView();
5331   if (aView.IsNull())
5332   {
5333     std::cerr << "Error: no active view. Please call vinit.\n";
5334     return 1;
5335   }
5336
5337   enum { Model, Ray, View, Window, Grid } aMode = Model;
5338
5339   // access coordinate arguments
5340   TColStd_SequenceOfReal aCoord;
5341   Standard_Integer anArgIdx = 1;
5342   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5343   {
5344     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5345     if (!anArg.IsRealValue())
5346     {
5347       break;
5348     }
5349     aCoord.Append (anArg.RealValue());
5350   }
5351
5352   // non-numeric argument too early
5353   if (aCoord.IsEmpty())
5354   {
5355     std::cerr << "Error: wrong number of arguments! See usage:\n";
5356     theDI.PrintHelp (theArgVec[0]);
5357     return 1;
5358   }
5359
5360   // collect all other arguments and options
5361   for (; anArgIdx < theArgNb; ++anArgIdx)
5362   {
5363     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5364     anArg.LowerCase();
5365     if      (anArg == "window") aMode = Window;
5366     else if (anArg == "view")   aMode = View;
5367     else if (anArg == "grid")   aMode = Grid;
5368     else if (anArg == "ray")    aMode = Ray;
5369     else
5370     {
5371       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5372       theDI.PrintHelp (theArgVec[0]);
5373       return 1;
5374     }
5375   }
5376
5377   // complete input checks
5378   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5379       (aCoord.Length() == 2 && theArgNb > 4) ||
5380       (aCoord.Length() == 3 && theArgNb > 5))
5381   {
5382     std::cerr << "Error: wrong number of arguments! See usage:\n";
5383     theDI.PrintHelp (theArgVec[0]);
5384     return 1;
5385   }
5386
5387   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5388   Standard_Integer aXYp[2] = {0, 0};
5389
5390   // convert one-dimensional coordinate
5391   if (aCoord.Length() == 1)
5392   {
5393     switch (aMode)
5394     {
5395       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5396       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5397       default:
5398         std::cerr << "Error: wrong arguments! See usage:\n";
5399         theDI.PrintHelp (theArgVec[0]);
5400         return 1;
5401     }
5402   }
5403
5404   // convert 2D coordinates from projection or view reference space
5405   if (aCoord.Length() == 2)
5406   {
5407     switch (aMode)
5408     {
5409       case Model :
5410         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5411         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5412         return 0;
5413
5414       case View :
5415         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5416         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5417         return 0;
5418
5419       case Window :
5420         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5421         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5422         return 0;
5423
5424       case Grid :
5425         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5426         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5427         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5428         return 0;
5429
5430       case Ray :
5431         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5432                                 (Standard_Integer) aCoord (2),
5433                                 aXYZ[0], aXYZ[1], aXYZ[2],
5434                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5435         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5436         return 0;
5437
5438       default:
5439         std::cerr << "Error: wrong arguments! See usage:\n";
5440         theDI.PrintHelp (theArgVec[0]);
5441         return 1;
5442     }
5443   }
5444
5445   // convert 3D coordinates from view reference space
5446   else if (aCoord.Length() == 3)
5447   {
5448     switch (aMode)
5449     {
5450       case Window :
5451         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5452         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5453         return 0;
5454
5455       case Grid :
5456         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5457         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5458         return 0;
5459
5460       default:
5461         std::cerr << "Error: wrong arguments! See usage:\n";
5462         theDI.PrintHelp (theArgVec[0]);
5463         return 1;
5464     }
5465   }
5466
5467   return 0;
5468 }
5469
5470 //==============================================================================
5471 //function : VFps
5472 //purpose  :
5473 //==============================================================================
5474
5475 static int VFps (Draw_Interpretor& theDI,
5476                  Standard_Integer  theArgNb,
5477                  const char**      theArgVec)
5478 {
5479   // get the active view
5480   Handle(V3d_View) aView = ViewerTest::CurrentView();
5481   if (aView.IsNull())
5482   {
5483     std::cerr << "No active view. Please call vinit.\n";
5484     return 1;
5485   }
5486
5487   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5488   if (aFramesNb <= 0)
5489   {
5490     std::cerr << "Incorrect arguments!\n";
5491     return 1;
5492   }
5493
5494   // the time is meaningless for first call
5495   // due to async OpenGl rendering
5496   aView->Redraw();
5497
5498   // redraw view in loop to estimate average values
5499   OSD_Timer aTimer;
5500   aTimer.Start();
5501   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5502   {
5503     aView->Redraw();
5504   }
5505   aTimer.Stop();
5506   Standard_Real aCpu;
5507   const Standard_Real aTime = aTimer.ElapsedTime();
5508   aTimer.OSD_Chronometer::Show (aCpu);
5509
5510   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5511   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5512
5513   // return statistics
5514   theDI << "FPS: " << aFpsAver << "\n"
5515         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5516
5517   // compute additional statistics in ray-tracing mode
5518   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5519
5520   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5521   {
5522     Standard_Integer aSizeX;
5523     Standard_Integer aSizeY;
5524
5525     aView->Window()->Size (aSizeX, aSizeY);
5526
5527     // 1 shadow ray and 1 secondary ray pew each bounce
5528     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5529
5530     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5531   }
5532
5533   return 0;
5534 }
5535
5536 //==============================================================================
5537 //function : VGlDebug
5538 //purpose  :
5539 //==============================================================================
5540
5541 static int VGlDebug (Draw_Interpretor& theDI,
5542                      Standard_Integer  theArgNb,
5543                      const char**      theArgVec)
5544 {
5545   Handle(OpenGl_GraphicDriver) aDriver;
5546   Handle(V3d_View) aView = ViewerTest::CurrentView();
5547   if (!aView.IsNull())
5548   {
5549     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5550   }
5551   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5552   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5553
5554   if (theArgNb < 2)
5555   {
5556     TCollection_AsciiString aDebActive, aSyncActive;
5557     if (aCaps == NULL)
5558     {
5559       aCaps = aDefCaps;
5560     }
5561     else
5562     {
5563       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5564                                                                   "GL_ARB_debug_output");
5565       aDebActive = isActive ? " (active)" : " (inactive)";
5566       if (isActive)
5567       {
5568         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5569         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5570       }
5571     }
5572
5573     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5574           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5575           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5576           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5577     return 0;
5578   }
5579
5580   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5581   {
5582     Standard_CString        anArg     = theArgVec[anArgIter];
5583     TCollection_AsciiString anArgCase (anArg);
5584     anArgCase.LowerCase();
5585     Standard_Boolean toEnableDebug = Standard_True;
5586     if (anArgCase == "-glsl"
5587      || anArgCase == "-glslwarn"
5588      || anArgCase == "-glslwarns"
5589      || anArgCase == "-glslwarnings")
5590     {
5591       Standard_Boolean toShowWarns = Standard_True;
5592       if (++anArgIter < theArgNb
5593       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5594       {
5595         --anArgIter;
5596       }
5597       aDefCaps->glslWarnings = toShowWarns;
5598       if (aCaps != NULL)
5599       {
5600         aCaps->glslWarnings = toShowWarns;
5601       }
5602     }
5603     else if (anArgCase == "-extra"
5604           || anArgCase == "-extramsg"
5605           || anArgCase == "-extramessages")
5606     {
5607       Standard_Boolean toShow = Standard_True;
5608       if (++anArgIter < theArgNb
5609       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5610       {
5611         --anArgIter;
5612       }
5613       aDefCaps->suppressExtraMsg = !toShow;
5614       if (aCaps != NULL)
5615       {
5616         aCaps->suppressExtraMsg = !toShow;
5617       }
5618     }
5619     else if (anArgCase == "-noextra"
5620           || anArgCase == "-noextramsg"
5621           || anArgCase == "-noextramessages")
5622     {
5623       Standard_Boolean toSuppress = Standard_True;
5624       if (++anArgIter < theArgNb
5625       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5626       {
5627         --anArgIter;
5628       }
5629       aDefCaps->suppressExtraMsg = toSuppress;
5630       if (aCaps != NULL)
5631       {
5632         aCaps->suppressExtraMsg = toSuppress;
5633       }
5634     }
5635     else if (anArgCase == "-sync")
5636     {
5637       Standard_Boolean toSync = Standard_True;
5638       if (++anArgIter < theArgNb
5639       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5640       {
5641         --anArgIter;
5642       }
5643       aDefCaps->contextSyncDebug = toSync;
5644       if (toSync)
5645       {
5646         aDefCaps->contextDebug = Standard_True;
5647       }
5648     }
5649     else if (anArgCase == "-debug")
5650     {
5651       if (++anArgIter < theArgNb
5652       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5653       {
5654         --anArgIter;
5655       }
5656       aDefCaps->contextDebug = toEnableDebug;
5657     }
5658     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5659           && (anArgIter + 1 == theArgNb))
5660     {
5661       // simple alias to turn on almost everything
5662       aDefCaps->contextDebug     = toEnableDebug;
5663       aDefCaps->contextSyncDebug = toEnableDebug;
5664       aDefCaps->glslWarnings     = toEnableDebug;
5665     }
5666     else
5667     {
5668       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5669       return 1;
5670     }
5671   }
5672
5673   return 0;
5674 }
5675
5676 //==============================================================================
5677 //function : VVbo
5678 //purpose  :
5679 //==============================================================================
5680
5681 static int VVbo (Draw_Interpretor& theDI,
5682                  Standard_Integer  theArgNb,
5683                  const char**      theArgVec)
5684 {
5685   const Standard_Boolean toSet    = (theArgNb > 1);
5686   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5687   if (toSet)
5688   {
5689     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5690   }
5691
5692   // get the context
5693   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5694   if (aContextAIS.IsNull())
5695   {
5696     if (!toSet)
5697     {
5698       std::cerr << "No active view!\n";
5699     }
5700     return 1;
5701   }
5702   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5703   if (!aDriver.IsNull())
5704   {
5705     if (!toSet)
5706     {
5707       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5708     }
5709     else
5710     {
5711       aDriver->ChangeOptions().vboDisable = toUseVbo;
5712     }
5713   }
5714
5715   return 0;
5716 }
5717
5718 //==============================================================================
5719 //function : VCaps
5720 //purpose  :
5721 //==============================================================================
5722
5723 static int VCaps (Draw_Interpretor& theDI,
5724                   Standard_Integer  theArgNb,
5725                   const char**      theArgVec)
5726 {
5727   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5728   Handle(OpenGl_GraphicDriver)   aDriver;
5729   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5730   if (!aContext.IsNull())
5731   {
5732     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5733     aCaps   = &aDriver->ChangeOptions();
5734   }
5735
5736   if (theArgNb < 2)
5737   {
5738     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5739     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5740     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5741     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5742     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5743     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5744     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5745     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5746     return 0;
5747   }
5748
5749   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5750   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5751   {
5752     Standard_CString        anArg     = theArgVec[anArgIter];
5753     TCollection_AsciiString anArgCase (anArg);
5754     anArgCase.LowerCase();
5755     if (anUpdateTool.parseRedrawMode (anArg))
5756     {
5757       continue;
5758     }
5759     else if (anArgCase == "-vsync"
5760           || anArgCase == "-swapinterval")
5761     {
5762       Standard_Boolean toEnable = Standard_True;
5763       if (++anArgIter < theArgNb
5764       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5765       {
5766         --anArgIter;
5767       }
5768       aCaps->swapInterval = toEnable;
5769     }
5770     else if (anArgCase == "-ffp")
5771     {
5772       Standard_Boolean toEnable = Standard_True;
5773       if (++anArgIter < theArgNb
5774       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5775       {
5776         --anArgIter;
5777       }
5778       aCaps->ffpEnable = toEnable;
5779     }
5780     else if (anArgCase == "-vbo")
5781     {
5782       Standard_Boolean toEnable = Standard_True;
5783       if (++anArgIter < theArgNb
5784       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5785       {
5786         --anArgIter;
5787       }
5788       aCaps->vboDisable = !toEnable;
5789     }
5790     else if (anArgCase == "-sprite"
5791           || anArgCase == "-sprites")
5792     {
5793       Standard_Boolean toEnable = Standard_True;
5794       if (++anArgIter < theArgNb
5795       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5796       {
5797         --anArgIter;
5798       }
5799       aCaps->pntSpritesDisable = !toEnable;
5800     }
5801     else if (anArgCase == "-softmode")
5802     {
5803       Standard_Boolean toEnable = Standard_True;
5804       if (++anArgIter < theArgNb
5805       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5806       {
5807         --anArgIter;
5808       }
5809       aCaps->contextNoAccel = toEnable;
5810     }
5811     else if (anArgCase == "-winbuffer"
5812           || anArgCase == "-windowbuffer"
5813           || anArgCase == "-usewinbuffer"
5814           || anArgCase == "-usewindowbuffer"
5815           || anArgCase == "-usesystembuffer")
5816     {
5817       Standard_Boolean toEnable = Standard_True;
5818       if (++anArgIter < theArgNb
5819       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5820       {
5821         --anArgIter;
5822       }
5823       aCaps->useSystemBuffer = toEnable;
5824     }
5825     else if (anArgCase == "-accel"
5826           || anArgCase == "-acceleration")
5827     {
5828       Standard_Boolean toEnable = Standard_True;
5829       if (++anArgIter < theArgNb
5830       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5831       {
5832         --anArgIter;
5833       }
5834       aCaps->contextNoAccel = !toEnable;
5835     }
5836     else if (anArgCase == "-compat"
5837           || anArgCase == "-compatprofile"
5838           || anArgCase == "-compatible"
5839           || anArgCase == "-compatibleprofile")
5840     {
5841       Standard_Boolean toEnable = Standard_True;
5842       if (++anArgIter < theArgNb
5843       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5844       {
5845         --anArgIter;
5846       }
5847       aCaps->contextCompatible = toEnable;
5848       if (!aCaps->contextCompatible)
5849       {
5850         aCaps->ffpEnable = Standard_False;
5851       }
5852     }
5853     else if (anArgCase == "-core"
5854           || anArgCase == "-coreprofile")
5855     {
5856       Standard_Boolean toEnable = Standard_True;
5857       if (++anArgIter < theArgNb
5858       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5859       {
5860         --anArgIter;
5861       }
5862       aCaps->contextCompatible = !toEnable;
5863       if (!aCaps->contextCompatible)
5864       {
5865         aCaps->ffpEnable = Standard_False;
5866       }
5867     }
5868     else if (anArgCase == "-stereo"
5869           || anArgCase == "-quadbuffer")
5870     {
5871       Standard_Boolean toEnable = Standard_True;
5872       if (++anArgIter < theArgNb
5873       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5874       {
5875         --anArgIter;
5876       }
5877       aCaps->contextStereo = toEnable;
5878     }
5879     else
5880     {
5881       std::cout << "Error: unknown argument '" << anArg << "'\n";
5882       return 1;
5883     }
5884   }
5885   if (aCaps != &ViewerTest_myDefaultCaps)
5886   {
5887     ViewerTest_myDefaultCaps = *aCaps;
5888   }
5889   return 0;
5890 }
5891
5892 //==============================================================================
5893 //function : VMemGpu
5894 //purpose  :
5895 //==============================================================================
5896
5897 static int VMemGpu (Draw_Interpretor& theDI,
5898                     Standard_Integer  theArgNb,
5899                     const char**      theArgVec)
5900 {
5901   // get the context
5902   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5903   if (aContextAIS.IsNull())
5904   {
5905     std::cerr << "No active view. Please call vinit.\n";
5906     return 1;
5907   }
5908
5909   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5910   if (aDriver.IsNull())
5911   {
5912     std::cerr << "Graphic driver not available.\n";
5913     return 1;
5914   }
5915
5916   Standard_Size aFreeBytes = 0;
5917   TCollection_AsciiString anInfo;
5918   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5919   {
5920     std::cerr << "Information not available.\n";
5921     return 1;
5922   }
5923
5924   if (theArgNb > 1 && *theArgVec[1] == 'f')
5925   {
5926     theDI << Standard_Real (aFreeBytes);
5927   }
5928   else
5929   {
5930     theDI << anInfo;
5931   }
5932
5933   return 0;
5934 }
5935
5936 // ==============================================================================
5937 // function : VReadPixel
5938 // purpose  :
5939 // ==============================================================================
5940 static int VReadPixel (Draw_Interpretor& theDI,
5941                        Standard_Integer  theArgNb,
5942                        const char**      theArgVec)
5943 {
5944   // get the active view
5945   Handle(V3d_View) aView = ViewerTest::CurrentView();
5946   if (aView.IsNull())
5947   {
5948     std::cerr << "No active view. Please call vinit.\n";
5949     return 1;
5950   }
5951   else if (theArgNb < 3)
5952   {
5953     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5954     return 1;
5955   }
5956
5957   Image_Format         aFormat     = Image_Format_RGBA;
5958   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
5959
5960   Standard_Integer aWidth, aHeight;
5961   aView->Window()->Size (aWidth, aHeight);
5962   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5963   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5964   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5965   {
5966     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5967     return 1;
5968   }
5969
5970   Standard_Boolean toShowName = Standard_False;
5971   Standard_Boolean toShowHls  = Standard_False;
5972   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5973   {
5974     TCollection_AsciiString aParam (theArgVec[anIter]);
5975     aParam.LowerCase();
5976     if (aParam == "rgb")
5977     {
5978       aFormat     = Image_Format_RGB;
5979       aBufferType = Graphic3d_BT_RGB;
5980     }
5981     else if (aParam == "hls")
5982     {
5983       aFormat     = Image_Format_RGB;
5984       aBufferType = Graphic3d_BT_RGB;
5985       toShowHls   = Standard_True;
5986     }
5987     else if (aParam == "rgbf")
5988     {
5989       aFormat     = Image_Format_RGBF;
5990       aBufferType = Graphic3d_BT_RGB;
5991     }
5992     else if (aParam == "rgba")
5993     {
5994       aFormat     = Image_Format_RGBA;
5995       aBufferType = Graphic3d_BT_RGBA;
5996     }
5997     else if (aParam == "rgbaf")
5998     {
5999       aFormat     = Image_Format_RGBAF;
6000       aBufferType = Graphic3d_BT_RGBA;
6001     }
6002     else if (aParam == "depth")
6003     {
6004       aFormat     = Image_Format_GrayF;
6005       aBufferType = Graphic3d_BT_Depth;
6006     }
6007     else if (aParam == "name")
6008     {
6009       toShowName = Standard_True;
6010     }
6011   }
6012
6013   Image_PixMap anImage;
6014   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6015   {
6016     std::cerr << "Image allocation failed\n";
6017     return 1;
6018   }
6019   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6020   {
6021     std::cerr << "Image dump failed\n";
6022     return 1;
6023   }
6024
6025   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6026   if (toShowName)
6027   {
6028     if (aBufferType == Graphic3d_BT_RGBA)
6029     {
6030       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6031     }
6032     else
6033     {
6034       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6035     }
6036   }
6037   else
6038   {
6039     switch (aBufferType)
6040     {
6041       default:
6042       case Graphic3d_BT_RGB:
6043       {
6044         if (toShowHls)
6045         {
6046           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6047         }
6048         else
6049         {
6050           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6051         }
6052         break;
6053       }
6054       case Graphic3d_BT_RGBA:
6055       {
6056         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6057         break;
6058       }
6059       case Graphic3d_BT_Depth:
6060       {
6061         theDI << aColor.GetRGB().Red();
6062         break;
6063       }
6064     }
6065   }
6066
6067   return 0;
6068 }
6069
6070 //! Auxiliary presentation for an image plane.
6071 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6072 {
6073 public:
6074   //! Main constructor.
6075   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6076                        const Standard_Real theWidth,
6077                        const Standard_Real theHeight,
6078                        const TCollection_AsciiString& theLabel)
6079   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6080   {
6081     SetDisplayMode (0);
6082     SetHilightMode (1);
6083     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6084     {
6085       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6086       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6087       Graphic3d_MaterialAspect aMat;
6088       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6089       aMat.SetAmbient  (1.0);
6090       aMat.SetDiffuse  (1.0);
6091       aMat.SetSpecular (1.0);
6092       aMat.SetEmissive (1.0);
6093       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6094       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6095       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6096       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6097       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6098       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6099       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6100       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6101       aFillAspect->SetFrontMaterial (aMat);
6102       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6103       aFillAspect->SetTextureMapOn();
6104     }
6105     {
6106       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6107       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6108       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6109       myDrawer->SetTextAspect (aTextAspect);
6110     }
6111     {
6112       const gp_Dir aNorm (0.0, 0.0, 1.0);
6113       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6114       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6115       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6116       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6117       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6118       myTris->AddEdge (1);
6119       myTris->AddEdge (2);
6120       myTris->AddEdge (3);
6121       myTris->AddEdge (3);
6122       myTris->AddEdge (2);
6123       myTris->AddEdge (4);
6124
6125       myRect = new Graphic3d_ArrayOfPolylines (4);
6126       myRect->AddVertex (myTris->Vertice (1));
6127       myRect->AddVertex (myTris->Vertice (3));
6128       myRect->AddVertex (myTris->Vertice (4));
6129       myRect->AddVertex (myTris->Vertice (2));
6130     }
6131   }
6132
6133   //! Returns TRUE for accepted display modes.
6134   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6135
6136   //! Compute presentation.
6137   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6138   {
6139     switch (theMode)
6140     {
6141       case 0:
6142       {
6143         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6144         aGroup->AddPrimitiveArray (myTris);
6145         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6146         aGroup->AddPrimitiveArray (myRect);
6147         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6148         return;
6149       }
6150       case 1:
6151       {
6152         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6153         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6154         aGroup->AddPrimitiveArray (myRect);
6155         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6156         return;
6157       }
6158     }
6159   }
6160
6161   //! Compute selection.
6162   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6163   {
6164     if (theMode == 0)
6165     {
6166       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6167       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6168       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6169       theSel->Add (aSensitive);
6170     }
6171   }
6172
6173 private:
6174   Handle(Graphic3d_ArrayOfTriangles) myTris;
6175   Handle(Graphic3d_ArrayOfPolylines) myRect;
6176   TCollection_AsciiString myLabel;
6177   Standard_Real myWidth;
6178   Standard_Real myHeight;
6179 };
6180
6181 //==============================================================================
6182 //function : VDiffImage
6183 //purpose  : The draw-command compares two images.
6184 //==============================================================================
6185
6186 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6187 {
6188   if (theArgNb < 3)
6189   {
6190     std::cout << "Syntax error: not enough arguments.\n";
6191     return 1;
6192   }
6193
6194   Standard_Integer anArgIter = 1;
6195   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6196   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6197   TCollection_AsciiString aDiffImagePath;
6198   Standard_Real    aTolColor        = -1.0;
6199   Standard_Integer toBlackWhite     = -1;
6200   Standard_Integer isBorderFilterOn = -1;
6201   Standard_Boolean isOldSyntax = Standard_False;
6202   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6203   for (; anArgIter < theArgNb; ++anArgIter)
6204   {
6205     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6206     anArg.LowerCase();
6207     if (anArgIter + 1 < theArgNb
6208      && (anArg == "-toleranceofcolor"
6209       || anArg == "-tolerancecolor"
6210       || anArg == "-tolerance"
6211       || anArg == "-toler"))
6212     {
6213       aTolColor = Atof (theArgVec[++anArgIter]);
6214       if (aTolColor < 0.0 || aTolColor > 1.0)
6215       {
6216         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6217         return 1;
6218       }
6219     }
6220     else if (anArg == "-blackwhite")
6221     {
6222       Standard_Boolean toEnable = Standard_True;
6223       if (anArgIter + 1 < theArgNb
6224        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6225       {
6226         ++anArgIter;
6227       }
6228       toBlackWhite = toEnable ? 1 : 0;
6229     }
6230     else if (anArg == "-borderfilter")
6231     {
6232       Standard_Boolean toEnable = Standard_True;
6233       if (anArgIter + 1 < theArgNb
6234        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6235       {
6236         ++anArgIter;
6237       }
6238       isBorderFilterOn = toEnable ? 1 : 0;
6239     }
6240     else if (anArg == "-exitonclose")
6241     {
6242       Draw_ToExitOnCloseView = true;
6243       if (anArgIter + 1 < theArgNb
6244        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6245       {
6246         ++anArgIter;
6247       }
6248     }
6249     else if (anArg == "-closeonescape"
6250           || anArg == "-closeonesc")
6251     {
6252       Draw_ToCloseViewOnEsc = true;
6253       if (anArgIter + 1 < theArgNb
6254        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6255       {
6256         ++anArgIter;
6257       }
6258     }
6259     else if (anArgIter + 3 < theArgNb
6260           && anArg == "-display")
6261     {
6262       aViewName   = theArgVec[++anArgIter];
6263       aPrsNameRef = theArgVec[++anArgIter];
6264       aPrsNameNew = theArgVec[++anArgIter];
6265       if (anArgIter + 1 < theArgNb
6266       && *theArgVec[anArgIter + 1] != '-')
6267       {
6268         aPrsNameDiff = theArgVec[++anArgIter];
6269       }
6270     }
6271     else if (aTolColor < 0.0
6272           && anArg.IsRealValue())
6273     {
6274       isOldSyntax = Standard_True;
6275       aTolColor = anArg.RealValue();
6276       if (aTolColor < 0.0 || aTolColor > 1.0)
6277       {
6278         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6279         return 1;
6280       }
6281     }
6282     else if (isOldSyntax
6283           && toBlackWhite == -1
6284           && (anArg == "0" || anArg == "1"))
6285     {
6286       toBlackWhite = anArg == "1" ? 1 : 0;
6287     }
6288     else if (isOldSyntax
6289           && isBorderFilterOn == -1
6290           && (anArg == "0" || anArg == "1"))
6291     {
6292       isBorderFilterOn = anArg == "1" ? 1 : 0;
6293     }
6294     else if (aDiffImagePath.IsEmpty())
6295     {
6296       aDiffImagePath = theArgVec[anArgIter];
6297     }
6298     else
6299     {
6300       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6301       return 1;
6302     }
6303   }
6304
6305   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6306   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6307   if (!anImgRef->Load (anImgPathRef))
6308   {
6309     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6310     return 1;
6311   }
6312   if (!anImgNew->Load (anImgPathNew))
6313   {
6314     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6315     return 1;
6316   }
6317
6318   // compare the images
6319   Image_Diff aComparer;
6320   Standard_Integer aDiffColorsNb = -1;
6321   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6322   {
6323     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6324     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6325     aDiffColorsNb = aComparer.Compare();
6326     theDI << aDiffColorsNb << "\n";
6327   }
6328
6329   // save image of difference
6330   Handle(Image_AlienPixMap) aDiff;
6331   if (aDiffColorsNb > 0
6332   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6333   {
6334     aDiff = new Image_AlienPixMap();
6335     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6336     {
6337       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6338       return 1;
6339     }
6340     aComparer.SaveDiffImage (*aDiff);
6341     if (!aDiffImagePath.IsEmpty()
6342      && !aDiff->Save (aDiffImagePath))
6343     {
6344       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6345       return 1;
6346     }
6347   }
6348
6349   if (aViewName.IsEmpty())
6350   {
6351     return 0;
6352   }
6353
6354   ViewerTest_Names aViewNames (aViewName);
6355   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6356   {
6357     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6358     theDI.Eval (aCommand.ToCString());
6359   }
6360
6361   Standard_Integer aPxLeft = 0;
6362   Standard_Integer aPxTop  = 0;
6363   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6364   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6365                               ? int(anImgRef->SizeY() * 2)
6366                               : int(anImgRef->SizeY());
6367   TCollection_AsciiString aDisplayName;
6368   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop,
6369                                                             aWinSizeX, aWinSizeY,
6370                                                             aViewName.ToCString(),
6371                                                             aDisplayName.ToCString());
6372
6373   Standard_Real aRatio = anImgRef->Ratio();
6374   Standard_Real aSizeX = 1.0;
6375   Standard_Real aSizeY = aSizeX / aRatio;
6376   {
6377     OSD_Path aPath (anImgPathRef);
6378     TCollection_AsciiString aLabelRef;
6379     if (!aPath.Name().IsEmpty())
6380     {
6381       aLabelRef = aPath.Name() + aPath.Extension();
6382     }
6383     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6384
6385     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6386     gp_Trsf aTrsfRef;
6387     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6388     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6389     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6390   }
6391   {
6392     OSD_Path aPath (anImgPathNew);
6393     TCollection_AsciiString aLabelNew;
6394     if (!aPath.Name().IsEmpty())
6395     {
6396       aLabelNew = aPath.Name() + aPath.Extension();
6397     }
6398     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6399
6400     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6401     gp_Trsf aTrsfRef;
6402     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6403     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6404     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6405   }
6406   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6407   if (!aDiff.IsNull())
6408   {
6409     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6410     gp_Trsf aTrsfDiff;
6411     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6412     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6413   }
6414   if (!aPrsNameDiff.IsEmpty())
6415   {
6416     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6417   }
6418   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6419   ViewerTest::CurrentView()->FitAll();
6420   return 0;
6421 }
6422
6423 //=======================================================================
6424 //function : VSelect
6425 //purpose  : Emulates different types of selection by mouse:
6426 //           1) single click selection
6427 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6428 //           3) selection with polygon having corners at
6429 //           pixel positions (x1,y1),...,(xn,yn)
6430 //           4) any of these selections with shift button pressed
6431 //=======================================================================
6432 static Standard_Integer VSelect (Draw_Interpretor& di,
6433                                  Standard_Integer argc,
6434                                  const char ** argv)
6435 {
6436   if(argc < 3)
6437   {
6438     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6439     return 1;
6440   }
6441
6442   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6443   if(myAIScontext.IsNull())
6444   {
6445     di << "use 'vinit' command before " << argv[0] << "\n";
6446     return 1;
6447   }
6448
6449   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6450   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6451   TCollection_AsciiString anArg;
6452   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6453   anArg.LowerCase();
6454   if (anArg == "-allowoverlap")
6455   {
6456     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6457       : argc == 7;
6458     if (!isValidated)
6459     {
6460       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6461       return 1;
6462     }
6463
6464     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6465     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6466     aCoordsNb -= 2;
6467   }
6468
6469   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6470   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6471   if(aCoordsNb == 2)
6472   {
6473     if(isShiftSelection)
6474       aCurrentEventManager->ShiftSelect();
6475     else
6476       aCurrentEventManager->Select();
6477   }
6478   else if(aCoordsNb == 4)
6479   {
6480     if(isShiftSelection)
6481       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6482     else
6483       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6484   }
6485   else
6486   {
6487     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6488
6489     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6490       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6491
6492     if(isShiftSelection)
6493       aCurrentEventManager->ShiftSelect(aPolyline);
6494     else
6495       aCurrentEventManager->Select(aPolyline);
6496   }
6497   return 0;
6498 }
6499
6500 //=======================================================================
6501 //function : VMoveTo
6502 //purpose  : Emulates cursor movement to defined pixel position
6503 //=======================================================================
6504 static Standard_Integer VMoveTo (Draw_Interpretor& di,
6505                                 Standard_Integer argc,
6506                                 const char ** argv)
6507 {
6508   if(argc != 3)
6509   {
6510     di << "Usage : " << argv[0] << " x y\n";
6511     return 1;
6512   }
6513
6514   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6515   if(aContext.IsNull())
6516   {
6517     di << "use 'vinit' command before " << argv[0] << "\n";
6518     return 1;
6519   }
6520   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6521   return 0;
6522 }
6523
6524 namespace
6525 {
6526   //! Global map storing all animations registered in ViewerTest.
6527   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6528
6529   //! The animation calling the Draw Harness command.
6530   class ViewerTest_AnimationProc : public AIS_Animation
6531   {
6532   public:
6533
6534     //! Main constructor.
6535     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6536                               Draw_Interpretor* theDI,
6537                               const TCollection_AsciiString& theCommand)
6538     : AIS_Animation (theAnimationName),
6539       myDrawInter(theDI),
6540       myCommand  (theCommand)
6541     {
6542       //
6543     }
6544
6545   protected:
6546
6547     //! Evaluate the command.
6548     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6549     {
6550       TCollection_AsciiString aCmd = myCommand;
6551       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6552       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6553       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6554       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6555       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6556       myDrawInter->Eval (aCmd.ToCString());
6557     }
6558
6559     //! Find the keyword in the command and replace it with value.
6560     //! @return the position of the keyword to pass value
6561     void replace (TCollection_AsciiString&       theCmd,
6562                   const TCollection_AsciiString& theKey,
6563                   const TCollection_AsciiString& theVal)
6564     {
6565       TCollection_AsciiString aCmd (theCmd);
6566       aCmd.LowerCase();
6567       const Standard_Integer aPos = aCmd.Search (theKey);
6568       if (aPos == -1)
6569       {
6570         return;
6571       }
6572
6573       TCollection_AsciiString aPart1, aPart2;
6574       Standard_Integer aPart1To = aPos - 1;
6575       if (aPart1To >= 1
6576        && aPart1To <= theCmd.Length())
6577       {
6578         aPart1 = theCmd.SubString (1, aPart1To);
6579       }
6580
6581       Standard_Integer aPart2From = aPos + theKey.Length();
6582       if (aPart2From >= 1
6583        && aPart2From <= theCmd.Length())
6584       {
6585         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6586       }
6587
6588       theCmd = aPart1 + theVal + aPart2;
6589     }
6590
6591   protected:
6592
6593     Draw_Interpretor*       myDrawInter;
6594     TCollection_AsciiString myCommand;
6595
6596   };
6597
6598   //! Replace the animation with the new one.
6599   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6600                                 Handle(AIS_Animation)&       theAnimation,
6601                                 const Handle(AIS_Animation)& theAnimationNew)
6602   {
6603     theAnimationNew->CopyFrom (theAnimation);
6604     if (!theParentAnimation.IsNull())
6605     {
6606       theParentAnimation->Replace (theAnimation, theAnimationNew);
6607     }
6608     else
6609     {
6610       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6611       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6612     }
6613     theAnimation = theAnimationNew;
6614   }
6615
6616   //! Parse the point.
6617   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6618   {
6619     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6620     if (!anXYZ[0].IsRealValue()
6621      || !anXYZ[1].IsRealValue()
6622      || !anXYZ[2].IsRealValue())
6623     {
6624       return Standard_False;
6625     }
6626
6627     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6628     return Standard_True;
6629   }
6630
6631   //! Parse the quaternion.
6632   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6633   {
6634     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6635     if (!anXYZW[0].IsRealValue()
6636      || !anXYZW[1].IsRealValue()
6637      || !anXYZW[2].IsRealValue()
6638      || !anXYZW[3].IsRealValue())
6639     {
6640       return Standard_False;
6641     }
6642
6643     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6644     return Standard_True;
6645   }
6646
6647   //! Auxiliary class for flipping image upside-down.
6648   class ImageFlipper
6649   {
6650   public:
6651
6652     //! Empty constructor.
6653     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6654
6655     //! Perform flipping.
6656     Standard_Boolean FlipY (Image_PixMap& theImage)
6657     {
6658       if (theImage.IsEmpty()
6659        || theImage.SizeX() == 0
6660        || theImage.SizeY() == 0)
6661       {
6662         return Standard_False;
6663       }
6664
6665       const Standard_Size aRowSize = theImage.SizeRowBytes();
6666       if (myTmp.Size() < aRowSize
6667       && !myTmp.Allocate (aRowSize))
6668       {
6669         return Standard_False;
6670       }
6671
6672       // for odd height middle row should be left as is
6673       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6674       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6675       {
6676         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6677         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6678         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
6679         memcpy (aTop,               aBot,         aRowSize);
6680         memcpy (aBot,               myTmp.Data(), aRowSize);
6681       }
6682       return Standard_True;
6683     }
6684
6685   private:
6686     NCollection_Buffer myTmp;
6687   };
6688
6689 }
6690
6691 //=================================================================================================
6692 //function : VViewParams
6693 //purpose  : Gets or sets AIS View characteristics
6694 //=================================================================================================
6695 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6696 {
6697   Handle(V3d_View) aView = ViewerTest::CurrentView();
6698   if (aView.IsNull())
6699   {
6700     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6701     return 1;
6702   }
6703
6704   Standard_Boolean toSetProj     = Standard_False;
6705   Standard_Boolean toSetUp       = Standard_False;
6706   Standard_Boolean toSetAt       = Standard_False;
6707   Standard_Boolean toSetEye      = Standard_False;
6708   Standard_Boolean toSetScale    = Standard_False;
6709   Standard_Boolean toSetSize     = Standard_False;
6710   Standard_Boolean toSetCenter2d = Standard_False;
6711   Standard_Real    aViewScale = aView->Scale();
6712   Standard_Real    aViewSize  = 1.0;
6713   Graphic3d_Vec2i  aCenter2d;
6714   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6715   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6716   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6717   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6718   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6719   if (theArgsNb == 1)
6720   {
6721     // print all of the available view parameters
6722     char aText[4096];
6723     Sprintf (aText,
6724              "Scale: %g\n"
6725              "Proj:  %12g %12g %12g\n"
6726              "Up:    %12g %12g %12g\n"
6727              "At:    %12g %12g %12g\n"
6728              "Eye:   %12g %12g %12g\n",
6729               aViewScale,
6730               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6731               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6732               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6733               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6734     theDi << aText;
6735     return 0;
6736   }
6737
6738   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6739   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6740   {
6741     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6742     anArg.LowerCase();
6743     if (anUpdateTool.parseRedrawMode (anArg))
6744     {
6745       continue;
6746     }
6747     else if (anArg == "-cmd"
6748           || anArg == "-command"
6749           || anArg == "-args")
6750     {
6751       char aText[4096];
6752       Sprintf (aText,
6753                "-scale %g "
6754                "-proj %g %g %g "
6755                "-up %g %g %g "
6756                "-at %g %g %g\n",
6757                 aViewScale,
6758                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6759                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6760                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6761       theDi << aText;
6762     }
6763     else if (anArg == "-scale"
6764           || anArg == "-size")
6765     {
6766       if (anArgIter + 1 < theArgsNb
6767        && *theArgVec[anArgIter + 1] != '-')
6768       {
6769         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6770         if (aValueArg.IsRealValue())
6771         {
6772           ++anArgIter;
6773           if (anArg == "-scale")
6774           {
6775             toSetScale = Standard_True;
6776             aViewScale = aValueArg.RealValue();
6777           }
6778           else if (anArg == "-size")
6779           {
6780             toSetSize = Standard_True;
6781             aViewSize = aValueArg.RealValue();
6782           }
6783           continue;
6784         }
6785       }
6786       if (anArg == "-scale")
6787       {
6788         theDi << "Scale: " << aView->Scale() << "\n";
6789       }
6790       else if (anArg == "-size")
6791       {
6792         Graphic3d_Vec2d aSizeXY;
6793         aView->Size (aSizeXY.x(), aSizeXY.y());
6794         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6795       }
6796     }
6797     else if (anArg == "-eye"
6798           || anArg == "-at"
6799           || anArg == "-up"
6800           || anArg == "-proj")
6801     {
6802       if (anArgIter + 3 < theArgsNb)
6803       {
6804         gp_XYZ anXYZ;
6805         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6806         {
6807           anArgIter += 3;
6808           if (anArg == "-eye")
6809           {
6810             toSetEye = Standard_True;
6811             aViewEye = anXYZ;
6812           }
6813           else if (anArg == "-at")
6814           {
6815             toSetAt = Standard_True;
6816             aViewAt = anXYZ;
6817           }
6818           else if (anArg == "-up")
6819           {
6820             toSetUp = Standard_True;
6821             aViewUp = anXYZ;
6822           }
6823           else if (anArg == "-proj")
6824           {
6825             toSetProj = Standard_True;
6826             aViewProj = anXYZ;
6827           }
6828           continue;
6829         }
6830       }
6831
6832       if (anArg == "-eye")
6833       {
6834         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6835       }
6836       else if (anArg == "-at")
6837       {
6838         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6839       }
6840       else if (anArg == "-up")
6841       {
6842         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6843       }
6844       else if (anArg == "-proj")
6845       {
6846         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6847       }
6848     }
6849     else if (anArg == "-center")
6850     {
6851       if (anArgIter + 2 < theArgsNb)
6852       {
6853         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6854         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6855         if (anX.IsIntegerValue()
6856          && anY.IsIntegerValue())
6857         {
6858           toSetCenter2d = Standard_True;
6859           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6860         }
6861       }
6862     }
6863     else
6864     {
6865       std::cout << "Syntax error at '" << anArg << "'\n";
6866       return 1;
6867     }
6868   }
6869
6870   // change view parameters in proper order
6871   if (toSetScale)
6872   {
6873     aView->SetScale (aViewScale);
6874   }
6875   if (toSetSize)
6876   {
6877     aView->SetSize (aViewSize);
6878   }
6879   if (toSetEye)
6880   {
6881     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6882   }
6883   if (toSetAt)
6884   {
6885     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6886   }
6887   if (toSetProj)
6888   {
6889     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6890   }
6891   if (toSetUp)
6892   {
6893     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6894   }
6895   if (toSetCenter2d)
6896   {
6897     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6898   }
6899
6900   return 0;
6901 }
6902
6903 //==============================================================================
6904 //function : VAnimation
6905 //purpose  :
6906 //==============================================================================
6907 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6908                                     Standard_Integer  theArgNb,
6909                                     const char**      theArgVec)
6910 {
6911   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6912   if (theArgNb < 2)
6913   {
6914     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6915          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6916     {
6917       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6918     }
6919     return 0;
6920   }
6921   if (aCtx.IsNull())
6922   {
6923     std::cout << "Error: no active view\n";
6924     return 1;
6925   }
6926
6927   Standard_Integer anArgIter = 1;
6928   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6929   if (aNameArg.IsEmpty())
6930   {
6931     std::cout << "Syntax error: animation name is not defined.\n";
6932     return 1;
6933   }
6934
6935   TCollection_AsciiString aNameArgLower = aNameArg;
6936   aNameArgLower.LowerCase();
6937   if (aNameArgLower == "-reset"
6938    || aNameArgLower == "-clear")
6939   {
6940     ViewerTest_AnimationTimelineMap.Clear();
6941     return 0;
6942   }
6943   else if (aNameArg.Value (1) == '-')
6944   {
6945     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6946     return 1;
6947   }
6948
6949   const char* aNameSplitter = "/";
6950   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6951   if (aSplitPos == -1)
6952   {
6953     aNameSplitter = ".";
6954     aSplitPos = aNameArg.Search (aNameSplitter);
6955   }
6956
6957   // find existing or create a new animation by specified name within syntax "parent.child".
6958   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6959   for (; !aNameArg.IsEmpty();)
6960   {
6961     TCollection_AsciiString aNameParent;
6962     if (aSplitPos != -1)
6963     {
6964       if (aSplitPos == aNameArg.Length())
6965       {
6966         std::cout << "Syntax error: animation name is not defined.\n";
6967         return 1;
6968       }
6969
6970       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6971       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6972
6973       aSplitPos = aNameArg.Search (aNameSplitter);
6974     }
6975     else
6976     {
6977       aNameParent = aNameArg;
6978       aNameArg.Clear();
6979     }
6980
6981     if (anAnimation.IsNull())
6982     {
6983       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6984       {
6985         anAnimation = new AIS_Animation (aNameParent);
6986         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6987       }
6988       aRootAnimation = anAnimation;
6989     }
6990     else
6991     {
6992       aParentAnimation = anAnimation;
6993       anAnimation = aParentAnimation->Find (aNameParent);
6994       if (anAnimation.IsNull())
6995       {
6996         anAnimation = new AIS_Animation (aNameParent);
6997         aParentAnimation->Add (anAnimation);
6998       }
6999     }
7000   }
7001
7002   if (anArgIter >= theArgNb)
7003   {
7004     // just print the list of children
7005     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7006     {
7007       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7008     }
7009     return 0;
7010   }
7011
7012   // animation parameters
7013   Standard_Boolean toPlay = Standard_False;
7014   Standard_Real aPlaySpeed     = 1.0;
7015   Standard_Real aPlayStartTime = anAnimation->StartPts();
7016   Standard_Real aPlayDuration  = anAnimation->Duration();
7017   Standard_Boolean isFreeCamera = Standard_False;
7018   Standard_Boolean isLockLoop   = Standard_False;
7019
7020   // video recording parameters
7021   TCollection_AsciiString aRecFile;
7022   Image_VideoParams aRecParams;
7023
7024   Handle(V3d_View) aView = ViewerTest::CurrentView();
7025   for (; anArgIter < theArgNb; ++anArgIter)
7026   {
7027     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7028     anArg.LowerCase();
7029     // general options
7030     if (anArg == "-reset"
7031      || anArg == "-clear")
7032     {
7033       anAnimation->Clear();
7034     }
7035     else if (anArg == "-remove"
7036           || anArg == "-del"
7037           || anArg == "-delete")
7038     {
7039       if (!aParentAnimation.IsNull())
7040       {
7041         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7042       }
7043       else
7044       {
7045         aParentAnimation->Remove (anAnimation);
7046       }
7047     }
7048     // playback options
7049     else if (anArg == "-play")
7050     {
7051       toPlay = Standard_True;
7052       if (++anArgIter < theArgNb)
7053       {
7054         if (*theArgVec[anArgIter] == '-')
7055         {
7056           --anArgIter;
7057           continue;
7058         }
7059         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7060
7061         if (++anArgIter < theArgNb)
7062         {
7063           if (*theArgVec[anArgIter] == '-')
7064           {
7065             --anArgIter;
7066             continue;
7067           }
7068           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7069         }
7070       }
7071     }
7072     else if (anArg == "-resume")
7073     {
7074       toPlay = Standard_True;
7075       aPlayStartTime = anAnimation->ElapsedTime();
7076       if (++anArgIter < theArgNb)
7077       {
7078         if (*theArgVec[anArgIter] == '-')
7079         {
7080           --anArgIter;
7081           continue;
7082         }
7083
7084         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7085       }
7086     }
7087     else if (anArg == "-playspeed"
7088           || anArg == "-speed")
7089     {
7090       if (++anArgIter >= theArgNb)
7091       {
7092         std::cout << "Syntax error at " << anArg << ".\n";
7093         return 1;
7094       }
7095       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7096     }
7097     else if (anArg == "-lock"
7098           || anArg == "-lockloop"
7099           || anArg == "-playlockloop")
7100     {
7101       isLockLoop = Standard_True;
7102     }
7103     else if (anArg == "-freecamera"
7104           || anArg == "-playfreecamera"
7105           || anArg == "-freelook")
7106     {
7107       isFreeCamera = Standard_True;
7108     }
7109     // video recodring options
7110     else if (anArg == "-rec"
7111           || anArg == "-record")
7112     {
7113       if (++anArgIter >= theArgNb)
7114       {
7115         std::cout << "Syntax error at " << anArg << ".\n";
7116         return 1;
7117       }
7118
7119       aRecFile = theArgVec[anArgIter];
7120       if (aRecParams.FpsNum <= 0)
7121       {
7122         aRecParams.FpsNum = 24;
7123       }
7124
7125       if (anArgIter + 2 < theArgNb
7126       && *theArgVec[anArgIter + 1] != '-'
7127       && *theArgVec[anArgIter + 2] != '-')
7128       {
7129         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7130         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7131         if (aWidthArg .IsIntegerValue()
7132          && aHeightArg.IsIntegerValue())
7133         {
7134           aRecParams.Width  = aWidthArg .IntegerValue();
7135           aRecParams.Height = aHeightArg.IntegerValue();
7136           anArgIter += 2;
7137         }
7138       }
7139     }
7140     else if (anArg == "-fps")
7141     {
7142       if (++anArgIter >= theArgNb)
7143       {
7144         std::cout << "Syntax error at " << anArg << ".\n";
7145         return 1;
7146       }
7147
7148       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7149       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7150       if (aSplitIndex == 0)
7151       {
7152         aRecParams.FpsNum = aFpsArg.IntegerValue();
7153       }
7154       else
7155       {
7156         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7157         aFpsArg.Split (aFpsArg.Length() - 1);
7158         const TCollection_AsciiString aNumStr = aFpsArg;
7159         aRecParams.FpsNum = aNumStr.IntegerValue();
7160         aRecParams.FpsDen = aDenStr.IntegerValue();
7161         if (aRecParams.FpsDen < 1)
7162         {
7163           std::cout << "Syntax error at " << anArg << ".\n";
7164           return 1;
7165         }
7166       }
7167     }
7168     else if (anArg == "-format")
7169     {
7170       if (++anArgIter >= theArgNb)
7171       {
7172         std::cout << "Syntax error at " << anArg << ".\n";
7173         return 1;
7174       }
7175       aRecParams.Format = theArgVec[anArgIter];
7176     }
7177     else if (anArg == "-pix_fmt"
7178           || anArg == "-pixfmt"
7179           || anArg == "-pixelformat")
7180     {
7181       if (++anArgIter >= theArgNb)
7182       {
7183         std::cout << "Syntax error at " << anArg << ".\n";
7184         return 1;
7185       }
7186       aRecParams.PixelFormat = theArgVec[anArgIter];
7187     }
7188     else if (anArg == "-codec"
7189           || anArg == "-vcodec"
7190           || anArg == "-videocodec")
7191     {
7192       if (++anArgIter >= theArgNb)
7193       {
7194         std::cout << "Syntax error at " << anArg << ".\n";
7195         return 1;
7196       }
7197       aRecParams.VideoCodec = theArgVec[anArgIter];
7198     }
7199     else if (anArg == "-crf"
7200           || anArg == "-preset"
7201           || anArg == "-qp")
7202     {
7203       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7204       if (++anArgIter >= theArgNb)
7205       {
7206         std::cout << "Syntax error at " << anArg << ".\n";
7207         return 1;
7208       }
7209
7210       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7211     }
7212     // animation definition options
7213     else if (anArg == "-start"
7214           || anArg == "-starttime"
7215           || anArg == "-startpts")
7216     {
7217       if (++anArgIter >= theArgNb)
7218       {
7219         std::cout << "Syntax error at " << anArg << ".\n";
7220         return 1;
7221       }
7222
7223       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7224       aRootAnimation->UpdateTotalDuration();
7225     }
7226     else if (anArg == "-end"
7227           || anArg == "-endtime"
7228           || anArg == "-endpts")
7229     {
7230       if (++anArgIter >= theArgNb)
7231       {
7232         std::cout << "Syntax error at " << anArg << ".\n";
7233         return 1;
7234       }
7235
7236       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7237       aRootAnimation->UpdateTotalDuration();
7238     }
7239     else if (anArg == "-dur"
7240           || anArg == "-duration")
7241     {
7242       if (++anArgIter >= theArgNb)
7243       {
7244         std::cout << "Syntax error at " << anArg << ".\n";
7245         return 1;
7246       }
7247
7248       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7249       aRootAnimation->UpdateTotalDuration();
7250     }
7251     else if (anArg == "-command"
7252           || anArg == "-cmd"
7253           || anArg == "-invoke"
7254           || anArg == "-eval"
7255           || anArg == "-proc")
7256     {
7257       if (++anArgIter >= theArgNb)
7258       {
7259         std::cout << "Syntax error at " << anArg << ".\n";
7260         return 1;
7261       }
7262
7263       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7264       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7265     }
7266     else if (anArg == "-objecttrsf"
7267           || anArg == "-objectransformation"
7268           || anArg == "-objtransformation"
7269           || anArg == "-objtrsf"
7270           || anArg == "-object"
7271           || anArg == "-obj")
7272     {
7273       if (++anArgIter >= theArgNb)
7274       {
7275         std::cout << "Syntax error at " << anArg << ".\n";
7276         return 1;
7277       }
7278
7279       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7280       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7281       if (!aMapOfAIS.IsBound2 (anObjName))
7282       {
7283         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7284         return 1;
7285       }
7286
7287       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
7288       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7289       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7290       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7291       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7292       Standard_Boolean isTrsfSet = Standard_False;
7293       Standard_Integer aTrsfArgIter = anArgIter + 1;
7294       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7295       {
7296         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7297         aTrsfArg.LowerCase();
7298         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7299         if (aTrsfArg.StartsWith ("-rotation")
7300          || aTrsfArg.StartsWith ("-rot"))
7301         {
7302           isTrsfSet = Standard_True;
7303           if (aTrsfArgIter + 4 >= theArgNb
7304           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7305           {
7306             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7307             return 1;
7308           }
7309           aTrsfArgIter += 4;
7310         }
7311         else if (aTrsfArg.StartsWith ("-location")
7312               || aTrsfArg.StartsWith ("-loc"))
7313         {
7314           isTrsfSet = Standard_True;
7315           if (aTrsfArgIter + 3 >= theArgNb
7316           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7317           {
7318             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7319             return 1;
7320           }
7321           aTrsfArgIter += 3;
7322         }
7323         else if (aTrsfArg.StartsWith ("-scale"))
7324         {
7325           isTrsfSet = Standard_True;
7326           if (++aTrsfArgIter >= theArgNb)
7327           {
7328             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7329             return 1;
7330           }
7331
7332           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7333           if (!aScaleStr.IsRealValue())
7334           {
7335             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7336             return 1;
7337           }
7338           aScales[anIndex] = aScaleStr.RealValue();
7339         }
7340         else
7341         {
7342           anArgIter = aTrsfArgIter - 1;
7343           break;
7344         }
7345       }
7346       if (!isTrsfSet)
7347       {
7348         std::cout << "Syntax error at " << anArg << ".\n";
7349         return 1;
7350       }
7351       else if (aTrsfArgIter >= theArgNb)
7352       {
7353         anArgIter = theArgNb;
7354       }
7355
7356       aTrsfs[0].SetRotation        (aRotQuats[0]);
7357       aTrsfs[1].SetRotation        (aRotQuats[1]);
7358       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7359       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7360       aTrsfs[0].SetScaleFactor     (aScales[0]);
7361       aTrsfs[1].SetScaleFactor     (aScales[1]);
7362
7363       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7364       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7365     }
7366     else if (anArg == "-viewtrsf"
7367           || anArg == "-view")
7368     {
7369       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7370       if (aCamAnimation.IsNull())
7371       {
7372         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7373         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7374       }
7375
7376       Handle(Graphic3d_Camera) aCams[2] =
7377       {
7378         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7379         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7380       };
7381
7382       Standard_Boolean isTrsfSet = Standard_False;
7383       Standard_Integer aViewArgIter = anArgIter + 1;
7384       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7385       {
7386         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7387         aViewArg.LowerCase();
7388         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7389         if (aViewArg.StartsWith ("-scale"))
7390         {
7391           isTrsfSet = Standard_True;
7392           if (++aViewArgIter >= theArgNb)
7393           {
7394             std::cout << "Syntax error at " << anArg << ".\n";
7395             return 1;
7396           }
7397
7398           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7399           if (!aScaleStr.IsRealValue())
7400           {
7401             std::cout << "Syntax error at " << aViewArg << ".\n";
7402             return 1;
7403           }
7404           Standard_Real aScale = aScaleStr.RealValue();
7405           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7406           aCams[anIndex]->SetScale (aScale);
7407         }
7408         else if (aViewArg.StartsWith ("-eye")
7409               || aViewArg.StartsWith ("-center")
7410               || aViewArg.StartsWith ("-at")
7411               || aViewArg.StartsWith ("-up"))
7412         {
7413           isTrsfSet = Standard_True;
7414           gp_XYZ anXYZ;
7415           if (aViewArgIter + 3 >= theArgNb
7416           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7417           {
7418             std::cout << "Syntax error at " << aViewArg << ".\n";
7419             return 1;
7420           }
7421           aViewArgIter += 3;
7422
7423           if (aViewArg.StartsWith ("-eye"))
7424           {
7425             aCams[anIndex]->SetEye (anXYZ);
7426           }
7427           else if (aViewArg.StartsWith ("-center")
7428                 || aViewArg.StartsWith ("-at"))
7429           {
7430             aCams[anIndex]->SetCenter (anXYZ);
7431           }
7432           else if (aViewArg.StartsWith ("-up"))
7433           {
7434             aCams[anIndex]->SetUp (anXYZ);
7435           }
7436         }
7437         else
7438         {
7439           anArgIter = aViewArgIter - 1;
7440           break;
7441         }
7442       }
7443       if (!isTrsfSet)
7444       {
7445         std::cout << "Syntax error at " << anArg << ".\n";
7446         return 1;
7447       }
7448       else if (aViewArgIter >= theArgNb)
7449       {
7450         anArgIter = theArgNb;
7451       }
7452
7453       aCamAnimation->SetCameraStart(aCams[0]);
7454       aCamAnimation->SetCameraEnd  (aCams[1]);
7455     }
7456     else
7457     {
7458       std::cout << "Syntax error at " << anArg << ".\n";
7459       return 1;
7460     }
7461   }
7462
7463   if (!toPlay && aRecFile.IsEmpty())
7464   {
7465     return 0;
7466   }
7467
7468   // Start animation timeline and process frame updating.
7469   TheIsAnimating = Standard_True;
7470   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7471   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7472   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7473   if (isFreeCamera)
7474   {
7475     aView->Camera()->Copy (aCameraBack);
7476   }
7477
7478   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7479   if (aRecParams.FpsNum <= 0)
7480   {
7481     while (!anAnimation->IsStopped())
7482     {
7483       aCameraBack->Copy (aView->Camera());
7484       const Standard_Real aPts = anAnimation->UpdateTimer();
7485       if (isFreeCamera)
7486       {
7487         aView->Camera()->Copy (aCameraBack);
7488       }
7489
7490       if (aPts >= anUpperPts)
7491       {
7492         anAnimation->Pause();
7493         break;
7494       }
7495
7496       if (aView->IsInvalidated())
7497       {
7498         aView->Redraw();
7499       }
7500       else
7501       {
7502         aView->RedrawImmediate();
7503       }
7504
7505       if (!isLockLoop)
7506       {
7507         // handle user events
7508         theDI.Eval ("after 1 set waiter 1");
7509         theDI.Eval ("vwait waiter");
7510       }
7511       if (!TheIsAnimating)
7512       {
7513         anAnimation->Pause();
7514         theDI << aPts;
7515         break;
7516       }
7517     }
7518
7519     if (aView->IsInvalidated())
7520     {
7521       aView->Redraw();
7522     }
7523     else
7524     {
7525       aView->RedrawImmediate();
7526     }
7527   }
7528   else
7529   {
7530     OSD_Timer aPerfTimer;
7531     aPerfTimer.Start();
7532
7533     Handle(Image_VideoRecorder) aRecorder;
7534     ImageFlipper aFlipper;
7535     Handle(Draw_ProgressIndicator) aProgress;
7536     if (!aRecFile.IsEmpty())
7537     {
7538       if (aRecParams.Width  <= 0
7539        || aRecParams.Height <= 0)
7540       {
7541         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7542       }
7543
7544       aRecorder = new Image_VideoRecorder();
7545       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7546       {
7547         std::cout << "Error: failed to open video file for recording\n";
7548         return 0;
7549       }
7550
7551       aProgress = new Draw_ProgressIndicator (theDI, 1);
7552     }
7553
7554     // Manage frame-rated animation here
7555     Standard_Real aPts = aPlayStartTime;
7556     int64_t aNbFrames = 0;
7557     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7558     Standard_Integer aSecondsProgress = 0;
7559     for (; aPts <= anUpperPts && aPSentry.More();)
7560     {
7561       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
7562       aPts = aPlayStartTime + aRecPts;
7563       ++aNbFrames;
7564       if (!anAnimation->Update (aPts))
7565       {
7566         break;
7567       }
7568
7569       if (!aRecorder.IsNull())
7570       {
7571         V3d_ImageDumpOptions aDumpParams;
7572         aDumpParams.Width          = aRecParams.Width;
7573         aDumpParams.Height         = aRecParams.Height;
7574         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
7575         aDumpParams.StereoOptions  = V3d_SDO_MONO;
7576         aDumpParams.ToAdjustAspect = Standard_True;
7577         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
7578         {
7579           std::cout << "Error: view dump is failed!\n";
7580           return 0;
7581         }
7582         aFlipper.FlipY (aRecorder->ChangeFrame());
7583         if (!aRecorder->PushFrame())
7584         {
7585           return 0;
7586         }
7587       }
7588       else
7589       {
7590         aView->Redraw();
7591       }
7592
7593       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7594       {
7595         aPSentry.Next();
7596         ++aSecondsProgress;
7597       }
7598     }
7599
7600     aPerfTimer.Stop();
7601     anAnimation->Stop();
7602     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7603     theDI << "Average FPS: " << aRecFps << "\n"
7604           << "Nb. Frames: "  << Standard_Real(aNbFrames);
7605
7606     aView->Redraw();
7607   }
7608
7609   aView->SetImmediateUpdate (wasImmediateUpdate);
7610   TheIsAnimating = Standard_False;
7611   return 0;
7612 }
7613
7614
7615 //=======================================================================
7616 //function : VChangeSelected
7617 //purpose  : Adds the shape to selection or remove one from it
7618 //=======================================================================
7619 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7620                                 Standard_Integer argc,
7621                                 const char ** argv)
7622 {
7623   if(argc != 2)
7624   {
7625     di<<"Usage : " << argv[0] << " shape \n";
7626     return 1;
7627   }
7628   //get AIS_Shape:
7629   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7630   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
7631   TCollection_AsciiString aName(argv[1]);
7632   Handle(AIS_InteractiveObject) anAISObject;
7633
7634   if(!aMap.IsBound2(aName))
7635   {
7636     di<<"Use 'vdisplay' before";
7637     return 1;
7638   }
7639   else
7640   {
7641     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
7642     if(anAISObject.IsNull()){
7643       di<<"No interactive object \n";
7644       return 1;
7645     }
7646
7647     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
7648   }
7649   return 0;
7650 }
7651
7652 //=======================================================================
7653 //function : VNbSelected
7654 //purpose  : Returns number of selected objects
7655 //=======================================================================
7656 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7657                                 Standard_Integer argc,
7658                                 const char ** argv)
7659 {
7660   if(argc != 1)
7661   {
7662     di << "Usage : " << argv[0] << "\n";
7663     return 1;
7664   }
7665   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7666   if(aContext.IsNull())
7667   {
7668     di << "use 'vinit' command before " << argv[0] << "\n";
7669     return 1;
7670   }
7671   di << aContext->NbSelected() << "\n";
7672   return 0;
7673 }
7674
7675 //=======================================================================
7676 //function : VPurgeDisplay
7677 //purpose  : Switches altialiasing on or off
7678 //=======================================================================
7679 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7680                                 Standard_Integer argc,
7681                                 const char ** argv)
7682 {
7683   if (argc > 1)
7684   {
7685     di << "Usage : " << argv[0] << "\n";
7686     return 1;
7687   }
7688   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7689   if (aContext.IsNull())
7690   {
7691     di << "use 'vinit' command before " << argv[0] << "\n";
7692     return 1;
7693   }
7694
7695   di << aContext->PurgeDisplay() << "\n";
7696   return 0;
7697 }
7698
7699 //=======================================================================
7700 //function : VSetViewSize
7701 //purpose  :
7702 //=======================================================================
7703 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7704                                 Standard_Integer argc,
7705                                 const char ** argv)
7706 {
7707   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7708   if(aContext.IsNull())
7709   {
7710     di << "use 'vinit' command before " << argv[0] << "\n";
7711     return 1;
7712   }
7713   if(argc != 2)
7714   {
7715     di<<"Usage : " << argv[0] << " Size\n";
7716     return 1;
7717   }
7718   Standard_Real aSize = Draw::Atof (argv[1]);
7719   if (aSize <= 0.)
7720   {
7721     di<<"Bad Size value  : " << aSize << "\n";
7722     return 1;
7723   }
7724
7725   Handle(V3d_View) aView = ViewerTest::CurrentView();
7726   aView->SetSize(aSize);
7727   return 0;
7728 }
7729
7730 //=======================================================================
7731 //function : VMoveView
7732 //purpose  :
7733 //=======================================================================
7734 static Standard_Integer VMoveView (Draw_Interpretor& di,
7735                                 Standard_Integer argc,
7736                                 const char ** argv)
7737 {
7738   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7739   if(aContext.IsNull())
7740   {
7741     di << "use 'vinit' command before " << argv[0] << "\n";
7742     return 1;
7743   }
7744   if(argc < 4 || argc > 5)
7745   {
7746     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7747     return 1;
7748   }
7749   Standard_Real Dx = Draw::Atof (argv[1]);
7750   Standard_Real Dy = Draw::Atof (argv[2]);
7751   Standard_Real Dz = Draw::Atof (argv[3]);
7752   Standard_Boolean aStart = Standard_True;
7753   if (argc == 5)
7754   {
7755       aStart = (Draw::Atoi (argv[4]) > 0);
7756   }
7757
7758   Handle(V3d_View) aView = ViewerTest::CurrentView();
7759   aView->Move(Dx,Dy,Dz,aStart);
7760   return 0;
7761 }
7762
7763 //=======================================================================
7764 //function : VTranslateView
7765 //purpose  :
7766 //=======================================================================
7767 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7768                                 Standard_Integer argc,
7769                                 const char ** argv)
7770 {
7771   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7772   if(aContext.IsNull())
7773   {
7774     di << "use 'vinit' command before " << argv[0] << "\n";
7775     return 1;
7776   }
7777   if(argc < 4 || argc > 5)
7778   {
7779     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7780     return 1;
7781   }
7782   Standard_Real Dx = Draw::Atof (argv[1]);
7783   Standard_Real Dy = Draw::Atof (argv[2]);
7784   Standard_Real Dz = Draw::Atof (argv[3]);
7785   Standard_Boolean aStart = Standard_True;
7786   if (argc == 5)
7787   {
7788       aStart = (Draw::Atoi (argv[4]) > 0);
7789   }
7790
7791   Handle(V3d_View) aView = ViewerTest::CurrentView();
7792   aView->Translate(Dx,Dy,Dz,aStart);
7793   return 0;
7794 }
7795
7796 //=======================================================================
7797 //function : VTurnView
7798 //purpose  :
7799 //=======================================================================
7800 static Standard_Integer VTurnView (Draw_Interpretor& di,
7801                                 Standard_Integer argc,
7802                                 const char ** argv)
7803 {
7804   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7805   if(aContext.IsNull()) {
7806     di << "use 'vinit' command before " << argv[0] << "\n";
7807     return 1;
7808   }
7809   if(argc < 4 || argc > 5){
7810     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7811     return 1;
7812   }
7813   Standard_Real Ax = Draw::Atof (argv[1]);
7814   Standard_Real Ay = Draw::Atof (argv[2]);
7815   Standard_Real Az = Draw::Atof (argv[3]);
7816   Standard_Boolean aStart = Standard_True;
7817   if (argc == 5)
7818   {
7819       aStart = (Draw::Atoi (argv[4]) > 0);
7820   }
7821
7822   Handle(V3d_View) aView = ViewerTest::CurrentView();
7823   aView->Turn(Ax,Ay,Az,aStart);
7824   return 0;
7825 }
7826
7827 //==============================================================================
7828 //function : VTextureEnv
7829 //purpose  : ENables or disables environment mapping
7830 //==============================================================================
7831 class OCC_TextureEnv : public Graphic3d_TextureEnv
7832 {
7833 public:
7834   OCC_TextureEnv(const Standard_CString FileName);
7835   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7836   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7837                             const Standard_Boolean theModulateFlag,
7838                             const Graphic3d_TypeOfTextureFilter theFilter,
7839                             const Standard_ShortReal theXScale,
7840                             const Standard_ShortReal theYScale,
7841                             const Standard_ShortReal theXShift,
7842                             const Standard_ShortReal theYShift,
7843                             const Standard_ShortReal theAngle);
7844   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7845 };
7846 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7847
7848 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7849   : Graphic3d_TextureEnv(theFileName)
7850 {
7851 }
7852
7853 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7854   : Graphic3d_TextureEnv(theTexId)
7855 {
7856 }
7857
7858 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7859                                           const Standard_Boolean theModulateFlag,
7860                                           const Graphic3d_TypeOfTextureFilter theFilter,
7861                                           const Standard_ShortReal theXScale,
7862                                           const Standard_ShortReal theYScale,
7863                                           const Standard_ShortReal theXShift,
7864                                           const Standard_ShortReal theYShift,
7865                                           const Standard_ShortReal theAngle)
7866 {
7867   myParams->SetRepeat     (theRepeatFlag);
7868   myParams->SetModulate   (theModulateFlag);
7869   myParams->SetFilter     (theFilter);
7870   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7871   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7872   myParams->SetRotation   (theAngle);
7873 }
7874
7875 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7876 {
7877   // get the active view
7878   Handle(V3d_View) aView = ViewerTest::CurrentView();
7879   if (aView.IsNull())
7880   {
7881     std::cerr << "No active view. Please call vinit.\n";
7882     return 1;
7883   }
7884
7885   // Checking the input arguments
7886   Standard_Boolean anEnableFlag = Standard_False;
7887   Standard_Boolean isOk         = theArgNb >= 2;
7888   if (isOk)
7889   {
7890     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7891     anEnableFlag = anEnableOpt.IsEqual("on");
7892     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7893   }
7894   if (anEnableFlag)
7895   {
7896     isOk = (theArgNb == 3 || theArgNb == 11);
7897     if (isOk)
7898     {
7899       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7900       isOk = (!aTextureOpt.IsIntegerValue() ||
7901              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7902
7903       if (isOk && theArgNb == 11)
7904       {
7905         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7906                                 aModulateOpt(theArgVec[4]),
7907                                 aFilterOpt  (theArgVec[5]),
7908                                 aSScaleOpt  (theArgVec[6]),
7909                                 aTScaleOpt  (theArgVec[7]),
7910                                 aSTransOpt  (theArgVec[8]),
7911                                 aTTransOpt  (theArgVec[9]),
7912                                 anAngleOpt  (theArgVec[10]);
7913         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7914                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7915                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7916                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7917                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7918                 anAngleOpt.IsRealValue());
7919       }
7920     }
7921   }
7922
7923   if (!isOk)
7924   {
7925     std::cerr << "Usage :" << std::endl;
7926     std::cerr << theArgVec[0] << " off" << std::endl;
7927     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;
7928     return 1;
7929   }
7930
7931   if (anEnableFlag)
7932   {
7933     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7934     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7935                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7936                                      new OCC_TextureEnv(theArgVec[2]);
7937
7938     if (theArgNb == 11)
7939     {
7940       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7941       aTexEnv->SetTextureParameters(
7942         aRepeatOpt.  IsEqual("repeat"),
7943         aModulateOpt.IsEqual("modulate"),
7944         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7945                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7946                                                                            Graphic3d_TOTF_TRILINEAR,
7947         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7948         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7949         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7950         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7951         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7952         );
7953     }
7954     aView->SetTextureEnv(aTexEnv);
7955   }
7956   else // Disabling environment mapping
7957   {
7958     Handle(Graphic3d_TextureEnv) aTexture;
7959     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7960   }
7961
7962   aView->Redraw();
7963   return 0;
7964 }
7965
7966 namespace
7967 {
7968   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7969
7970   //! Remove registered clipping plane from all views and objects.
7971   static void removePlane (MapOfPlanes& theRegPlanes,
7972                            const TCollection_AsciiString& theName)
7973   {
7974     Handle(Graphic3d_ClipPlane) aClipPlane;
7975     if (!theRegPlanes.Find (theName, aClipPlane))
7976     {
7977       std::cout << "Warning: no such plane.\n";
7978       return;
7979     }
7980
7981     theRegPlanes.UnBind (theName);
7982     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7983          anIObjIt.More(); anIObjIt.Next())
7984     {
7985       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7986       aPrs->RemoveClipPlane (aClipPlane);
7987     }
7988
7989     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
7990          aViewIt.More(); aViewIt.Next())
7991     {
7992       const Handle(V3d_View)& aView = aViewIt.Key2();
7993       aView->RemoveClipPlane(aClipPlane);
7994     }
7995
7996     ViewerTest::RedrawAllViews();
7997   }
7998 }
7999
8000 //===============================================================================================
8001 //function : VClipPlane
8002 //purpose  :
8003 //===============================================================================================
8004 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8005 {
8006   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8007   static MapOfPlanes aRegPlanes;
8008
8009   if (theArgsNb < 2)
8010   {
8011     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8012     {
8013       theDi << aPlaneIter.Key() << " ";
8014     }
8015     return 0;
8016   }
8017
8018   TCollection_AsciiString aCommand (theArgVec[1]);
8019   aCommand.LowerCase();
8020   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8021   if (anActiveView.IsNull())
8022   {
8023     std::cout << "Error: no active view.\n";
8024     return 1;
8025   }
8026
8027   // print maximum number of planes for current viewer
8028   if (aCommand == "-maxplanes"
8029    || aCommand == "maxplanes")
8030   {
8031     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8032           << " plane slots provided by driver.\n";
8033     return 0;
8034   }
8035
8036   // create / delete plane instance
8037   if (aCommand == "-create"
8038    || aCommand == "create"
8039    || aCommand == "-delete"
8040    || aCommand == "delete"
8041    || aCommand == "-clone"
8042    || aCommand == "clone")
8043   {
8044     if (theArgsNb < 3)
8045     {
8046       std::cout << "Syntax error: plane name is required.\n";
8047       return 1;
8048     }
8049
8050     Standard_Boolean toCreate = aCommand == "-create"
8051                              || aCommand == "create";
8052     Standard_Boolean toClone  = aCommand == "-clone"
8053                              || aCommand == "clone";
8054     Standard_Boolean toDelete = aCommand == "-delete"
8055                              || aCommand == "delete";
8056     TCollection_AsciiString aPlane (theArgVec[2]);
8057
8058     if (toCreate)
8059     {
8060       if (aRegPlanes.IsBound (aPlane))
8061       {
8062         std::cout << "Warning: existing plane has been overridden.\n";
8063         toDelete = true;
8064       }
8065       else
8066       {
8067         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8068         return 0;
8069       }
8070     }
8071     else if (toClone) // toClone
8072     {
8073       if (!aRegPlanes.IsBound (aPlane))
8074       {
8075         std::cout << "Error: no such plane.\n";
8076         return 1;
8077       }
8078       else if (theArgsNb < 4)
8079       {
8080         std::cout << "Syntax error: enter name for new plane.\n";
8081         return 1;
8082       }
8083
8084       TCollection_AsciiString aClone (theArgVec[3]);
8085       if (aRegPlanes.IsBound (aClone))
8086       {
8087         std::cout << "Error: plane name is in use.\n";
8088         return 1;
8089       }
8090
8091       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8092
8093       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8094       return 0;
8095     }
8096
8097     if (toDelete)
8098     {
8099       if (aPlane == "ALL"
8100        || aPlane == "all"
8101        || aPlane == "*")
8102       {
8103         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8104         {
8105           aPlane = aPlaneIter.Key();
8106           removePlane (aRegPlanes, aPlane);
8107           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8108         }
8109       }
8110       else
8111       {
8112         removePlane (aRegPlanes, aPlane);
8113       }
8114     }
8115
8116     if (toCreate)
8117     {
8118       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8119     }
8120     return 0;
8121   }
8122
8123   // set / unset plane command
8124   if (aCommand == "set"
8125    || aCommand == "unset")
8126   {
8127     if (theArgsNb < 5)
8128     {
8129       std::cout << "Syntax error: need more arguments.\n";
8130       return 1;
8131     }
8132
8133     // redirect to new syntax
8134     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8135     anArgVec.SetValue (1, theArgVec[0]);
8136     anArgVec.SetValue (2, theArgVec[2]);
8137     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8138     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8139     {
8140       anArgVec.SetValue (anIt, theArgVec[anIt]);
8141     }
8142
8143     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8144   }
8145
8146   // change plane command
8147   TCollection_AsciiString aPlaneName;
8148   Handle(Graphic3d_ClipPlane) aClipPlane;
8149   Standard_Integer anArgIter = 0;
8150   if (aCommand == "-change"
8151    || aCommand == "change")
8152   {
8153     // old syntax support
8154     if (theArgsNb < 3)
8155     {
8156       std::cout << "Syntax error: need more arguments.\n";
8157       return 1;
8158     }
8159
8160     anArgIter  = 3;
8161     aPlaneName = theArgVec[2];
8162     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8163     {
8164       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8165       return 1;
8166     }
8167   }
8168   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8169   {
8170     anArgIter  = 2;
8171     aPlaneName = theArgVec[1];
8172   }
8173   else
8174   {
8175     anArgIter  = 2;
8176     aPlaneName = theArgVec[1];
8177     aClipPlane = new Graphic3d_ClipPlane();
8178     aRegPlanes.Bind (aPlaneName, aClipPlane);
8179     theDi << "Created new plane " << aPlaneName << ".\n";
8180   }
8181
8182   if (theArgsNb - anArgIter < 1)
8183   {
8184     std::cout << "Syntax error: need more arguments.\n";
8185     return 1;
8186   }
8187
8188   for (; anArgIter < theArgsNb; ++anArgIter)
8189   {
8190     const char**     aChangeArgs   = theArgVec + anArgIter;
8191     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8192     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8193     aChangeArg.LowerCase();
8194
8195     Standard_Boolean toEnable = Standard_True;
8196     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8197     {
8198       aClipPlane->SetOn (toEnable);
8199     }
8200     else if (aChangeArg == "-equation"
8201           || aChangeArg == "equation")
8202     {
8203       if (aNbChangeArgs < 5)
8204       {
8205         std::cout << "Syntax error: need more arguments.\n";
8206         return 1;
8207       }
8208
8209       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
8210       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
8211       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
8212       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
8213       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8214       anArgIter += 4;
8215     }
8216     else if (aChangeArg == "-capping"
8217           || aChangeArg == "capping")
8218     {
8219       if (aNbChangeArgs < 2)
8220       {
8221         std::cout << "Syntax error: need more arguments.\n";
8222         return 1;
8223       }
8224
8225       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8226       {
8227         aClipPlane->SetCapping (toEnable);
8228         anArgIter += 1;
8229       }
8230       else
8231       {
8232         // just skip otherwise (old syntax)
8233       }
8234     }
8235     else if (aChangeArg == "-useobjectmaterial"
8236           || aChangeArg == "-useobjectmat"
8237           || aChangeArg == "-useobjmat"
8238           || aChangeArg == "-useobjmaterial")
8239     {
8240       if (aNbChangeArgs < 2)
8241       {
8242         std::cout << "Syntax error: need more arguments.\n";
8243         return 1;
8244       }
8245
8246       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8247       {
8248         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8249         anArgIter += 1;
8250       }
8251     }
8252     else if (aChangeArg == "-useobjecttexture"
8253           || aChangeArg == "-useobjecttex"
8254           || aChangeArg == "-useobjtexture"
8255           || aChangeArg == "-useobjtex")
8256     {
8257       if (aNbChangeArgs < 2)
8258       {
8259         std::cout << "Syntax error: need more arguments.\n";
8260         return 1;
8261       }
8262
8263       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8264       {
8265         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8266         anArgIter += 1;
8267       }
8268     }
8269     else if (aChangeArg == "-useobjectshader"
8270           || aChangeArg == "-useobjshader")
8271     {
8272       if (aNbChangeArgs < 2)
8273       {
8274         std::cout << "Syntax error: need more arguments.\n";
8275         return 1;
8276       }
8277
8278       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8279       {
8280         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8281         anArgIter += 1;
8282       }
8283     }
8284     else if (aChangeArg == "-color"
8285           || aChangeArg == "color")
8286     {
8287       Quantity_Color aColor;
8288       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8289                                                            aChangeArgs + 1,
8290                                                            aColor);
8291       if (aNbParsed == 0)
8292       {
8293         std::cout << "Syntax error: need more arguments.\n";
8294         return 1;
8295       }
8296
8297       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8298       aMat.SetAmbientColor (aColor);
8299       aMat.SetDiffuseColor (aColor);
8300       aClipPlane->SetCappingMaterial (aMat);
8301       anArgIter += aNbParsed;
8302     }
8303     else if (aChangeArg == "-texname"
8304           || aChangeArg == "texname")
8305     {
8306       if (aNbChangeArgs < 2)
8307       {
8308         std::cout << "Syntax error: need more arguments.\n";
8309         return 1;
8310       }
8311
8312       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8313       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8314       if (!aTexture->IsDone())
8315       {
8316         aClipPlane->SetCappingTexture (NULL);
8317       }
8318       else
8319       {
8320         aTexture->EnableModulate();
8321         aTexture->EnableRepeat();
8322         aClipPlane->SetCappingTexture (aTexture);
8323       }
8324       anArgIter += 1;
8325     }
8326     else if (aChangeArg == "-texscale"
8327           || aChangeArg == "texscale")
8328     {
8329       if (aClipPlane->CappingTexture().IsNull())
8330       {
8331         std::cout << "Error: no texture is set.\n";
8332         return 1;
8333       }
8334
8335       if (aNbChangeArgs < 3)
8336       {
8337         std::cout << "Syntax error: need more arguments.\n";
8338         return 1;
8339       }
8340
8341       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8342       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8343       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8344       anArgIter += 2;
8345     }
8346     else if (aChangeArg == "-texorigin"
8347           || aChangeArg == "texorigin") // texture origin
8348     {
8349       if (aClipPlane->CappingTexture().IsNull())
8350       {
8351         std::cout << "Error: no texture is set.\n";
8352         return 1;
8353       }
8354
8355       if (aNbChangeArgs < 3)
8356       {
8357         std::cout << "Syntax error: need more arguments.\n";
8358         return 1;
8359       }
8360
8361       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8362       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8363
8364       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8365       anArgIter += 2;
8366     }
8367     else if (aChangeArg == "-texrotate"
8368           || aChangeArg == "texrotate") // texture rotation
8369     {
8370       if (aClipPlane->CappingTexture().IsNull())
8371       {
8372         std::cout << "Error: no texture is set.\n";
8373         return 1;
8374       }
8375
8376       if (aNbChangeArgs < 2)
8377       {
8378         std::cout << "Syntax error: need more arguments.\n";
8379         return 1;
8380       }
8381
8382       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8383       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8384       anArgIter += 1;
8385     }
8386     else if (aChangeArg == "-hatch"
8387           || aChangeArg == "hatch")
8388     {
8389       if (aNbChangeArgs < 2)
8390       {
8391         std::cout << "Syntax error: need more arguments.\n";
8392         return 1;
8393       }
8394
8395       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8396       aHatchStr.LowerCase();
8397       if (aHatchStr == "on")
8398       {
8399         aClipPlane->SetCappingHatchOn();
8400       }
8401       else if (aHatchStr == "off")
8402       {
8403         aClipPlane->SetCappingHatchOff();
8404       }
8405       else
8406       {
8407         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8408       }
8409       anArgIter += 1;
8410     }
8411     else if (aChangeArg == "-delete"
8412           || aChangeArg == "delete")
8413     {
8414       removePlane (aRegPlanes, aPlaneName);
8415       return 0;
8416     }
8417     else if (aChangeArg == "-set"
8418           || aChangeArg == "-unset")
8419     {
8420       // set / unset plane command
8421       Standard_Boolean toSet = aChangeArg == "-set";
8422       Standard_Integer anIt = 1;
8423       for (; anIt < aNbChangeArgs; ++anIt)
8424       {
8425         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8426         if (anEntityName.IsEmpty()
8427          || anEntityName.Value (1) == '-')
8428         {
8429           break;
8430         }
8431         else if (ViewerTest_myViews.IsBound1 (anEntityName))
8432         {
8433           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8434           if (toSet)
8435           {
8436             aView->AddClipPlane (aClipPlane);
8437           }
8438           else
8439           {
8440             aView->RemoveClipPlane (aClipPlane);
8441           }
8442           continue;
8443         }
8444         else if (GetMapOfAIS().IsBound2 (anEntityName))
8445         {
8446           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
8447           if (toSet)
8448           {
8449             aIObj->AddClipPlane (aClipPlane);
8450           }
8451           else
8452           {
8453             aIObj->RemoveClipPlane (aClipPlane);
8454           }
8455         }
8456         else
8457         {
8458           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
8459           return 1;
8460         }
8461       }
8462
8463       if (anIt == 1)
8464       {
8465         // apply to active view
8466         if (toSet)
8467         {
8468           anActiveView->AddClipPlane (aClipPlane);
8469         }
8470         else
8471         {
8472           anActiveView->RemoveClipPlane (aClipPlane);
8473         }
8474       }
8475       else
8476       {
8477         anArgIter = anArgIter + anIt - 1;
8478       }
8479     }
8480     else
8481     {
8482       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8483       return 1;
8484     }
8485   }
8486
8487   ViewerTest::RedrawAllViews();
8488   return 0;
8489 }
8490
8491 //===============================================================================================
8492 //function : VZRange
8493 //purpose  :
8494 //===============================================================================================
8495 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8496 {
8497   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8498
8499   if (aCurrentView.IsNull())
8500   {
8501     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8502     return 1;
8503   }
8504
8505   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
8506
8507   if (theArgsNb < 2)
8508   {
8509     theDi << "ZNear: " << aCamera->ZNear() << "\n";
8510     theDi << "ZFar: " << aCamera->ZFar() << "\n";
8511     return 0;
8512   }
8513
8514   if (theArgsNb == 3)
8515   {
8516     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8517     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
8518
8519     if (aNewZNear >= aNewZFar)
8520     {
8521       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
8522       return 1;
8523     }
8524
8525     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8526     {
8527       std::cout << theArgVec[0] << ": invalid arguments: ";
8528       std::cout << "znear, zfar should be positive for perspective camera.\n";
8529       return 1;
8530     }
8531
8532     aCamera->SetZRange (aNewZNear, aNewZFar);
8533   }
8534   else
8535   {
8536     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8537     return 1;
8538   }
8539
8540   aCurrentView->Redraw();
8541
8542   return 0;
8543 }
8544
8545 //===============================================================================================
8546 //function : VAutoZFit
8547 //purpose  :
8548 //===============================================================================================
8549 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8550 {
8551   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8552
8553   if (aCurrentView.IsNull())
8554   {
8555     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8556     return 1;
8557   }
8558
8559   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
8560
8561   if (theArgsNb > 3)
8562   {
8563     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8564     return 1;
8565   }
8566
8567   if (theArgsNb < 2)
8568   {
8569     theDi << "Auto z-fit mode: \n"
8570           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
8571           << "Scale: " << aScale << "\n";
8572     return 0;
8573   }
8574
8575   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
8576
8577   if (theArgsNb >= 3)
8578   {
8579     aScale = Draw::Atoi (theArgVec[2]);
8580   }
8581
8582   aCurrentView->SetAutoZFitMode (isOn, aScale);
8583   aCurrentView->AutoZFit();
8584   aCurrentView->Redraw();
8585
8586   return 0;
8587 }
8588
8589 //! Auxiliary function to print projection type
8590 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
8591 {
8592   switch (theProjType)
8593   {
8594     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
8595     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
8596     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
8597     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
8598     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
8599   }
8600   return "UNKNOWN";
8601 }
8602
8603 //===============================================================================================
8604 //function : VCamera
8605 //purpose  :
8606 //===============================================================================================
8607 static int VCamera (Draw_Interpretor& theDI,
8608                     Standard_Integer  theArgsNb,
8609                     const char**      theArgVec)
8610 {
8611   Handle(V3d_View) aView = ViewerTest::CurrentView();
8612   if (aView.IsNull())
8613   {
8614     std::cout << "Error: no active view.\n";
8615     return 1;
8616   }
8617
8618   Handle(Graphic3d_Camera) aCamera = aView->Camera();
8619   if (theArgsNb < 2)
8620   {
8621     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
8622     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
8623     theDI << "Distance:   " << aCamera->Distance() << "\n";
8624     theDI << "IOD:        " << aCamera->IOD() << "\n";
8625     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
8626     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
8627     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
8628     return 0;
8629   }
8630
8631   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8632   {
8633     Standard_CString        anArg = theArgVec[anArgIter];
8634     TCollection_AsciiString anArgCase (anArg);
8635     anArgCase.LowerCase();
8636     if (anArgCase == "-proj"
8637      || anArgCase == "-projection"
8638      || anArgCase == "-projtype"
8639      || anArgCase == "-projectiontype")
8640     {
8641       theDI << projTypeName (aCamera->ProjectionType()) << " ";
8642     }
8643     else if (anArgCase == "-ortho"
8644           || anArgCase == "-orthographic")
8645     {
8646       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8647     }
8648     else if (anArgCase == "-persp"
8649           || anArgCase == "-perspective"
8650           || anArgCase == "-perspmono"
8651           || anArgCase == "-perspectivemono"
8652           || anArgCase == "-mono")
8653     {
8654       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8655     }
8656     else if (anArgCase == "-stereo"
8657           || anArgCase == "-stereoscopic"
8658           || anArgCase == "-perspstereo"
8659           || anArgCase == "-perspectivestereo")
8660     {
8661       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8662     }
8663     else if (anArgCase == "-left"
8664           || anArgCase == "-lefteye"
8665           || anArgCase == "-monoleft"
8666           || anArgCase == "-monolefteye"
8667           || anArgCase == "-perpsleft"
8668           || anArgCase == "-perpslefteye")
8669     {
8670       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8671     }
8672     else if (anArgCase == "-right"
8673           || anArgCase == "-righteye"
8674           || anArgCase == "-monoright"
8675           || anArgCase == "-monorighteye"
8676           || anArgCase == "-perpsright")
8677     {
8678       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8679     }
8680     else if (anArgCase == "-dist"
8681           || anArgCase == "-distance")
8682     {
8683       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8684       if (anArgValue != NULL
8685       && *anArgValue != '-')
8686       {
8687         ++anArgIter;
8688         aCamera->SetDistance (Draw::Atof (anArgValue));
8689         continue;
8690       }
8691       theDI << aCamera->Distance() << " ";
8692     }
8693     else if (anArgCase == "-iod")
8694     {
8695       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8696       if (anArgValue != NULL
8697       && *anArgValue != '-')
8698       {
8699         ++anArgIter;
8700         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8701         continue;
8702       }
8703       theDI << aCamera->IOD() << " ";
8704     }
8705     else if (anArgCase == "-iodtype")
8706     {
8707       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8708       TCollection_AsciiString anValueCase (anArgValue);
8709       anValueCase.LowerCase();
8710       if (anValueCase == "abs"
8711        || anValueCase == "absolute")
8712       {
8713         ++anArgIter;
8714         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8715         continue;
8716       }
8717       else if (anValueCase == "rel"
8718             || anValueCase == "relative")
8719       {
8720         ++anArgIter;
8721         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8722         continue;
8723       }
8724       else if (*anArgValue != '-')
8725       {
8726         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8727         return 1;
8728       }
8729       switch (aCamera->GetIODType())
8730       {
8731         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8732         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8733       }
8734     }
8735     else if (anArgCase == "-zfocus")
8736     {
8737       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8738       if (anArgValue != NULL
8739       && *anArgValue != '-')
8740       {
8741         ++anArgIter;
8742         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8743         continue;
8744       }
8745       theDI << aCamera->ZFocus() << " ";
8746     }
8747     else if (anArgCase == "-zfocustype")
8748     {
8749       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8750       TCollection_AsciiString anValueCase (anArgValue);
8751       anValueCase.LowerCase();
8752       if (anValueCase == "abs"
8753        || anValueCase == "absolute")
8754       {
8755         ++anArgIter;
8756         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8757         continue;
8758       }
8759       else if (anValueCase == "rel"
8760             || anValueCase == "relative")
8761       {
8762         ++anArgIter;
8763         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8764         continue;
8765       }
8766       else if (*anArgValue != '-')
8767       {
8768         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8769         return 1;
8770       }
8771       switch (aCamera->ZFocusType())
8772       {
8773         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8774         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8775       }
8776     }
8777     else if (anArgCase == "-fov"
8778           || anArgCase == "-fovy")
8779     {
8780       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8781       if (anArgValue != NULL
8782       && *anArgValue != '-')
8783       {
8784         ++anArgIter;
8785         aCamera->SetFOVy (Draw::Atof (anArgValue));
8786         continue;
8787       }
8788       theDI << aCamera->FOVy() << " ";
8789     }
8790     else
8791     {
8792       std::cout << "Error: unknown argument '" << anArg << "'\n";
8793       return 1;
8794     }
8795   }
8796
8797   aView->AutoZFit();
8798   aView->Redraw();
8799
8800   return 0;
8801 }
8802
8803 //! Parse stereo output mode
8804 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8805                                          Graphic3d_StereoMode& theMode)
8806 {
8807   TCollection_AsciiString aFlag (theArg);
8808   aFlag.LowerCase();
8809   if (aFlag == "quadbuffer")
8810   {
8811     theMode = Graphic3d_StereoMode_QuadBuffer;
8812   }
8813   else if (aFlag == "anaglyph")
8814   {
8815     theMode = Graphic3d_StereoMode_Anaglyph;
8816   }
8817   else if (aFlag == "row"
8818         || aFlag == "rowinterlaced")
8819   {
8820     theMode = Graphic3d_StereoMode_RowInterlaced;
8821   }
8822   else if (aFlag == "col"
8823         || aFlag == "colinterlaced"
8824         || aFlag == "columninterlaced")
8825   {
8826     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8827   }
8828   else if (aFlag == "chess"
8829         || aFlag == "chessboard")
8830   {
8831     theMode = Graphic3d_StereoMode_ChessBoard;
8832   }
8833   else if (aFlag == "sbs"
8834         || aFlag == "sidebyside")
8835   {
8836     theMode = Graphic3d_StereoMode_SideBySide;
8837   }
8838   else if (aFlag == "ou"
8839         || aFlag == "overunder")
8840   {
8841     theMode = Graphic3d_StereoMode_OverUnder;
8842   }
8843   else if (aFlag == "pageflip"
8844         || aFlag == "softpageflip")
8845   {
8846     theMode = Graphic3d_StereoMode_SoftPageFlip;
8847   }
8848   else
8849   {
8850     return Standard_False;
8851   }
8852   return Standard_True;
8853 }
8854
8855 //! Parse anaglyph filter
8856 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8857                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8858 {
8859   TCollection_AsciiString aFlag (theArg);
8860   aFlag.LowerCase();
8861   if (aFlag == "redcyansimple")
8862   {
8863     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8864   }
8865   else if (aFlag == "redcyan"
8866         || aFlag == "redcyanoptimized")
8867   {
8868     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8869   }
8870   else if (aFlag == "yellowbluesimple")
8871   {
8872     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8873   }
8874   else if (aFlag == "yellowblue"
8875         || aFlag == "yellowblueoptimized")
8876   {
8877     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8878   }
8879   else if (aFlag == "greenmagenta"
8880         || aFlag == "greenmagentasimple")
8881   {
8882     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8883   }
8884   else
8885   {
8886     return Standard_False;
8887   }
8888   return Standard_True;
8889 }
8890
8891 //==============================================================================
8892 //function : VStereo
8893 //purpose  :
8894 //==============================================================================
8895
8896 static int VStereo (Draw_Interpretor& theDI,
8897                     Standard_Integer  theArgNb,
8898                     const char**      theArgVec)
8899 {
8900   Handle(V3d_View) aView = ViewerTest::CurrentView();
8901   if (theArgNb < 2)
8902   {
8903     if (aView.IsNull())
8904     {
8905       std::cout << "Error: no active viewer!\n";
8906       return 0;
8907     }
8908
8909     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8910     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8911     if (isActive)
8912     {
8913       TCollection_AsciiString aMode;
8914       switch (aView->RenderingParams().StereoMode)
8915       {
8916         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8917         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8918         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8919         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8920         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8921         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8922         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8923         case Graphic3d_StereoMode_Anaglyph  :
8924           aMode = "anaglyph";
8925           switch (aView->RenderingParams().AnaglyphFilter)
8926           {
8927             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8928             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8929             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8930             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8931             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8932             default: break;
8933           }
8934         default: break;
8935       }
8936       theDI << "Mode " << aMode << "\n";
8937     }
8938     return 0;
8939   }
8940
8941   Handle(Graphic3d_Camera) aCamera;
8942   Graphic3d_RenderingParams*   aParams   = NULL;
8943   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8944   if (!aView.IsNull())
8945   {
8946     aParams   = &aView->ChangeRenderingParams();
8947     aMode     = aParams->StereoMode;
8948     aCamera   = aView->Camera();
8949   }
8950
8951   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8952   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8953   {
8954     Standard_CString        anArg = theArgVec[anArgIter];
8955     TCollection_AsciiString aFlag (anArg);
8956     aFlag.LowerCase();
8957     if (anUpdateTool.parseRedrawMode (aFlag))
8958     {
8959       continue;
8960     }
8961     else if (aFlag == "0"
8962           || aFlag == "off")
8963     {
8964       if (++anArgIter < theArgNb)
8965       {
8966         std::cout << "Error: wrong number of arguments!\n";
8967         return 1;
8968       }
8969
8970       if (!aCamera.IsNull()
8971        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8972       {
8973         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8974       }
8975       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8976       return 0;
8977     }
8978     else if (aFlag == "1"
8979           || aFlag == "on")
8980     {
8981       if (++anArgIter < theArgNb)
8982       {
8983         std::cout << "Error: wrong number of arguments!\n";
8984         return 1;
8985       }
8986
8987       if (!aCamera.IsNull())
8988       {
8989         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8990       }
8991       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8992       return 0;
8993     }
8994     else if (aFlag == "-reverse"
8995           || aFlag == "-reversed"
8996           || aFlag == "-swap")
8997     {
8998       Standard_Boolean toEnable = Standard_True;
8999       if (++anArgIter < theArgNb
9000       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9001       {
9002         --anArgIter;
9003       }
9004       aParams->ToReverseStereo = toEnable;
9005     }
9006     else if (aFlag == "-noreverse"
9007           || aFlag == "-noswap")
9008     {
9009       Standard_Boolean toDisable = Standard_True;
9010       if (++anArgIter < theArgNb
9011       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9012       {
9013         --anArgIter;
9014       }
9015       aParams->ToReverseStereo = !toDisable;
9016     }
9017     else if (aFlag == "-mode"
9018           || aFlag == "-stereomode")
9019     {
9020       if (++anArgIter >= theArgNb
9021       || !parseStereoMode (theArgVec[anArgIter], aMode))
9022       {
9023         std::cout << "Error: syntax error at '" << anArg << "'\n";
9024         return 1;
9025       }
9026
9027       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9028       {
9029         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9030       }
9031     }
9032     else if (aFlag == "-anaglyph"
9033           || aFlag == "-anaglyphfilter")
9034     {
9035       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9036       if (++anArgIter >= theArgNb
9037       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9038       {
9039         std::cout << "Error: syntax error at '" << anArg << "'\n";
9040         return 1;
9041       }
9042
9043       aMode = Graphic3d_StereoMode_Anaglyph;
9044       aParams->AnaglyphFilter = aFilter;
9045     }
9046     else if (parseStereoMode (anArg, aMode)) // short syntax
9047     {
9048       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9049       {
9050         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9051       }
9052     }
9053     else
9054     {
9055       std::cout << "Error: syntax error at '" << anArg << "'\n";
9056       return 1;
9057     }
9058   }
9059
9060   if (!aView.IsNull())
9061   {
9062     aParams->StereoMode = aMode;
9063     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9064   }
9065   return 0;
9066 }
9067
9068 //===============================================================================================
9069 //function : VDefaults
9070 //purpose  :
9071 //===============================================================================================
9072 static int VDefaults (Draw_Interpretor& theDi,
9073                       Standard_Integer  theArgsNb,
9074                       const char**      theArgVec)
9075 {
9076   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9077   if (aCtx.IsNull())
9078   {
9079     std::cerr << "No active viewer!\n";
9080     return 1;
9081   }
9082
9083   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9084   if (theArgsNb < 2)
9085   {
9086     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9087     {
9088       theDi << "DeflType:           relative\n"
9089             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9090     }
9091     else
9092     {
9093       theDi << "DeflType:           absolute\n"
9094             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9095     }
9096     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9097     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9098     return 0;
9099   }
9100
9101   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9102   {
9103     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9104     anArg.UpperCase();
9105     if (anArg == "-ABSDEFL"
9106      || anArg == "-ABSOLUTEDEFLECTION"
9107      || anArg == "-DEFL"
9108      || anArg == "-DEFLECTION")
9109     {
9110       if (++anArgIter >= theArgsNb)
9111       {
9112         std::cout << "Error: wrong syntax at " << anArg << "\n";
9113         return 1;
9114       }
9115       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9116       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9117     }
9118     else if (anArg == "-RELDEFL"
9119           || anArg == "-RELATIVEDEFLECTION"
9120           || anArg == "-DEVCOEFF"
9121           || anArg == "-DEVIATIONCOEFF"
9122           || anArg == "-DEVIATIONCOEFFICIENT")
9123     {
9124       if (++anArgIter >= theArgsNb)
9125       {
9126         std::cout << "Error: wrong syntax at " << anArg << "\n";
9127         return 1;
9128       }
9129       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9130       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9131     }
9132     else if (anArg == "-ANGDEFL"
9133           || anArg == "-ANGULARDEFL"
9134           || anArg == "-ANGULARDEFLECTION")
9135     {
9136       if (++anArgIter >= theArgsNb)
9137       {
9138         std::cout << "Error: wrong syntax at " << anArg << "\n";
9139         return 1;
9140       }
9141       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9142       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9143     }
9144     else if (anArg == "-AUTOTR"
9145           || anArg == "-AUTOTRIANG"
9146           || anArg == "-AUTOTRIANGULATION")
9147     {
9148       if (++anArgIter >= theArgsNb)
9149       {
9150         std::cout << "Error: wrong syntax at " << anArg << "\n";
9151         return 1;
9152       }
9153       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9154       aValue.LowerCase();
9155       if (aValue == "on"
9156        || aValue == "1")
9157       {
9158         aDefParams->SetAutoTriangulation (Standard_True);
9159       }
9160       else if (aValue == "off"
9161             || aValue == "0")
9162       {
9163         aDefParams->SetAutoTriangulation (Standard_False);
9164       }
9165     }
9166     else
9167     {
9168       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9169     }
9170   }
9171
9172   return 0;
9173 }
9174
9175 //! Auxiliary method
9176 inline void addLight (const Handle(V3d_Light)& theLightNew,
9177                       const Standard_Boolean   theIsGlobal)
9178 {
9179   if (theLightNew.IsNull())
9180   {
9181     return;
9182   }
9183
9184   if (theIsGlobal)
9185   {
9186     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
9187   }
9188   else
9189   {
9190     ViewerTest::CurrentView()->SetLightOn (theLightNew);
9191   }
9192 }
9193
9194 //! Auxiliary method
9195 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9196 {
9197   TCollection_AsciiString anArgNextCase (theArgNext);
9198   anArgNextCase.UpperCase();
9199   if (anArgNextCase.Length() > 5
9200    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9201   {
9202     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9203   }
9204   else
9205   {
9206     return theArgNext.IntegerValue();
9207   }
9208 }
9209
9210 //===============================================================================================
9211 //function : VLight
9212 //purpose  :
9213 //===============================================================================================
9214 static int VLight (Draw_Interpretor& theDi,
9215                    Standard_Integer  theArgsNb,
9216                    const char**      theArgVec)
9217 {
9218   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9219   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9220   if (aView.IsNull()
9221    || aViewer.IsNull())
9222   {
9223     std::cerr << "No active viewer!\n";
9224     return 1;
9225   }
9226
9227   Standard_Real anXYZ[3]   = {};
9228   Standard_Real anAtten[2] = {};
9229   if (theArgsNb < 2)
9230   {
9231     // print lights info
9232     Standard_Integer aLightId = 0;
9233     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9234     {
9235       Handle(V3d_Light) aLight = aLightIter.Value();
9236       const Quantity_Color aColor = aLight->Color();
9237       theDi << "Light" << aLightId << "\n";
9238       switch (aLight->Type())
9239       {
9240         case V3d_AMBIENT:
9241         {
9242           theDi << "  Type:       Ambient\n";
9243           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9244           break;
9245         }
9246         case V3d_DIRECTIONAL:
9247         {
9248           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
9249           theDi << "  Type:       Directional\n";
9250           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9251           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9252           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9253           if (!aLightDir.IsNull())
9254           {
9255             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9256             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9257             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9258             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9259           }
9260           break;
9261         }
9262         case V3d_POSITIONAL:
9263         {
9264           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
9265           theDi << "  Type:       Positional\n";
9266           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9267           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9268           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9269           if (!aLightPos.IsNull())
9270           {
9271             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9272             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9273             aLightPos->Attenuation (anAtten[0], anAtten[1]);
9274             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9275           }
9276           break;
9277         }
9278         case V3d_SPOT:
9279         {
9280           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
9281           theDi << "  Type:       Spot\n";
9282           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9283           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9284           if (!aLightSpot.IsNull())
9285           {
9286             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9287             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9288             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9289             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9290             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9291             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9292             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
9293             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
9294           }
9295           break;
9296         }
9297         default:
9298         {
9299           theDi << "  Type:       UNKNOWN\n";
9300           break;
9301         }
9302       }
9303       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
9304     }
9305   }
9306
9307   Handle(V3d_Light) aLightNew;
9308   Handle(V3d_Light) aLightOld;
9309   Standard_Boolean  isGlobal = Standard_True;
9310   Standard_Boolean  toCreate = Standard_False;
9311   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9312   {
9313     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9314     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
9315     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
9316     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
9317     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
9318
9319     TCollection_AsciiString aName, aValue;
9320     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9321     TCollection_AsciiString anArgCase (anArg);
9322     anArgCase.UpperCase();
9323     if (anArgCase.IsEqual ("NEW")
9324      || anArgCase.IsEqual ("ADD")
9325      || anArgCase.IsEqual ("CREATE"))
9326     {
9327       toCreate = Standard_True;
9328     }
9329     else if (anArgCase.IsEqual ("GLOB")
9330           || anArgCase.IsEqual ("GLOBAL"))
9331     {
9332       isGlobal = Standard_True;
9333     }
9334     else if (anArgCase.IsEqual ("LOC")
9335           || anArgCase.IsEqual ("LOCAL"))
9336     {
9337       isGlobal = Standard_False;
9338     }
9339     else if (anArgCase.IsEqual ("DEF")
9340           || anArgCase.IsEqual ("DEFAULTS"))
9341     {
9342       toCreate = Standard_False;
9343       aViewer->SetDefaultLights();
9344     }
9345     else if (anArgCase.IsEqual ("CLR")
9346           || anArgCase.IsEqual ("CLEAR"))
9347     {
9348       toCreate = Standard_False;
9349       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
9350       {
9351         Handle(V3d_Light) aLight = aLightIter.Value();
9352         aViewer->DelLight (aLight);
9353         aLightIter = aView->ActiveLightIterator();
9354       }
9355     }
9356     else if (anArgCase.IsEqual ("AMB")
9357           || anArgCase.IsEqual ("AMBIENT")
9358           || anArgCase.IsEqual ("AMBLIGHT"))
9359     {
9360       addLight (aLightNew, isGlobal);
9361       if (!toCreate)
9362       {
9363         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9364         return 1;
9365       }
9366       toCreate  = Standard_False;
9367       aLightNew = new V3d_AmbientLight (aViewer);
9368     }
9369     else if (anArgCase.IsEqual ("DIRECTIONAL")
9370           || anArgCase.IsEqual ("DIRLIGHT"))
9371     {
9372       addLight (aLightNew, isGlobal);
9373       if (!toCreate)
9374       {
9375         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9376         return 1;
9377       }
9378       toCreate  = Standard_False;
9379       aLightNew = new V3d_DirectionalLight (aViewer);
9380     }
9381     else if (anArgCase.IsEqual ("SPOT")
9382           || anArgCase.IsEqual ("SPOTLIGHT"))
9383     {
9384       addLight (aLightNew, isGlobal);
9385       if (!toCreate)
9386       {
9387         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9388         return 1;
9389       }
9390       toCreate  = Standard_False;
9391       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
9392     }
9393     else if (anArgCase.IsEqual ("POSLIGHT")
9394           || anArgCase.IsEqual ("POSITIONAL"))
9395     {
9396       addLight (aLightNew, isGlobal);
9397       if (!toCreate)
9398       {
9399         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9400         return 1;
9401       }
9402       toCreate  = Standard_False;
9403       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
9404     }
9405     else if (anArgCase.IsEqual ("CHANGE"))
9406     {
9407       addLight (aLightNew, isGlobal);
9408       aLightNew.Nullify();
9409       if (++anArgIt >= theArgsNb)
9410       {
9411         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9412         return 1;
9413       }
9414
9415       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
9416       Standard_Integer aLightIt = 0;
9417       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9418       {
9419         if (aLightIt == aLightId)
9420         {
9421           aLightOld = aLightIter.Value();
9422           break;
9423         }
9424       }
9425
9426       if (aLightOld.IsNull())
9427       {
9428         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
9429         return 1;
9430       }
9431     }
9432     else if (anArgCase.IsEqual ("DEL")
9433           || anArgCase.IsEqual ("DELETE"))
9434     {
9435       Handle(V3d_Light) aLightDel;
9436       if (++anArgIt >= theArgsNb)
9437       {
9438         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9439         return 1;
9440       }
9441
9442       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9443       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
9444       Standard_Integer aLightIt = 0;
9445       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9446       {
9447         aLightDel = aLightIter.Value();
9448         if (aLightIt == aLightDelId)
9449         {
9450           break;
9451         }
9452       }
9453       if (!aLightDel.IsNull())
9454       {
9455         aViewer->DelLight (aLightDel);
9456       }
9457     }
9458     else if (anArgCase.IsEqual ("COLOR")
9459           || anArgCase.IsEqual ("COLOUR"))
9460     {
9461       if (++anArgIt >= theArgsNb)
9462       {
9463         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9464         return 1;
9465       }
9466
9467       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9468       anArgNext.UpperCase();
9469       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
9470       if (!aLightCurr.IsNull())
9471       {
9472         aLightCurr->SetColor (aColor);
9473       }
9474     }
9475     else if (anArgCase.IsEqual ("POS")
9476           || anArgCase.IsEqual ("POSITION"))
9477     {
9478       if ((anArgIt + 3) >= theArgsNb)
9479       {
9480         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9481         return 1;
9482       }
9483
9484       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9485       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9486       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9487       if (!aLightDir.IsNull())
9488       {
9489         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9490       }
9491       else if (!aLightPos.IsNull())
9492       {
9493         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9494       }
9495       else if (!aLightSpot.IsNull())
9496       {
9497         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9498       }
9499       else
9500       {
9501         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9502         return 1;
9503       }
9504     }
9505     else if (anArgCase.IsEqual ("DIR")
9506           || anArgCase.IsEqual ("DIRECTION"))
9507     {
9508       if ((anArgIt + 3) >= theArgsNb)
9509       {
9510         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9511         return 1;
9512       }
9513
9514       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9515       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9516       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9517       if (!aLightDir.IsNull())
9518       {
9519         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9520       }
9521       else if (!aLightSpot.IsNull())
9522       {
9523         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9524       }
9525       else
9526       {
9527         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9528         return 1;
9529       }
9530     }
9531     else if (anArgCase.IsEqual ("SM")
9532           || anArgCase.IsEqual ("SMOOTHNESS"))
9533     {
9534       if (++anArgIt >= theArgsNb)
9535       {
9536         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9537         return 1;
9538       }
9539
9540       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
9541
9542       if (fabs (aSmoothness) < Precision::Confusion())
9543       {
9544         aLightCurr->SetIntensity (1.f);
9545       }
9546       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
9547       {
9548         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
9549       }
9550       else
9551       {
9552         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
9553         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
9554       }
9555
9556       if (!aLightPos.IsNull())
9557       {
9558         aLightPos->SetSmoothRadius (aSmoothness);
9559       }
9560       else if (!aLightDir.IsNull())
9561       {
9562         aLightDir->SetSmoothAngle (aSmoothness);
9563       }
9564     }
9565     else if (anArgCase.IsEqual ("INT")
9566           || anArgCase.IsEqual ("INTENSITY"))
9567     {
9568       if (++anArgIt >= theArgsNb)
9569       {
9570         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9571         return 1;
9572       }
9573
9574       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
9575
9576       if (!aLightCurr.IsNull())
9577       {
9578         aLightCurr->SetIntensity (aIntensity);
9579       }
9580     }
9581     else if (anArgCase.IsEqual ("ANG")
9582           || anArgCase.IsEqual ("ANGLE"))
9583     {
9584       if (++anArgIt >= theArgsNb)
9585       {
9586         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9587         return 1;
9588       }
9589
9590       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
9591
9592       if (!aLightSpot.IsNull())
9593       {
9594         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
9595       }
9596     }
9597     else if (anArgCase.IsEqual ("CONSTATTEN")
9598           || anArgCase.IsEqual ("CONSTATTENUATION"))
9599     {
9600       if (++anArgIt >= theArgsNb)
9601       {
9602         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9603         return 1;
9604       }
9605
9606       if (!aLightPos.IsNull())
9607       {
9608         aLightPos->Attenuation (anAtten[0], anAtten[1]);
9609         anAtten[0] = Atof (theArgVec[anArgIt]);
9610         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
9611       }
9612       else if (!aLightSpot.IsNull())
9613       {
9614         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9615         anAtten[0] = Atof (theArgVec[anArgIt]);
9616         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
9617       }
9618       else
9619       {
9620         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9621         return 1;
9622       }
9623     }
9624     else if (anArgCase.IsEqual ("LINATTEN")
9625           || anArgCase.IsEqual ("LINEARATTEN")
9626           || anArgCase.IsEqual ("LINEARATTENUATION"))
9627     {
9628       if (++anArgIt >= theArgsNb)
9629       {
9630         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9631         return 1;
9632       }
9633
9634       if (!aLightPos.IsNull())
9635       {
9636         aLightPos->Attenuation (anAtten[0], anAtten[1]);
9637         anAtten[1] = Atof (theArgVec[anArgIt]);
9638         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
9639       }
9640       else if (!aLightSpot.IsNull())
9641       {
9642         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9643         anAtten[1] = Atof (theArgVec[anArgIt]);
9644         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
9645       }
9646       else
9647       {
9648         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9649         return 1;
9650       }
9651     }
9652     else if (anArgCase.IsEqual ("EXP")
9653           || anArgCase.IsEqual ("EXPONENT")
9654           || anArgCase.IsEqual ("SPOTEXP")
9655           || anArgCase.IsEqual ("SPOTEXPONENT"))
9656     {
9657       if (++anArgIt >= theArgsNb)
9658       {
9659         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9660         return 1;
9661       }
9662
9663       if (!aLightSpot.IsNull())
9664       {
9665         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
9666       }
9667       else
9668       {
9669         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9670         return 1;
9671       }
9672     }
9673     else if (anArgCase.IsEqual ("HEAD")
9674           || anArgCase.IsEqual ("HEADLIGHT"))
9675     {
9676       if (++anArgIt >= theArgsNb)
9677       {
9678         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9679         return 1;
9680       }
9681
9682       if (aLightAmb.IsNull()
9683        && !aLightCurr.IsNull())
9684       {
9685         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
9686       }
9687       else
9688       {
9689         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9690         return 1;
9691       }
9692     }
9693     else
9694     {
9695       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9696     }
9697   }
9698
9699   addLight (aLightNew, isGlobal);
9700   aViewer->UpdateLights();
9701
9702   return 0;
9703 }
9704
9705 //=======================================================================
9706 //function : VRenderParams
9707 //purpose  : Enables/disables rendering features
9708 //=======================================================================
9709
9710 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9711                                        Standard_Integer  theArgNb,
9712                                        const char**      theArgVec)
9713 {
9714   Handle(V3d_View) aView = ViewerTest::CurrentView();
9715   if (aView.IsNull())
9716   {
9717     std::cerr << "Error: no active viewer!\n";
9718     return 1;
9719   }
9720
9721   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9722   TCollection_AsciiString aCmdName (theArgVec[0]);
9723   aCmdName.LowerCase();
9724   if (aCmdName == "vraytrace")
9725   {
9726     if (theArgNb == 1)
9727     {
9728       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9729       return 0;
9730     }
9731     else if (theArgNb == 2)
9732     {
9733       TCollection_AsciiString aValue (theArgVec[1]);
9734       aValue.LowerCase();
9735       if (aValue == "on"
9736        || aValue == "1")
9737       {
9738         aParams.Method = Graphic3d_RM_RAYTRACING;
9739         aView->Redraw();
9740         return 0;
9741       }
9742       else if (aValue == "off"
9743             || aValue == "0")
9744       {
9745         aParams.Method = Graphic3d_RM_RASTERIZATION;
9746         aView->Redraw();
9747         return 0;
9748       }
9749       else
9750       {
9751         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9752         return 1;
9753       }
9754     }
9755     else
9756     {
9757       std::cout << "Error: wrong number of arguments\n";
9758       return 1;
9759     }
9760   }
9761
9762   if (theArgNb < 2)
9763   {
9764     theDI << "renderMode:  ";
9765     switch (aParams.Method)
9766     {
9767       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9768       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9769     }
9770     theDI << "\n";
9771     theDI << "transparency:  ";
9772     switch (aParams.TransparencyMethod)
9773     {
9774       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
9775       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
9776                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
9777     }
9778     theDI << "\n";
9779     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9780     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
9781     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9782     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9783     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9784     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9785     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9786     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9787     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9788     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9789     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9790     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9791     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
9792     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
9793     theDI << "shadingModel: ";
9794     switch (aView->ShadingModel())
9795     {
9796       case V3d_COLOR:   theDI << "color";   break;
9797       case V3d_FLAT:    theDI << "flat";    break;
9798       case V3d_GOURAUD: theDI << "gouraud"; break;
9799       case V3d_PHONG:   theDI << "phong";   break;
9800     }
9801     theDI << "\n";
9802     return 0;
9803   }
9804
9805   Standard_Boolean toPrint = Standard_False;
9806   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9807   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9808   {
9809     Standard_CString        anArg (theArgVec[anArgIter]);
9810     TCollection_AsciiString aFlag (anArg);
9811     aFlag.LowerCase();
9812     if (anUpdateTool.parseRedrawMode (aFlag))
9813     {
9814       continue;
9815     }
9816     else if (aFlag == "-echo"
9817           || aFlag == "-print")
9818     {
9819       toPrint = Standard_True;
9820       anUpdateTool.Invalidate();
9821     }
9822     else if (aFlag == "-mode"
9823           || aFlag == "-rendermode"
9824           || aFlag == "-render_mode")
9825     {
9826       if (toPrint)
9827       {
9828         switch (aParams.Method)
9829         {
9830           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9831           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9832         }
9833         continue;
9834       }
9835       else
9836       {
9837         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9838         return 1;
9839       }
9840     }
9841     else if (aFlag == "-ray"
9842           || aFlag == "-raytrace")
9843     {
9844       if (toPrint)
9845       {
9846         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9847         continue;
9848       }
9849
9850       aParams.Method = Graphic3d_RM_RAYTRACING;
9851     }
9852     else if (aFlag == "-rast"
9853           || aFlag == "-raster"
9854           || aFlag == "-rasterization")
9855     {
9856       if (toPrint)
9857       {
9858         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9859         continue;
9860       }
9861
9862       aParams.Method = Graphic3d_RM_RASTERIZATION;
9863     }
9864     else if (aFlag == "-msaa")
9865     {
9866       if (toPrint)
9867       {
9868         theDI << aParams.NbMsaaSamples << " ";
9869         continue;
9870       }
9871       else if (++anArgIter >= theArgNb)
9872       {
9873         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9874         return 1;
9875       }
9876
9877       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9878       if (aNbSamples < 0)
9879       {
9880         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9881         return 1;
9882       }
9883       else
9884       {
9885         aParams.NbMsaaSamples = aNbSamples;
9886       }
9887     }
9888     else if (aFlag == "-oit")
9889     {
9890       if (toPrint)
9891       {
9892         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
9893         {
9894           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
9895         }
9896         else
9897         {
9898           theDI << "off" << " ";
9899         }
9900         continue;
9901       }
9902       else if (++anArgIter >= theArgNb)
9903       {
9904         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9905         return 1;
9906       }
9907
9908       TCollection_AsciiString aParam = theArgVec[anArgIter];
9909       aParam.LowerCase();
9910       if (aParam.IsRealValue())
9911       {
9912         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
9913         if (aWeight < 0.f || aWeight > 1.f)
9914         {
9915           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
9916           return 1;
9917         }
9918
9919         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
9920         aParams.OitDepthFactor     = aWeight;
9921       }
9922       else if (aParam == "off")
9923       {
9924         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
9925       }
9926       else
9927       {
9928         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9929         return 1;
9930       }
9931     }
9932     else if (aFlag == "-rendscale"
9933           || aFlag == "-renderscale"
9934           || aFlag == "-renderresolutionscale")
9935     {
9936       if (toPrint)
9937       {
9938         theDI << aParams.RenderResolutionScale << " ";
9939         continue;
9940       }
9941       else if (++anArgIter >= theArgNb)
9942       {
9943         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9944         return 1;
9945       }
9946
9947       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
9948       if (aScale < 0.01)
9949       {
9950         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
9951         return 1;
9952       }
9953       else
9954       {
9955         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
9956       }
9957     }
9958     else if (aFlag == "-raydepth"
9959           || aFlag == "-ray_depth")
9960     {
9961       if (toPrint)
9962       {
9963         theDI << aParams.RaytracingDepth << " ";
9964         continue;
9965       }
9966       else if (++anArgIter >= theArgNb)
9967       {
9968         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9969         return 1;
9970       }
9971
9972       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9973
9974       // We allow RaytracingDepth be more than 10 in case of GI enabled
9975       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9976       {
9977         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9978         return 1;
9979       }
9980       else
9981       {
9982         aParams.RaytracingDepth = aDepth;
9983       }
9984     }
9985     else if (aFlag == "-shad"
9986           || aFlag == "-shadows")
9987     {
9988       if (toPrint)
9989       {
9990         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
9991         continue;
9992       }
9993
9994       Standard_Boolean toEnable = Standard_True;
9995       if (++anArgIter < theArgNb
9996       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9997       {
9998         --anArgIter;
9999       }
10000       aParams.IsShadowEnabled = toEnable;
10001     }
10002     else if (aFlag == "-refl"
10003           || aFlag == "-reflections")
10004     {
10005       if (toPrint)
10006       {
10007         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10008         continue;
10009       }
10010
10011       Standard_Boolean toEnable = Standard_True;
10012       if (++anArgIter < theArgNb
10013       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10014       {
10015         --anArgIter;
10016       }
10017       aParams.IsReflectionEnabled = toEnable;
10018     }
10019     else if (aFlag == "-fsaa")
10020     {
10021       if (toPrint)
10022       {
10023         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10024         continue;
10025       }
10026
10027       Standard_Boolean toEnable = Standard_True;
10028       if (++anArgIter < theArgNb
10029       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10030       {
10031         --anArgIter;
10032       }
10033       aParams.IsAntialiasingEnabled = toEnable;
10034     }
10035     else if (aFlag == "-gleam")
10036     {
10037       if (toPrint)
10038       {
10039         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10040         continue;
10041       }
10042
10043       Standard_Boolean toEnable = Standard_True;
10044       if (++anArgIter < theArgNb
10045       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10046       {
10047         --anArgIter;
10048       }
10049       aParams.IsTransparentShadowEnabled = toEnable;
10050     }
10051     else if (aFlag == "-gi")
10052     {
10053       if (toPrint)
10054       {
10055         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10056         continue;
10057       }
10058
10059       Standard_Boolean toEnable = Standard_True;
10060       if (++anArgIter < theArgNb
10061       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10062       {
10063         --anArgIter;
10064       }
10065       aParams.IsGlobalIlluminationEnabled = toEnable;
10066       if (!toEnable)
10067       {
10068         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10069       }
10070     }
10071     else if (aFlag == "-blockedrng"
10072           || aFlag == "-brng")
10073     {
10074       if (toPrint)
10075       {
10076         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10077         continue;
10078       }
10079
10080       Standard_Boolean toEnable = Standard_True;
10081       if (++anArgIter < theArgNb
10082         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10083       {
10084         --anArgIter;
10085       }
10086       aParams.CoherentPathTracingMode = toEnable;
10087     }
10088     else if (aFlag == "-maxrad")
10089     {
10090       if (toPrint)
10091       {
10092         theDI << aParams.RadianceClampingValue << " ";
10093         continue;
10094       }
10095       else if (++anArgIter >= theArgNb)
10096       {
10097         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10098         return 1;
10099       }
10100
10101       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10102       if (!aMaxRadStr.IsRealValue())
10103       {
10104         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10105         return 1;
10106       }
10107
10108       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10109       if (aMaxRadiance <= 0.0)
10110       {
10111         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10112         return 1;
10113       }
10114       else
10115       {
10116         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
10117       }
10118     }
10119     else if (aFlag == "-iss")
10120     {
10121       if (toPrint)
10122       {
10123         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
10124         continue;
10125       }
10126
10127       Standard_Boolean toEnable = Standard_True;
10128       if (++anArgIter < theArgNb
10129         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10130       {
10131         --anArgIter;
10132       }
10133       aParams.AdaptiveScreenSampling = toEnable;
10134     }
10135     else if (aFlag == "-issd")
10136     {
10137       if (toPrint)
10138       {
10139         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
10140         continue;
10141       }
10142
10143       Standard_Boolean toEnable = Standard_True;
10144       if (++anArgIter < theArgNb
10145         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10146       {
10147         --anArgIter;
10148       }
10149       aParams.ShowSamplingTiles = toEnable;
10150     }
10151     else if (aFlag == "-nbtiles")
10152     {
10153       if (toPrint)
10154       {
10155         theDI << aParams.NbRayTracingTiles << " ";
10156         continue;
10157       }
10158       else if (++anArgIter >= theArgNb)
10159       {
10160         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10161         return 1;
10162       }
10163
10164       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
10165
10166       if (aNbTiles < 64)
10167       {
10168         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
10169         std::cerr << "Specify value in range [64, 1024].\n";
10170         return 1;
10171       }
10172       else
10173       {
10174         aParams.NbRayTracingTiles = aNbTiles;
10175       }
10176     }
10177     else if (aFlag == "-env")
10178     {
10179       if (toPrint)
10180       {
10181         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
10182         continue;
10183       }
10184
10185       Standard_Boolean toEnable = Standard_True;
10186       if (++anArgIter < theArgNb
10187         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10188       {
10189         --anArgIter;
10190       }
10191       aParams.UseEnvironmentMapBackground = toEnable;
10192     }
10193     else if (aFlag == "-twoside")
10194     {
10195       if (toPrint)
10196       {
10197         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
10198         continue;
10199       }
10200
10201       Standard_Boolean toEnable = Standard_True;
10202       if (++anArgIter < theArgNb
10203         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10204       {
10205         --anArgIter;
10206       }
10207       aParams.TwoSidedBsdfModels = toEnable;
10208     }
10209     else if (aFlag == "-shademodel"
10210           || aFlag == "-shadingmodel"
10211           || aFlag == "-shading")
10212     {
10213       if (toPrint)
10214       {
10215         switch (aView->ShadingModel())
10216         {
10217           case V3d_COLOR:   theDI << "color ";   break;
10218           case V3d_FLAT:    theDI << "flat ";    break;
10219           case V3d_GOURAUD: theDI << "gouraud "; break;
10220           case V3d_PHONG:   theDI << "phong ";   break;
10221         }
10222         continue;
10223       }
10224
10225       if (++anArgIter >= theArgNb)
10226       {
10227         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10228       }
10229
10230       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10231       aMode.LowerCase();
10232       if (aMode == "color"
10233        || aMode == "none")
10234       {
10235         aView->SetShadingModel (V3d_COLOR);
10236       }
10237       else if (aMode == "flat"
10238             || aMode == "facet")
10239       {
10240         aView->SetShadingModel (V3d_FLAT);
10241       }
10242       else if (aMode == "gouraud"
10243             || aMode == "vertex"
10244             || aMode == "vert")
10245       {
10246         aView->SetShadingModel (V3d_GOURAUD);
10247       }
10248       else if (aMode == "phong"
10249             || aMode == "fragment"
10250             || aMode == "frag"
10251             || aMode == "pixel")
10252       {
10253         aView->SetShadingModel (V3d_PHONG);
10254       }
10255       else
10256       {
10257         std::cout << "Error: unknown shading model '" << aMode << "'\n";
10258         return 1;
10259       }
10260     }
10261     else if (aFlag == "-resolution")
10262     {
10263       if (++anArgIter >= theArgNb)
10264       {
10265         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10266         return 1;
10267       }
10268
10269       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
10270       if (aResolution.IsIntegerValue())
10271       {
10272         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
10273       }
10274       else
10275       {
10276         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10277         return 1;
10278       }
10279     }
10280     else if (aFlag == "-rebuildglsl"
10281           || aFlag == "-rebuild")
10282     {
10283       if (toPrint)
10284       {
10285         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
10286         continue;
10287       }
10288
10289       Standard_Boolean toEnable = Standard_True;
10290       if (++anArgIter < theArgNb
10291           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10292       {
10293         --anArgIter;
10294       }
10295       aParams.RebuildRayTracingShaders = toEnable;
10296     }
10297     else if (aFlag == "-focal")
10298     {
10299       if (++anArgIter >= theArgNb)
10300       {
10301         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10302         return 1;
10303       }
10304
10305       TCollection_AsciiString aParam (theArgVec[anArgIter]);
10306       if (aParam.IsRealValue())
10307       {
10308         float aFocalDist = static_cast<float> (aParam.RealValue());
10309         if (aFocalDist < 0)
10310         {
10311           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10312           return 1;
10313         }
10314         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
10315       }
10316       else
10317       {
10318         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10319         return 1;
10320       }
10321     }
10322     else if (aFlag == "-aperture")
10323     {
10324       if (++anArgIter >= theArgNb)
10325       {
10326         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10327         return 1;
10328       }
10329
10330       TCollection_AsciiString aParam(theArgVec[anArgIter]);
10331       if (aParam.IsRealValue())
10332       {
10333         float aApertureSize = static_cast<float> (aParam.RealValue());
10334         if (aApertureSize < 0)
10335         {
10336           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10337           return 1;
10338         }
10339         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
10340       }
10341       else
10342       {
10343         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10344         return 1;
10345       }
10346     }
10347     else if (aFlag == "-exposure")
10348     {
10349       if (++anArgIter >= theArgNb)
10350       {
10351         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10352         return 1;
10353       }
10354
10355       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
10356       if (anExposure.IsRealValue())
10357       {
10358         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
10359       }
10360       else
10361       {
10362         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10363         return 1;
10364       }
10365     }
10366     else if (aFlag == "-whitepoint")
10367     {
10368       if (++anArgIter >= theArgNb)
10369       {
10370         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10371         return 1;
10372       }
10373
10374       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
10375       if (aWhitePoint.IsRealValue())
10376       {
10377         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
10378       }
10379       else
10380       {
10381         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10382         return 1;
10383       }
10384     }
10385     else if (aFlag == "-tonemapping")
10386     {
10387       if (++anArgIter >= theArgNb)
10388       {
10389         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10390         return 1;
10391       }
10392
10393       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10394       aMode.LowerCase();
10395
10396       if (aMode == "disabled")
10397       {
10398         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
10399       }
10400       else if (aMode == "filmic")
10401       {
10402         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
10403       }
10404       else
10405       {
10406         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10407         return 1;
10408       }
10409     }
10410     else
10411     {
10412       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
10413       return 1;
10414     }
10415   }
10416
10417   return 0;
10418 }
10419
10420 //=======================================================================
10421 //function : VProgressiveMode
10422 //purpose  :
10423 //=======================================================================
10424 #if defined(_WIN32)
10425 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
10426                                           Standard_Integer  /*theNbArgs*/,
10427                                           const char**      /*theArgs*/)
10428 {
10429   Handle(V3d_View) aView = ViewerTest::CurrentView();
10430   if (aView.IsNull())
10431   {
10432     std::cerr << "Error: no active viewer!\n";
10433     return 1;
10434   }
10435
10436   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
10437
10438   for (;;)
10439   {
10440     aView->Redraw();
10441
10442     Standard_Boolean toExit = Standard_False;
10443
10444     MSG aMsg;
10445     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
10446     {
10447       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
10448       {
10449         toExit = Standard_True;
10450       }
10451
10452       TranslateMessage (&aMsg);
10453       DispatchMessageW (&aMsg);
10454     }
10455
10456     if (toExit)
10457     {
10458       break;
10459     }
10460   }
10461
10462   return 0;
10463 }
10464 #endif
10465
10466 //=======================================================================
10467 //function : VFrustumCulling
10468 //purpose  : enables/disables view volume's culling.
10469 //=======================================================================
10470 static int VFrustumCulling (Draw_Interpretor& theDI,
10471                             Standard_Integer  theArgNb,
10472                             const char**      theArgVec)
10473 {
10474   Handle(V3d_View) aView = ViewerTest::CurrentView();
10475   if (aView.IsNull())
10476   {
10477     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
10478     return 1;
10479   }
10480
10481   if (theArgNb < 2)
10482   {
10483     theDI << (aView->IsCullingEnabled() ? "on" : "off");
10484     return 0;
10485   }
10486   else if (theArgNb != 2)
10487   {
10488     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
10489     return 1;
10490   }
10491
10492   TCollection_AsciiString aModeStr (theArgVec[1]);
10493   aModeStr.LowerCase();
10494   Standard_Boolean toEnable = 0;
10495   if (aModeStr == "on")
10496   {
10497     toEnable = 1;
10498   }
10499   else if (aModeStr == "off")
10500   {
10501     toEnable = 0;
10502   }
10503   else
10504   {
10505     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10506   }
10507
10508   aView->SetFrustumCulling (toEnable);
10509   aView->Redraw();
10510   return 0;
10511 }
10512
10513 //=======================================================================
10514 //function : VHighlightSelected
10515 //purpose  : 
10516 //=======================================================================
10517 static int VHighlightSelected (Draw_Interpretor& theDI,
10518                                Standard_Integer  theArgNb,
10519                                const char**      theArgVec)
10520 {
10521   if (ViewerTest::GetAISContext().IsNull())
10522   {
10523     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
10524     return 1;
10525   }
10526
10527   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10528
10529   if (theArgNb < 2)
10530   {
10531     theDI << (aContext->ToHilightSelected() ? "on" : "off");
10532     return 0;
10533   }
10534
10535   if (theArgNb != 2)
10536   {
10537     std::cout  << theArgVec[0] << " error : wrong number of parameters."
10538           << "Type 'help" << theArgVec[0] << "' for more information.";
10539     return 1;
10540   }
10541
10542   // Parse parameter
10543   TCollection_AsciiString aMode (theArgVec[1]);
10544   aMode.LowerCase();
10545   Standard_Boolean toEnable = Standard_False;
10546   if (aMode.IsEqual ("on"))
10547   {
10548     toEnable = Standard_True;
10549   }
10550   else if (aMode.IsEqual ("off"))
10551   {
10552     toEnable = Standard_False;
10553   }
10554   else
10555   {
10556     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10557   }
10558
10559   if (toEnable != aContext->ToHilightSelected())
10560   {
10561     aContext->SetToHilightSelected (toEnable);
10562
10563     // Move cursor to null position and  back to process updating of detection
10564     // and highlighting of selected object immediatly.
10565     Standard_Integer aPixX = 0;
10566     Standard_Integer aPixY = 0;
10567     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
10568
10569     anEventManager->GetCurrentPosition (aPixX, aPixY);
10570     anEventManager->MoveTo (0, 0);
10571     anEventManager->MoveTo (aPixX, aPixY);
10572   }
10573
10574   return 0;
10575 }
10576
10577 //=======================================================================
10578 //function : VXRotate
10579 //purpose  :
10580 //=======================================================================
10581 static Standard_Integer VXRotate (Draw_Interpretor& di,
10582                                    Standard_Integer argc,
10583                                    const char ** argv)
10584 {
10585   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10586   if (aContext.IsNull())
10587   {
10588     di << argv[0] << "ERROR : use 'vinit' command before \n";
10589     return 1;
10590   }
10591   
10592   if (argc != 3)
10593   {
10594     di << "ERROR : Usage : " << argv[0] << " name angle\n";
10595     return 1;
10596   }
10597
10598   TCollection_AsciiString aName (argv[1]);
10599   Standard_Real anAngle = Draw::Atof (argv[2]);
10600
10601   // find object
10602   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
10603   Handle(AIS_InteractiveObject) anIObj;
10604   if (!aMap.IsBound2 (aName) )
10605   {
10606     di << "Use 'vdisplay' before\n";
10607     return 1;
10608   }
10609   else
10610   {
10611     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
10612
10613     gp_Trsf aTransform;
10614     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
10615     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
10616
10617     aContext->SetLocation (anIObj, aTransform);
10618     aContext->UpdateCurrentViewer();
10619   }
10620
10621   return 0;
10622 }
10623
10624 //===============================================================================================
10625 //class   : ViewerTest_AISManipulator
10626 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
10627 //===============================================================================================
10628 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10629
10630 class ViewerTest_AISManipulator : public AIS_Manipulator
10631 {
10632 public:
10633
10634   ViewerTest_AISManipulator() : AIS_Manipulator()
10635   {
10636     GetMapOfAISManipulators().Add (this);
10637   }
10638
10639   virtual ~ViewerTest_AISManipulator()
10640   {
10641     GetMapOfAISManipulators().Remove (this);
10642   }
10643
10644   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10645 };
10646
10647 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10648 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10649
10650 //===============================================================================================
10651 //function : VManipulator
10652 //purpose  :
10653 //===============================================================================================
10654 static int VManipulator (Draw_Interpretor& theDi,
10655                          Standard_Integer  theArgsNb,
10656                          const char**      theArgVec)
10657 {
10658   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10659   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10660   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
10661   if (aView.IsNull()
10662    || aViewer.IsNull())
10663   {
10664     std::cerr << "No active viewer!\n";
10665     return 1;
10666   }
10667
10668   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
10669   Standard_Integer anArgIter = 1;
10670   for (; anArgIter < theArgsNb; ++anArgIter)
10671   {
10672     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
10673   }
10674
10675   ViewerTest_CmdParser aCmd;
10676   aCmd.AddDescription ("Manages manipulator for interactive objects:");
10677   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
10678   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
10679   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
10680   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
10681   aCmd.AddOption ("detach",         "...       - detach manipulator");
10682
10683   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
10684   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
10685   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
10686
10687   aCmd.AddOption ("move",   "... x y z - move object");
10688   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
10689   aCmd.AddOption ("scale",  "... factor - scale object");
10690
10691   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
10692   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
10693   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
10694   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
10695   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
10696   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
10697   aCmd.AddOption ("size",              "... size - set size of manipulator");
10698   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
10699
10700   aCmd.Parse (theArgsNb, theArgVec);
10701
10702   if (aCmd.HasOption ("help"))
10703   {
10704     theDi.PrintHelp (theArgVec[0]);
10705     return 0;
10706   }
10707
10708   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
10709
10710   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
10711
10712   if (aName.IsEmpty())
10713   {
10714     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
10715     return 1;
10716   }
10717
10718   // ----------------------------------
10719   // detach existing manipulator object
10720   // ----------------------------------
10721
10722   if (aCmd.HasOption ("detach"))
10723   {
10724     if (!aMapAIS.IsBound2 (aName))
10725     {
10726       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
10727       return 1;
10728     }
10729
10730     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10731     if (aManipulator.IsNull())
10732     {
10733       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10734       return 1;
10735     }
10736
10737     aManipulator->Detach();
10738     aMapAIS.UnBind2 (aName);
10739     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
10740
10741     return 0;
10742   }
10743
10744   // -----------------------------------------------
10745   // find or create manipulator if it does not exist
10746   // -----------------------------------------------
10747
10748   Handle(AIS_Manipulator) aManipulator;
10749   if (!aMapAIS.IsBound2 (aName))
10750   {
10751     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
10752
10753     aManipulator = new ViewerTest_AISManipulator();
10754     aMapAIS.Bind (aManipulator, aName);
10755   }
10756   else
10757   {
10758     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10759     if (aManipulator.IsNull())
10760     {
10761       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10762       return 1;
10763     }
10764   }
10765
10766   // -----------------------------------------
10767   // change properties of manipulator instance
10768   // -----------------------------------------
10769
10770   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
10771   {
10772     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
10773   }
10774   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
10775   {
10776     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
10777   }
10778   if (aCmd.HasOption ("followRotation", 1, Standard_True))
10779   {
10780     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
10781   }
10782   if (aCmd.HasOption ("gap", 1, Standard_True))
10783   {
10784     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
10785   }
10786   if (aCmd.HasOption ("part", 3, Standard_True))
10787   {
10788     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
10789     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
10790     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
10791     if (aMode < 1 || aMode > 3)
10792     {
10793       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
10794       return 1;
10795     }
10796
10797     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
10798   }
10799   if (aCmd.HasOption ("pos", 3, Standard_True))
10800   {
10801     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
10802     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
10803     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
10804
10805     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
10806   }
10807   if (aCmd.HasOption ("size", 1, Standard_True))
10808   {
10809     aManipulator->SetSize (aCmd.ArgFloat ("size"));
10810   }
10811   if (aCmd.HasOption ("zoomable", 1, Standard_True))
10812   {
10813     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
10814
10815     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
10816     {
10817       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
10818       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
10819     }
10820   }
10821
10822   // ---------------------------------------------------
10823   // attach, detach or access manipulator from an object
10824   // ---------------------------------------------------
10825
10826   if (aCmd.HasOption ("attach"))
10827   {
10828     // Find an object and attach manipulator to it
10829     if (!aCmd.HasOption ("attach", 1, Standard_True))
10830     {
10831       return 1;
10832     }
10833
10834     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
10835     if (!aMapAIS.IsBound2 (anObjName))
10836     {
10837       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
10838       return 1;
10839     }
10840
10841     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
10842     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
10843     for (; anIt.More(); anIt.Next())
10844     {
10845       if (anIt.Value()->IsAttached()
10846        && anIt.Value()->Object() == anObject)
10847       {
10848         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
10849         return 1;
10850       }
10851     }
10852
10853     AIS_Manipulator::OptionsForAttach anOptions;
10854     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
10855     {
10856       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
10857     }
10858     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
10859     {
10860       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
10861     }
10862     if (aCmd.HasOption ("enableModes", 1, Standard_True))
10863     {
10864       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
10865     }
10866
10867     aManipulator->Attach (anObject, anOptions);
10868   }
10869
10870   // --------------------------------------
10871   // apply transformation using manipulator
10872   // --------------------------------------
10873
10874   if (aCmd.HasOption ("startTransform", 2, Standard_True))
10875   {
10876     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
10877   }
10878   if (aCmd.HasOption ("transform", 2, Standard_True))
10879   {
10880     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
10881   }
10882   if (aCmd.HasOption ("stopTransform"))
10883   {
10884     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
10885
10886     aManipulator->StopTransform (toApply);
10887   }
10888
10889   gp_Trsf aT;
10890   if (aCmd.HasOption ("move", 3, Standard_True))
10891   {
10892     aT.SetTranslationPart (aCmd.ArgVec ("move"));
10893   }
10894   if (aCmd.HasOption ("rotate", 7, Standard_True))
10895   {
10896     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
10897   }
10898   if (aCmd.HasOption ("scale", 1))
10899   {
10900     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
10901   }
10902
10903   if (aT.Form() != gp_Identity)
10904   {
10905     aManipulator->Transform (aT);
10906   }
10907
10908   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
10909
10910   return 0;
10911 }
10912
10913 //===============================================================================================
10914 //function : VSelectionProperties
10915 //purpose  :
10916 //===============================================================================================
10917 static int VSelectionProperties (Draw_Interpretor& theDi,
10918                                  Standard_Integer  theArgsNb,
10919                                  const char**      theArgVec)
10920 {
10921   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10922   if (aCtx.IsNull())
10923   {
10924     std::cerr << "No active viewer!\n";
10925     return 1;
10926   }
10927
10928   Standard_Boolean toPrint  = theArgsNb == 1;
10929   Standard_Boolean toRedraw = Standard_False;
10930   Standard_Integer anArgIter = 1;
10931   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
10932   if (anArgIter < theArgsNb)
10933   {
10934     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
10935     anArgFirst.LowerCase();
10936     ++anArgIter;
10937     if (anArgFirst == "dynhighlight"
10938      || anArgFirst == "dynhilight"
10939      || anArgFirst == "dynamichighlight"
10940      || anArgFirst == "dynamichilight")
10941     {
10942       aType = Prs3d_TypeOfHighlight_Dynamic;
10943     }
10944     else if (anArgFirst == "localdynhighlight"
10945           || anArgFirst == "localdynhilight"
10946           || anArgFirst == "localdynamichighlight"
10947           || anArgFirst == "localdynamichilight")
10948     {
10949       aType = Prs3d_TypeOfHighlight_LocalDynamic;
10950     }
10951     else if (anArgFirst == "selhighlight"
10952           || anArgFirst == "selhilight"
10953           || anArgFirst == "selectedhighlight"
10954           || anArgFirst == "selectedhilight")
10955     {
10956       aType = Prs3d_TypeOfHighlight_Selected;
10957     }
10958     else if (anArgFirst == "localselhighlight"
10959           || anArgFirst == "localselhilight"
10960           || anArgFirst == "localselectedhighlight"
10961           || anArgFirst == "localselectedhilight")
10962     {
10963       aType = Prs3d_TypeOfHighlight_LocalSelected;
10964     }
10965     else
10966     {
10967       --anArgIter;
10968     }
10969   }
10970   for (; anArgIter < theArgsNb; ++anArgIter)
10971   {
10972     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10973     anArg.LowerCase();
10974     if (anArg == "-help")
10975     {
10976       theDi.PrintHelp (theArgVec[0]);
10977       return 0;
10978     }
10979     else if (anArg == "-print")
10980     {
10981       toPrint = Standard_True;
10982     }
10983     else if (anArg == "-autoactivate")
10984     {
10985       Standard_Boolean toEnable = Standard_True;
10986       if (anArgIter + 1 < theArgsNb
10987        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
10988       {
10989         ++anArgIter;
10990       }
10991       aCtx->SetAutoActivateSelection (toEnable);
10992     }
10993     else if (anArg == "-pickstrategy"
10994           || anArg == "-pickingstrategy")
10995     {
10996       if (++anArgIter >= theArgsNb)
10997       {
10998         std::cout << "Syntax error: type of highlighting is undefined\n";
10999         return 1;
11000       }
11001
11002       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11003       TCollection_AsciiString aVal (theArgVec[anArgIter]);
11004       aVal.LowerCase();
11005       if (aVal == "first"
11006        || aVal == "firstaccepted"
11007        || aVal == "firstacceptable")
11008       {
11009         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11010       }
11011       else if (aVal == "topmost"
11012             || aVal == "onlyTopmost")
11013       {
11014         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
11015       }
11016       else
11017       {
11018         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
11019         return 1;
11020       }
11021
11022       aCtx->SetPickingStrategy (aStrategy);
11023     }
11024     else if (anArg == "-pixtol"
11025           && anArgIter + 1 < theArgsNb)
11026     {
11027       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
11028     }
11029     else if ((anArg == "-mode"
11030            || anArg == "-dispmode")
11031           && anArgIter + 1 < theArgsNb)
11032     {
11033       if (aType == Prs3d_TypeOfHighlight_None)
11034       {
11035         std::cout << "Syntax error: type of highlighting is undefined\n";
11036         return 1;
11037       }
11038
11039       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
11040       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11041       aStyle->SetDisplayMode (aDispMode);
11042       toRedraw = Standard_True;
11043     }
11044     else if (anArg == "-layer"
11045           && anArgIter + 1 < theArgsNb)
11046     {
11047       if (aType == Prs3d_TypeOfHighlight_None)
11048       {
11049         std::cout << "Syntax error: type of highlighting is undefined\n";
11050         return 1;
11051       }
11052
11053       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
11054       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
11055       {
11056         TColStd_SequenceOfInteger aLayers;
11057         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
11058         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
11059         {
11060           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
11061           return 1;
11062         }
11063       }
11064
11065       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11066       aStyle->SetZLayer (aNewLayer);
11067       toRedraw = Standard_True;
11068     }
11069     else if (anArg == "-hicolor"
11070           || anArg == "-selcolor"
11071           || anArg == "-color")
11072     {
11073       if (anArg.StartsWith ("-hi"))
11074       {
11075         aType = Prs3d_TypeOfHighlight_Dynamic;
11076       }
11077       else if (anArg.StartsWith ("-sel"))
11078       {
11079         aType = Prs3d_TypeOfHighlight_Selected;
11080       }
11081       else if (aType == Prs3d_TypeOfHighlight_None)
11082       {
11083         std::cout << "Syntax error: type of highlighting is undefined\n";
11084         return 1;
11085       }
11086
11087       Quantity_Color aColor;
11088       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
11089                                                            theArgVec + anArgIter + 1,
11090                                                            aColor);
11091       if (aNbParsed == 0)
11092       {
11093         std::cout << "Syntax error: need more arguments.\n";
11094         return 1;
11095       }
11096       anArgIter += aNbParsed;
11097
11098       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11099       aStyle->SetColor (aColor);
11100       toRedraw = Standard_True;
11101     }
11102     else if ((anArg == "-transp"
11103            || anArg == "-transparency"
11104            || anArg == "-hitransp"
11105            || anArg == "-seltransp"
11106            || anArg == "-hitransplocal"
11107            || anArg == "-seltransplocal")
11108           && anArgIter + 1 < theArgsNb)
11109     {
11110       if (anArg.StartsWith ("-hi"))
11111       {
11112         aType = Prs3d_TypeOfHighlight_Dynamic;
11113       }
11114       else if (anArg.StartsWith ("-sel"))
11115       {
11116         aType = Prs3d_TypeOfHighlight_Selected;
11117       }
11118       else if (aType == Prs3d_TypeOfHighlight_None)
11119       {
11120         std::cout << "Syntax error: type of highlighting is undefined\n";
11121         return 1;
11122       }
11123
11124       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
11125       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11126       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
11127       toRedraw = Standard_True;
11128     }
11129     else if ((anArg == "-mat"
11130            || anArg == "-material")
11131           && anArgIter + 1 < theArgsNb)
11132     {
11133       if (aType == Prs3d_TypeOfHighlight_None)
11134       {
11135         std::cout << "Syntax error: type of highlighting is undefined\n";
11136         return 1;
11137       }
11138
11139       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11140       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
11141       if (aMatName != Graphic3d_NOM_DEFAULT)
11142       {
11143         ++anArgIter;
11144         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
11145         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
11146         Graphic3d_MaterialAspect aMat (aMatName);
11147         aMat.SetColor (aStyle->Color());
11148         aMat.SetTransparency (aStyle->Transparency());
11149         anAspect->SetFrontMaterial (aMat);
11150         anAspect->SetInteriorColor (aStyle->Color());
11151         aStyle->SetBasicFillAreaAspect (anAspect);
11152       }
11153       else
11154       {
11155         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
11156       }
11157       toRedraw = Standard_True;
11158     }
11159     else
11160     {
11161       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
11162     }
11163   }
11164
11165   if (toPrint)
11166   {
11167     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
11168     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
11169     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
11170     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
11171     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
11172     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
11173     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
11174     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
11175     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
11176     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
11177     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
11178     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
11179   }
11180
11181   if (aCtx->NbSelected() != 0 && toRedraw)
11182   {
11183     aCtx->HilightSelected (Standard_True);
11184   }
11185
11186   return 0;
11187 }
11188
11189 //===============================================================================================
11190 //function : VDumpSelectionImage
11191 //purpose  :
11192 //===============================================================================================
11193 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
11194                                 Standard_Integer  theArgsNb,
11195                                 const char**      theArgVec)
11196 {
11197   if (theArgsNb < 2)
11198   {
11199     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
11200     return 1;
11201   }
11202
11203   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
11204   if (aContext.IsNull())
11205   {
11206     std::cout << "Error: no active view.\n";
11207     return 1;
11208   }
11209
11210   TCollection_AsciiString aFile;
11211   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11212   Image_Format anImgFormat = Image_Format_BGR;
11213   Standard_Integer aPickedIndex = 1;
11214   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
11215   {
11216     TCollection_AsciiString aParam (theArgVec[anArgIter]);
11217     aParam.LowerCase();
11218     if (aParam == "-type")
11219     {
11220       if (++anArgIter >= theArgsNb)
11221       {
11222         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
11223         return 1;
11224       }
11225
11226       TCollection_AsciiString aValue (theArgVec[anArgIter]);
11227       aValue.LowerCase();
11228       if (aValue == "depth"
11229        || aValue == "normdepth"
11230        || aValue == "normalizeddepth")
11231       {
11232         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11233         anImgFormat = Image_Format_GrayF;
11234       }
11235       if (aValue == "depthinverted"
11236        || aValue == "normdepthinverted"
11237        || aValue == "normalizeddepthinverted"
11238        || aValue == "inverted")
11239       {
11240         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
11241         anImgFormat = Image_Format_GrayF;
11242       }
11243       else if (aValue == "unnormdepth"
11244             || aValue == "unnormalizeddepth")
11245       {
11246         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
11247         anImgFormat = Image_Format_GrayF;
11248       }
11249       else if (aValue == "objectcolor"
11250             || aValue == "object"
11251             || aValue == "color")
11252       {
11253         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
11254       }
11255       else if (aValue == "entitycolor"
11256             || aValue == "entity")
11257       {
11258         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
11259       }
11260       else if (aValue == "ownercolor"
11261             || aValue == "owner")
11262       {
11263         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
11264       }
11265       else if (aValue == "selectionmodecolor"
11266             || aValue == "selectionmode"
11267             || aValue == "selmodecolor"
11268             || aValue == "selmode")
11269       {
11270         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
11271       }
11272     }
11273     else if (aParam == "-picked"
11274           || aParam == "-pickeddepth"
11275           || aParam == "-pickedindex")
11276     {
11277       if (++anArgIter >= theArgsNb)
11278       {
11279         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
11280         return 1;
11281       }
11282
11283       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
11284     }
11285     else if (aFile.IsEmpty())
11286     {
11287       aFile = theArgVec[anArgIter];
11288     }
11289     else
11290     {
11291       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
11292       return 1;
11293     }
11294   }
11295   if (aFile.IsEmpty())
11296   {
11297     std::cout << "Syntax error: image file name is missing.\n";
11298     return 1;
11299   }
11300
11301   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
11302   Standard_Integer aWidth = 0, aHeight = 0;
11303   aView->Window()->Size (aWidth, aHeight);
11304
11305   Image_AlienPixMap aPixMap;
11306   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
11307   {
11308     std::cout << "Error: can't allocate image.\n";
11309     return 1;
11310   }
11311   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
11312   {
11313     std::cout << "Error: can't generate selection image.\n";
11314     return 1;
11315   }
11316   if (!aPixMap.Save (aFile))
11317   {
11318     std::cout << "Error: can't save selection image.\n";
11319     return 0;
11320   }
11321   return 0;
11322 }
11323
11324 //=======================================================================
11325 //function : ViewerCommands
11326 //purpose  :
11327 //=======================================================================
11328
11329 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
11330 {
11331
11332   const char *group = "ZeViewer";
11333   theCommands.Add("vinit",
11334           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
11335     "\n\t\t:     [-exitOnClose] [-closeOnEscape]"
11336   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11337     "\n\t\t:     [-display displayName]"
11338   #endif
11339     "\n\t\t: Creates new View window with specified name viewName."
11340     "\n\t\t: By default the new view is created in the viewer and in"
11341     "\n\t\t: graphic driver shared with active view."
11342     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
11343     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
11344     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
11345 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11346     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
11347     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
11348 #endif
11349     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
11350     "\n\t\t:  -width, -height width and heigth of window respectively."
11351     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
11352     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
11353     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
11354     __FILE__,VInit,group);
11355   theCommands.Add("vclose" ,
11356     "[view_id [keep_context=0|1]]\n"
11357     "or vclose ALL - to remove all created views\n"
11358     " - removes view(viewer window) defined by its view_id.\n"
11359     " - keep_context: by default 0; if 1 and the last view is deleted"
11360     " the current context is not removed.",
11361     __FILE__,VClose,group);
11362   theCommands.Add("vactivate" ,
11363     "view_id"
11364     " - activates view(viewer window) defined by its view_id",
11365     __FILE__,VActivate,group);
11366   theCommands.Add("vviewlist",
11367     "vviewlist [format={tree, long}]"
11368     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
11369     " - format: format of result output, if tree the output is a tree view;"
11370     "otherwise it's a list of full view names. By default format = tree",
11371     __FILE__,VViewList,group);
11372   theCommands.Add("vhelp" ,
11373     "vhelp            : display help on the viewer commands",
11374     __FILE__,VHelp,group);
11375   theCommands.Add("vtop" ,
11376     "vtop or <T>      : Top view. Orientation +X+Y" ,
11377     __FILE__,VTop,group);
11378   theCommands.Add("vbottom" ,
11379     "vbottom          : Bottom view. Orientation +X-Y" ,
11380     __FILE__,VBottom,group);
11381   theCommands.Add("vleft" ,
11382     "vleft            : Left view. Orientation -Y+Z" ,
11383     __FILE__,VLeft,group);
11384   theCommands.Add("vright" ,
11385     "vright           : Right view. Orientation +Y+Z" ,
11386     __FILE__,VRight,group);
11387   theCommands.Add("vaxo" ,
11388     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
11389     __FILE__,VAxo,group);
11390   theCommands.Add("vfront" ,
11391     "vfront           : Front view. Orientation +X+Z" ,
11392     __FILE__,VFront,group);
11393   theCommands.Add("vback" ,
11394     "vback            : Back view. Orientation -X+Z" ,
11395     __FILE__,VBack,group);
11396   theCommands.Add("vpick" ,
11397     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
11398     VPick,group);
11399   theCommands.Add("vfit",
11400     "vfit or <F> [-selected] [-noupdate]"
11401     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
11402     __FILE__,VFit,group);
11403   theCommands.Add ("vfitarea",
11404     "vfitarea x1 y1 x2 y2"
11405     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
11406     "\n\t\t: Fit view to show area located between two points"
11407     "\n\t\t: given in world 2D or 3D corrdinates.",
11408     __FILE__, VFitArea, group);
11409   theCommands.Add ("vzfit", "vzfit [scale]\n"
11410     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
11411     "   \"scale\" - specifies factor to scale computed z range.\n",
11412     __FILE__, VZFit, group);
11413   theCommands.Add("vrepaint",
11414             "vrepaint [-immediate]"
11415     "\n\t\t: force redraw",
11416     __FILE__,VRepaint,group);
11417   theCommands.Add("vclear",
11418     "vclear          : vclear"
11419     "\n\t\t: remove all the object from the viewer",
11420     __FILE__,VClear,group);
11421   theCommands.Add("vsetbg",
11422     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
11423     __FILE__,VSetBg,group);
11424   theCommands.Add("vsetbgmode",
11425     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
11426     __FILE__,VSetBgMode,group);
11427   theCommands.Add("vsetgradientbg",
11428     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
11429     __FILE__,VSetGradientBg,group);
11430   theCommands.Add("vsetgrbgmode",
11431     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
11432     __FILE__,VSetGradientBgMode,group);
11433   theCommands.Add("vsetcolorbg",
11434     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
11435     __FILE__,VSetColorBg,group);
11436   theCommands.Add("vsetdefaultbg",
11437     "vsetdefaultbg r g b\n"
11438     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
11439     "\n\t\t: Set default viewer background fill color (flat/gradient).",
11440     __FILE__,VSetDefaultBg,group);
11441   theCommands.Add("vscale",
11442     "vscale          : vscale X Y Z",
11443     __FILE__,VScale,group);
11444   theCommands.Add("vzbufftrihedron",
11445             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
11446     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
11447     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
11448     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
11449     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
11450     "\n\t\t: Displays a trihedron",
11451     __FILE__,VZBuffTrihedron,group);
11452   theCommands.Add("vrotate",
11453     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
11454     "\n                : Option -mouseStart starts rotation according to the mouse position"
11455     "\n                : Option -mouseMove continues rotation with angle computed"
11456     "\n                : from last and new mouse position."
11457     "\n                : vrotate AX AY AZ [X Y Z]",
11458     __FILE__,VRotate,group);
11459   theCommands.Add("vzoom",
11460     "vzoom           : vzoom coef",
11461     __FILE__,VZoom,group);
11462   theCommands.Add("vpan",
11463     "vpan            : vpan dx dy",
11464     __FILE__,VPan,group);
11465   theCommands.Add("vexport",
11466     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
11467     " : exports the view to a vector file of a given format"
11468     " : notice that EMF format requires patched gl2ps",
11469     __FILE__,VExport,group);
11470   theCommands.Add("vcolorscale",
11471     "vcolorscale name [-noupdate|-update] [-demo]"
11472     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
11473     "\n\t\t:       [-font HeightFont=20]"
11474     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
11475     "\n\t\t:       [-smoothTransition {on|off}=off]"
11476     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
11477     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
11478     "\n\t\t:       [-textpos {left|right|center|none}=right]"
11479     "\n\t\t:       [-labelAtBorder {on|off}=on]"
11480     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
11481     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
11482     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
11483     "\n\t\t:       [-xy Left=0 Bottom=0]"
11484     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
11485     "\n\t\t:  -colors   - set colors for all intervals"
11486     "\n\t\t:  -color    - set color for specific interval"
11487     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
11488     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
11489     "\n\t\t:              at border means the value inbetween neighbor intervals,"
11490     "\n\t\t:              at center means the center value within current interval"
11491     "\n\t\t:  -labels   - set labels for all intervals"
11492     "\n\t\t:  -freeLabels - same as -labels but does not require"
11493     "\n\t\t:              matching the number of intervals"
11494     "\n\t\t:  -label    - set label for specific interval"
11495     "\n\t\t:  -title    - set title"
11496     "\n\t\t:  -reversed - setup smooth color transition between intervals"
11497     "\n\t\t:  -smoothTransition - swap colorscale direction"
11498     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
11499     __FILE__, VColorScale, group);
11500   theCommands.Add("vgraduatedtrihedron",
11501     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
11502     "\t[-namefont Name] [-valuesfont Name]\n"
11503     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
11504     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
11505     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
11506     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
11507     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
11508     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
11509     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
11510     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
11511     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
11512     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
11513     " - Displays or erases graduated trihedron"
11514     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
11515     " - namefont - font of axes names. Default: Arial\n"
11516     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
11517     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
11518     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
11519     " - valuesfont - font of axes values. Default: Arial\n"
11520     " - xcolor, ycolor, zcolor - color of axis and values\n"
11521     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
11522     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
11523     __FILE__,VGraduatedTrihedron,group);
11524   theCommands.Add("vtile" ,
11525             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
11526     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
11527     "\n\t\t:  -totalSize the size of virtual bigger viewport"
11528     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
11529     "\n\t\t:  -lowerLeft tile offset as lower left corner"
11530     "\n\t\t:  -upperLeft tile offset as upper left corner",
11531     __FILE__, VTile, group);
11532   theCommands.Add("vzlayer",
11533               "vzlayer [layerId]"
11534       "\n\t\t:         [-add|-delete|-get|-settings]"
11535       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
11536       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
11537       "\n\t\t: ZLayer list management:"
11538       "\n\t\t:   -add      add new z layer to viewer and print its id"
11539       "\n\t\t:   -delete   delete z layer"
11540       "\n\t\t:   -get      print sequence of z layers"
11541       "\n\t\t:   -settings print status of z layer settings"
11542       "\n\t\t:   -disable  disables given setting"
11543       "\n\t\t:   -enable   enables  given setting",
11544     __FILE__,VZLayer,group);
11545   theCommands.Add("vlayerline",
11546     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
11547     __FILE__,VLayerLine,group);
11548   theCommands.Add ("vgrid",
11549     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
11550     " : Mode - rectangular or circular"
11551     " : Type - lines or points",
11552     __FILE__, VGrid, group);
11553   theCommands.Add ("vpriviledgedplane",
11554     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
11555     "\n\t\t:   Ox, Oy, Oz - plane origin"
11556     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
11557     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
11558     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
11559     __FILE__, VPriviledgedPlane, group);
11560   theCommands.Add ("vconvert",
11561     "vconvert v [Mode={window|view}]"
11562     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
11563     "\n\t\t: vconvert x y z [Mode={window|grid}]"
11564     "\n\t\t:   window - convert to window coordinates, pixels"
11565     "\n\t\t:   view   - convert to view projection plane"
11566     "\n\t\t:   grid   - convert to model coordinates, given on grid"
11567     "\n\t\t:   ray    - convert projection ray to model coordiantes"
11568     "\n\t\t: - vconvert v window : convert view to window;"
11569     "\n\t\t: - vconvert v view   : convert window to view;"
11570     "\n\t\t: - vconvert x y window : convert view to window;"
11571     "\n\t\t: - vconvert x y view : convert window to view;"
11572     "\n\t\t: - vconvert x y : convert window to model;"
11573     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
11574     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
11575     "\n\t\t: - vconvert x y z window : convert model to window;"
11576     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
11577     "\n\t\t: Converts the given coordinates to window/view/model space.",
11578     __FILE__, VConvert, group);
11579   theCommands.Add ("vfps",
11580     "vfps [framesNb=100] : estimate average frame rate for active view",
11581     __FILE__, VFps, group);
11582   theCommands.Add ("vgldebug",
11583             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
11584     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
11585     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
11586     "\n\t\t: Debug context can be requested only on Windows"
11587     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
11588     "\n\t\t:  -sync     - request synchronized debug GL context"
11589     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
11590     "\n\t\t:              which are suppressed by default,"
11591     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
11592     "\n\t\t:              which are suppressed by default",
11593     __FILE__, VGlDebug, group);
11594   theCommands.Add ("vvbo",
11595     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
11596     __FILE__, VVbo, group);
11597   theCommands.Add ("vstereo",
11598             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
11599     "\n\t\t:         [-anaglyph Filter]"
11600     "\n\t\t: Control stereo output mode. Available modes for -mode:"
11601     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
11602     "\n\t\t:                     requires driver support."
11603     "\n\t\t:                     Should be called BEFORE vinit!"
11604     "\n\t\t:  anaglyph         - Anaglyph glasses"
11605     "\n\t\t:  rowInterlaced    - row-interlaced display"
11606     "\n\t\t:  columnInterlaced - column-interlaced display"
11607     "\n\t\t:  chessBoard       - chess-board output"
11608     "\n\t\t:  sideBySide       - horizontal pair"
11609     "\n\t\t:  overUnder        - vertical   pair"
11610     "\n\t\t: Available Anaglyph filters for -anaglyph:"
11611     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
11612     "\n\t\t:  greenMagentaSimple",
11613     __FILE__, VStereo, group);
11614   theCommands.Add ("vcaps",
11615             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
11616     "\n\t\t:       [-compatibleProfile {0|1}]"
11617     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
11618     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
11619     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
11620     "\n\t\t: Modify particular graphic driver options:"
11621     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
11622     "\n\t\t:             built-in GLSL programs"
11623     "\n\t\t:            (requires compatible profile)"
11624     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
11625     "\n\t\t:             arrays to GPU memory)"
11626     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
11627     "\n\t\t:  vsync    - switch VSync on or off"
11628     "\n\t\t:  winBuffer - allow using window buffer for rendering"
11629     "\n\t\t: Context creation options:"
11630     "\n\t\t:  softMode          - software OpenGL implementation"
11631     "\n\t\t:  compatibleProfile - backward-compatible profile"
11632     "\n\t\t:  quadbuffer        - QuadBuffer"
11633     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
11634     "\n\t\t: rendering paths producing the same visual result when"
11635     "\n\t\t: possible."
11636     "\n\t\t: Command is intended for testing old hardware compatibility.",
11637     __FILE__, VCaps, group);
11638   theCommands.Add ("vmemgpu",
11639     "vmemgpu [f]: print system-dependent GPU memory information if available;"
11640     " with f option returns free memory in bytes",
11641     __FILE__, VMemGpu, group);
11642   theCommands.Add ("vreadpixel",
11643     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
11644     " : Read pixel value for active view",
11645     __FILE__, VReadPixel, group);
11646   theCommands.Add("diffimage",
11647             "diffimage imageFile1 imageFile2 [diffImageFile]"
11648     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
11649     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
11650     "\n\t\t: Compare two images by content and generate difference image."
11651     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
11652     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
11653     __FILE__, VDiffImage, group);
11654   theCommands.Add ("vselect",
11655     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
11656     "- emulates different types of selection:\n"
11657     "- 1) single click selection\n"
11658     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
11659     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
11660     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
11661     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
11662     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
11663     " (partial inclusion - overlap - is not allowed by default)\n"
11664     "- 5) any of these selections with shift button pressed",
11665     __FILE__, VSelect, group);
11666   theCommands.Add ("vmoveto",
11667     "vmoveto x y"
11668     "- emulates cursor movement to pixel postion (x,y)",
11669     __FILE__, VMoveTo, group);
11670   theCommands.Add ("vviewparams",
11671               "vviewparams [-args] [-scale [s]]"
11672       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
11673       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
11674       "\n\t\t: Manage current view parameters or prints all"
11675       "\n\t\t: current values when called without argument."
11676       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
11677       "\n\t\t:   -eye  [x y z] prints or sets eye location"
11678       "\n\t\t:   -at   [x y z] prints or sets center of look"
11679       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
11680       "\n\t\t:   -proj [x y z] prints or sets direction of look"
11681       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
11682       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
11683       "\n\t\t:                 or changes the size of its maximum dimension"
11684       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
11685     __FILE__, VViewParams, group);
11686
11687   theCommands.Add("vanimation", "Alias for vanim",
11688     __FILE__, VAnimation, group);
11689
11690   theCommands.Add("vanim",
11691             "List existing animations:"
11692     "\n\t\t:  vanim"
11693     "\n\t\t: Animation playback:"
11694     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
11695     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
11696     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
11697     "\n\t\t:   -freeLook skip camera animations"
11698     "\n\t\t:   -lockLoop disable any interactions"
11699     "\n\t\t:"
11700     "\n\t\t: Animation definition:"
11701     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
11702     "\n\t\t:        [start TimeSec] [duration TimeSec]"
11703     "\n\t\t:"
11704     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
11705     "\n\t\t: specifies nested animations."
11706     "\n\t\t: There is no syntax to explicitly add new animation,"
11707     "\n\t\t: and all non-existing animations within the name will be"
11708     "\n\t\t: implicitly created on first use (including parents)."
11709     "\n\t\t:"
11710     "\n\t\t: Each animation might define the SINGLE action (see below),"
11711     "\n\t\t: like camera transition, object transformation or custom callback."
11712     "\n\t\t: Child animations can be used for defining concurrent actions."
11713     "\n\t\t:"
11714     "\n\t\t: Camera animation:"
11715     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
11716     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
11717     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
11718     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
11719     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
11720     "\n\t\t:   -atX    camera Center positions pair"
11721     "\n\t\t:   -upX    camera Up directions pair"
11722     "\n\t\t:   -scaleX camera Scale factors pair"
11723     "\n\t\t: Object animation:"
11724     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
11725     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
11726     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
11727     "\n\t\t:   -locX   object Location points pair (translation)"
11728     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
11729     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
11730     "\n\t\t: Custom callback:"
11731     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
11732     "\n\t\t:   %Pts        overall animation presentation timestamp"
11733     "\n\t\t:   %LocalPts   local animation timestamp"
11734     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
11735     "\n\t\t:"
11736     "\n\t\t: Video recording:"
11737     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
11738     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
11739     "\n\t\t:             [-crf Value] [-preset Preset]"
11740     "\n\t\t:   -fps     video framerate"
11741     "\n\t\t:   -format  file format, container (matroska, etc.)"
11742     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
11743     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
11744     "\n\t\t:   -crf     constant rate factor (specific to codec)"
11745     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
11746     __FILE__, VAnimation, group);
11747
11748   theCommands.Add("vchangeselected",
11749     "vchangeselected shape"
11750     "- adds to shape to selection or remove one from it",
11751                 __FILE__, VChangeSelected, group);
11752   theCommands.Add ("vnbselected",
11753     "vnbselected"
11754     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
11755   theCommands.Add ("vcamera",
11756               "vcamera [-ortho] [-projtype]"
11757       "\n\t\t:         [-persp]"
11758       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
11759       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
11760       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
11761       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
11762       "\n\t\t: Manage camera parameters."
11763       "\n\t\t: Prints current value when option called without argument."
11764       "\n\t\t: Orthographic camera:"
11765       "\n\t\t:   -ortho      activate orthographic projection"
11766       "\n\t\t: Perspective camera:"
11767       "\n\t\t:   -persp      activate perspective  projection (mono)"
11768       "\n\t\t:   -fovy       field of view in y axis, in degrees"
11769       "\n\t\t:   -distance   distance of eye from camera center"
11770       "\n\t\t: Stereoscopic camera:"
11771       "\n\t\t:   -stereo     perspective  projection (stereo)"
11772       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
11773       "\n\t\t:   -rightEye   perspective  projection (right eye)"
11774       "\n\t\t:   -iod        intraocular distance value"
11775       "\n\t\t:   -iodType    distance type, absolute or relative"
11776       "\n\t\t:   -zfocus     stereographic focus value"
11777       "\n\t\t:   -zfocusType focus type, absolute or relative",
11778     __FILE__, VCamera, group);
11779   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
11780     "- vautozfit [on={1|0}] [scale]\n"
11781     "    Prints or changes parameters of automatic z-fit mode:\n"
11782     "   \"on\" - turns automatic z-fit on or off\n"
11783     "   \"scale\" - specifies factor to scale computed z range.\n",
11784     __FILE__, VAutoZFit, group);
11785   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
11786     "   vzrange                - without parameters shows current values\n"
11787     "   vzrange [znear] [zfar] - applies provided values to view",
11788     __FILE__,VZRange, group);
11789   theCommands.Add ("vpurgedisplay",
11790     "vpurgedisplay"
11791     "- removes structures which don't belong to objects displayed in neutral point",
11792     __FILE__, VPurgeDisplay, group);
11793   theCommands.Add("vsetviewsize",
11794     "vsetviewsize size",
11795     __FILE__,VSetViewSize,group);
11796   theCommands.Add("vmoveview",
11797     "vmoveview Dx Dy Dz [Start = 1|0]",
11798     __FILE__,VMoveView,group);
11799   theCommands.Add("vtranslateview",
11800     "vtranslateview Dx Dy Dz [Start = 1|0)]",
11801     __FILE__,VTranslateView,group);
11802   theCommands.Add("vturnview",
11803     "vturnview Ax Ay Az [Start = 1|0]",
11804     __FILE__,VTurnView,group);
11805   theCommands.Add("vtextureenv",
11806     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
11807     "or user-defined file and optionally applying texture mapping parameters\n"
11808     "                  Usage:\n"
11809     "                  vtextureenv off - disables environment mapping\n"
11810     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
11811     "                              std_texture = (0..7)\n"
11812     "                              rep         = {clamp|repeat}\n"
11813     "                              mod         = {decal|modulate}\n"
11814     "                              flt         = {nearest|bilinear|trilinear}\n"
11815     "                              ss, st      - scale factors for s and t texture coordinates\n"
11816     "                              ts, tt      - translation for s and t texture coordinates\n"
11817     "                              rot         - texture rotation angle in degrees",
11818     __FILE__, VTextureEnv, group);
11819   theCommands.Add("vhlr",
11820             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
11821       "\n\t\t: Hidden Line Removal algorithm."
11822       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
11823       "\n\t\t:   -algoType   type of HLR algorithm.\n",
11824     __FILE__,VHLR,group);
11825   theCommands.Add("vhlrtype",
11826               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
11827       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
11828       "\n\t\t:   'algo' - exact HLR algorithm is applied"
11829       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
11830       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
11831     __FILE__,VHLRType,group);
11832   theCommands.Add("vclipplane",
11833               "vclipplane planeName [{0|1}]"
11834       "\n\t\t:   [-equation A B C D]"
11835       "\n\t\t:   [-set|-unset [objects|views]]"
11836       "\n\t\t:   [-maxPlanes]"
11837       "\n\t\t:   [-capping {0|1}]"
11838       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
11839       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
11840       "\n\t\t:       [-texRotate Angle]"
11841       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
11842       "\n\t\t:       [-useObjShader {0|1}]"
11843       "\n\t\t: Clipping planes management:"
11844       "\n\t\t:   -maxPlanes   print plane limit for view"
11845       "\n\t\t:   -delete      delete plane with given name"
11846       "\n\t\t:   {off|on|0|1} turn clipping on/off"
11847       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
11848       "\n\t\t:                applied to active View when list is omitted"
11849       "\n\t\t:   -equation A B C D change plane equation"
11850       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
11851       "\n\t\t: Capping options:"
11852       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
11853       "\n\t\t:   -color R G B          set capping color"
11854       "\n\t\t:   -texName Texture      set capping texture"
11855       "\n\t\t:   -texScale SX SY       set capping tex scale"
11856       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
11857       "\n\t\t:   -texRotate Angle      set capping tex rotation"
11858       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
11859       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
11860       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
11861       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
11862       __FILE__, VClipPlane, group);
11863   theCommands.Add("vdefaults",
11864                "vdefaults [-absDefl value]"
11865        "\n\t\t:           [-devCoeff value]"
11866        "\n\t\t:           [-angDefl value]"
11867        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
11868     , __FILE__, VDefaults, group);
11869   theCommands.Add("vlight",
11870     "tool to manage light sources, without arguments shows list of lights."
11871     "\n    Main commands: "
11872     "\n      'clear' to clear lights"
11873     "\n      '{def}aults' to load deafault lights"
11874     "\n      'add' (or 'new') <type> to add any light source"
11875     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
11876     "\n      'change' <lightId> to edit light source with specified lightId"
11877     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
11878     "\n        {pos}ition X Y Z"
11879     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
11880     "\n        color colorName"
11881     "\n        {head}light 0|1"
11882     "\n        {sm}oothness value"
11883     "\n        {int}ensity value"
11884     "\n        {constAtten}uation value"
11885     "\n        {linearAtten}uation value"
11886     "\n        angle angleDeg"
11887     "\n        {spotexp}onent value"
11888     "\n        local|global"
11889     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
11890     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
11891     __FILE__, VLight, group);
11892   theCommands.Add("vraytrace",
11893             "vraytrace [0|1]"
11894     "\n\t\t: Turns on/off ray-tracing renderer."
11895     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
11896     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
11897     __FILE__, VRenderParams, group);
11898   theCommands.Add("vrenderparams",
11899     "\n    Manages rendering parameters: "
11900     "\n      '-raster'                   Disables GPU ray-tracing"
11901     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
11902     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
11903     "\n      '-rendScale    value        Rendering resolution scale factor"
11904     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
11905     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
11906     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
11907     "\n      '-reflections  on|off'      Enables/disables specular reflections"
11908     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
11909     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
11910     "\n      '-gi           on|off'      Enables/disables global illumination effects"
11911     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
11912     "\n      '-env          on|off'      Enables/disables environment map background"
11913     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
11914     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
11915     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
11916     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
11917     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
11918     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
11919     "\n      '-shadingModel model'       Controls shading model from enumeration"
11920     "\n                                  color, flat, gouraud, phong"
11921     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
11922     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
11923     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
11924     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
11925     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
11926     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
11927     "\n    Unlike vcaps, these parameters dramatically change visual properties."
11928     "\n    Command is intended to control presentation quality depending on"
11929     "\n    hardware capabilities and performance.",
11930     __FILE__, VRenderParams, group);
11931   theCommands.Add("vfrustumculling",
11932     "vfrustumculling [toEnable]: enables/disables objects clipping",
11933     __FILE__,VFrustumCulling,group);
11934   theCommands.Add("vhighlightselected",
11935     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
11936     "Without arguments it shows if highlighting of selected objects is enabled now.",
11937     __FILE__,VHighlightSelected,group);
11938   theCommands.Add ("vplace",
11939             "vplace dx dy"
11940     "\n\t\t: Places the point (in pixels) at the center of the window",
11941     __FILE__, VPlace, group);
11942   theCommands.Add("vxrotate",
11943     "vxrotate",
11944     __FILE__,VXRotate,group);
11945
11946     theCommands.Add("vmanipulator",
11947       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
11948       "\n    tool to create and manage AIS manipulators."
11949       "\n    Options: "
11950       "\n      '-attach AISObject'                 attach manipulator to AISObject"
11951       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
11952       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
11953       "\n      '-enableModes    {0|1}'             enable modes when attaching"
11954       "\n      '-detach'                           detach manipulator"
11955       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
11956       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
11957       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
11958       "\n      '-move x y z'                     - move attached object"
11959       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
11960       "\n      '-scale factor'                   - scale attached object"
11961       "\n      '-autoActivate      {0|1}'        - set activation on detection"
11962       "\n      '-followTranslation {0|1}'        - set following translation transform"
11963       "\n      '-followRotation    {0|1}'        - set following rotation transform"
11964       "\n      '-gap value'                      - set gap between sub-parts"
11965       "\n      '-part axis mode    {0|1}'        - set visual part"
11966       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
11967       "\n      '-size value'                     - set size of manipulator"
11968       "\n      '-zoomable {0|1}'                 - set zoom persistence",
11969     __FILE__, VManipulator, group);
11970
11971   theCommands.Add("vselprops",
11972     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
11973     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
11974     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
11975     "\n    -pickStrategy {first|topmost} : defines picking strategy"
11976     "\n                            'first'   to pick first acceptable (default)"
11977     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
11978     "\n    -pixTol    value        : sets up pixel tolerance"
11979     "\n    -dispMode  dispMode     : sets display mode for highlighting"
11980     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
11981     "\n    -color     {name|r g b} : sets highlight color"
11982     "\n    -transp    value        : sets transparency coefficient for highlight"
11983     "\n    -material  material     : sets highlight material"
11984     "\n    -print                  : prints current state of all mentioned parameters",
11985     __FILE__, VSelectionProperties, group);
11986
11987   theCommands.Add ("vseldump",
11988                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
11989                    "\n\t\t: Generate an image based on detection results:"
11990                    "\n\t\t:   depth       normalized depth values"
11991                    "\n\t\t:   unnormDepth unnormalized depth values"
11992                    "\n\t\t:   object      color of detected object"
11993                    "\n\t\t:   owner       color of detected owner"
11994                    "\n\t\t:   selMode     color of selection mode"
11995                    "\n\t\t:   entity      color of etected entity",
11996                    __FILE__, VDumpSelectionImage, group);
11997
11998 #if defined(_WIN32)
11999   theCommands.Add("vprogressive",
12000     "vprogressive",
12001     __FILE__, VProgressiveMode, group);
12002 #endif
12003 }