0029735: Draw Harness - command to set 2D mode for viewer in ViewerTest package
[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 //! Setting additional flag to store 2D mode of the View to avoid scene rotation by mouse/key events
173 class ViewerTest_V3dView : public V3d_View
174 {
175   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_V3dView, V3d_View)
176 public:
177   //! Initializes the view.
178   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType = V3d_ORTHOGRAPHIC,
179                       bool theIs2dMode = false)
180   : V3d_View (theViewer, theType), myIs2dMode (theIs2dMode) {}
181
182   //! Initializes the view by copying.
183   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
184   : V3d_View (theViewer, theView), myIs2dMode (false)
185   {
186     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (theView))
187     {
188       myIs2dMode = aV3dView->IsViewIn2DMode();
189     }
190   }
191
192   //! Returns true if 2D mode is set for the view
193   bool IsViewIn2DMode() const { return myIs2dMode; }
194
195   //! Sets 2D mode for the view
196   void SetView2DMode (bool the2dMode) { myIs2dMode = the2dMode; }
197
198 public:
199
200   //! Returns true if active view in 2D mode.
201   static bool IsCurrentViewIn2DMode()
202   {
203     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
204     {
205       return aV3dView->IsViewIn2DMode();
206     }
207     return false;
208   }
209
210   //! Set if active view in 2D mode.
211   static void SetCurrentView2DMode (bool theIs2d)
212   {
213     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
214     {
215       aV3dView->SetView2DMode (theIs2d);
216     }
217   }
218
219 private:
220
221   Standard_Boolean myIs2dMode; //!< 2D mode flag
222
223 };
224
225 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
226 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
227 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
228 static OpenGl_Caps ViewerTest_myDefaultCaps;
229
230 static void OSWindowSetup();
231
232 static struct
233 {
234   Quantity_Color FlatColor;
235   Quantity_Color GradientColor1;
236   Quantity_Color GradientColor2;
237   Aspect_GradientFillMethod FillMethod;
238 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
239
240 //==============================================================================
241 //  EVENT GLOBAL VARIABLES
242 //==============================================================================
243
244 static int Start_Rot = 0;
245 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
246 int X_Motion = 0; // Current cursor position
247 int Y_Motion = 0;
248 int X_ButtonPress = 0; // Last ButtonPress position
249 int Y_ButtonPress = 0;
250 Standard_Boolean IsDragged = Standard_False;
251 Standard_Boolean DragFirst = Standard_False;
252 Standard_Boolean TheIsAnimating = Standard_False;
253 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
254 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
255
256
257 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
258 {
259   static Handle(AIS_RubberBand) aBand;
260   if (aBand.IsNull())
261   {
262     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
263     aBand->SetDisplayMode (0);
264   }
265   return aBand;
266 }
267
268 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
269
270 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
271 {
272   static ViewerTest_MapOfAISManipulators aMap;
273   return aMap;
274 }
275
276 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
277 {
278   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
279   for (; anIt.More(); anIt.Next())
280   {
281     if (anIt.Value()->HasActiveMode())
282     {
283       return anIt.Value();
284     }
285   }
286   return NULL;
287 }
288
289 //==============================================================================
290
291 #ifdef _WIN32
292 static LRESULT WINAPI ViewerWindowProc(
293                                        HWND hwnd,
294                                        UINT uMsg,
295                                        WPARAM wParam,
296                                        LPARAM lParam );
297 static LRESULT WINAPI AdvViewerWindowProc(
298   HWND hwnd,
299   UINT uMsg,
300   WPARAM wParam,
301   LPARAM lParam );
302 #endif
303
304
305 //==============================================================================
306 //function : WClass
307 //purpose  :
308 //==============================================================================
309
310 const Handle(Standard_Transient)& ViewerTest::WClass()
311 {
312   static Handle(Standard_Transient) theWClass;
313 #if defined(_WIN32)
314   if (theWClass.IsNull())
315   {
316     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
317                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
318                                 ::LoadCursor (NULL, IDC_ARROW));
319   }
320 #endif
321   return theWClass;
322 }
323
324 //==============================================================================
325 //function : CreateName
326 //purpose  : Create numerical name for new object in theMap
327 //==============================================================================
328 template <typename ObjectType>
329 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
330                                     const TCollection_AsciiString& theDefaultString)
331 {
332   if (theObjectMap.IsEmpty())
333     return theDefaultString + TCollection_AsciiString(1);
334
335   Standard_Integer aNextKey = 1;
336   Standard_Boolean isFound = Standard_False;
337   while (!isFound)
338   {
339     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
340     // Look for objects with default names
341     if (theObjectMap.IsBound1(aStringKey))
342     {
343       aNextKey++;
344     }
345     else
346       isFound = Standard_True;
347   }
348
349   return theDefaultString + TCollection_AsciiString(aNextKey);
350 }
351
352 //==============================================================================
353 //structure : ViewerTest_Names
354 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
355 //==============================================================================
356 struct ViewerTest_Names
357 {
358 private:
359   TCollection_AsciiString myDriverName;
360   TCollection_AsciiString myViewerName;
361   TCollection_AsciiString myViewName;
362
363 public:
364
365   const TCollection_AsciiString& GetDriverName () const
366   {
367     return myDriverName;
368   }
369   void SetDriverName (const TCollection_AsciiString& theDriverName)
370   {
371     myDriverName = theDriverName;
372   }
373   const TCollection_AsciiString& GetViewerName () const
374   {
375     return myViewerName;
376   }
377   void SetViewerName (const TCollection_AsciiString& theViewerName)
378   {
379     myViewerName = theViewerName;
380   }
381   const TCollection_AsciiString& GetViewName () const
382   {
383     return myViewName;
384   }
385   void SetViewName (const TCollection_AsciiString& theViewName)
386   {
387     myViewName = theViewName;
388   }
389
390   //===========================================================================
391   //function : Constructor for ViewerTest_Names
392   //purpose  : Get view, viewer, driver names from custom string
393   //===========================================================================
394
395   ViewerTest_Names (const TCollection_AsciiString& theInputString)
396   {
397     TCollection_AsciiString aName(theInputString);
398     if (theInputString.IsEmpty())
399     {
400       // Get current configuration
401       if (ViewerTest_myDrivers.IsEmpty())
402         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
403           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
404       else
405         myDriverName = ViewerTest_myDrivers.Find2
406         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
407
408       if(ViewerTest_myContexts.IsEmpty())
409       {
410         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
411           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
412       }
413       else
414       {
415         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
416       }
417
418       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
419     }
420     else
421     {
422       // There is at least view name
423       Standard_Integer aParserNumber = 0;
424       for (Standard_Integer i = 0; i < 3; ++i)
425       {
426         Standard_Integer aParserPos = aName.SearchFromEnd("/");
427         if(aParserPos != -1)
428         {
429           aParserNumber++;
430           aName.Split(aParserPos-1);
431         }
432         else
433           break;
434       }
435       if (aParserNumber == 0)
436       {
437         // Only view name
438         if (!ViewerTest::GetAISContext().IsNull())
439         {
440           myDriverName = ViewerTest_myDrivers.Find2
441           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
442           myViewerName = ViewerTest_myContexts.Find2
443           (ViewerTest::GetAISContext());
444         }
445         else
446         {
447           // There is no opened contexts here, need to create names for viewer and driver
448           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
449             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
450
451           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
452             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
453         }
454         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
455       }
456       else if (aParserNumber == 1)
457       {
458         // Here is viewerName/viewName
459         if (!ViewerTest::GetAISContext().IsNull())
460           myDriverName = ViewerTest_myDrivers.Find2
461           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
462         else
463         {
464           // There is no opened contexts here, need to create name for driver
465           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
466             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
467         }
468         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
469
470         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
471       }
472       else
473       {
474         //Here is driverName/viewerName/viewName
475         myDriverName = TCollection_AsciiString(aName);
476
477         TCollection_AsciiString aViewerName(theInputString);
478         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
479         myViewerName = TCollection_AsciiString(aViewerName);
480
481         myViewName = TCollection_AsciiString(theInputString);
482       }
483     }
484   }
485 };
486
487 //==============================================================================
488 //function : FindContextByView
489 //purpose  : Find AIS_InteractiveContext by View
490 //==============================================================================
491
492 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
493 {
494   Handle(AIS_InteractiveContext) anAISContext;
495
496   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
497        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
498   {
499     if (anIter.Value()->CurrentViewer() == theView->Viewer())
500        return anIter.Key2();
501   }
502   return anAISContext;
503 }
504
505
506 //==============================================================================
507 //function : SetWindowTitle
508 //purpose  : Set window title
509 //==============================================================================
510
511 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
512                      Standard_CString theTitle)
513 {
514 #if defined(_WIN32)
515   const TCollection_ExtendedString theTitleW (theTitle);
516   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
517 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
518   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
519 #else
520   if(GetDisplayConnection()->GetDisplay())
521   {
522     Window aWindow =
523       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
524     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
525   }
526 #endif
527 }
528
529 //==============================================================================
530 //function : IsWindowOverlapped
531 //purpose  : Check if theWindow overlapp another view
532 //==============================================================================
533
534 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
535                                      const Standard_Integer thePxTop,
536                                      const Standard_Integer thePxRight,
537                                      const Standard_Integer thePxBottom,
538                                      TCollection_AsciiString& theViewId)
539 {
540   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
541       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
542   {
543     Standard_Integer aTop = 0,
544       aLeft = 0,
545       aRight = 0,
546       aBottom = 0;
547     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
548     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
549         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
550         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
551         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
552     {
553       theViewId = anIter.Key1();
554       return Standard_True;
555     }
556   }
557   return Standard_False;
558 }
559
560 // Workaround: to create and delete non-orthographic views outside ViewerTest
561 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
562 {
563   ViewerTest_myViews.UnBind1 (theName);
564 }
565
566 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
567                                const Handle(V3d_View)& theView)
568 {
569   ViewerTest_myViews.Bind (theName, theView);
570 }
571
572 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
573 {
574   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
575 }
576 //==============================================================================
577 //function : ViewerInit
578 //purpose  : Create the window viewer and initialize all the global variable
579 //==============================================================================
580
581 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
582                                                 const Standard_Integer thePxTop,
583                                                 const Standard_Integer thePxWidth,
584                                                 const Standard_Integer thePxHeight,
585                                                 const TCollection_AsciiString& theViewName,
586                                                 const TCollection_AsciiString& theDisplayName,
587                                                 const Handle(V3d_View)& theViewToClone)
588 {
589   // Default position and dimension of the viewer window.
590   // Note that left top corner is set to be sufficiently small to have
591   // window fit in the small screens (actual for remote desktops, see #23003).
592   // The position corresponds to the window's client area, thus some
593   // gap is added for window frame to be visible.
594   Standard_Integer aPxLeft   = 20;
595   Standard_Integer aPxTop    = 40;
596   Standard_Integer aPxWidth  = 409;
597   Standard_Integer aPxHeight = 409;
598   Standard_Boolean toCreateViewer = Standard_False;
599   if (!theViewToClone.IsNull())
600   {
601     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
602   }
603
604   Handle(OpenGl_GraphicDriver) aGraphicDriver;
605   ViewerTest_Names aViewNames(theViewName);
606   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
607     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
608
609   if (thePxLeft != 0)
610     aPxLeft = thePxLeft;
611   if (thePxTop != 0)
612     aPxTop = thePxTop;
613   if (thePxWidth != 0)
614     aPxWidth = thePxWidth;
615   if (thePxHeight != 0)
616     aPxHeight = thePxHeight;
617
618   // Get graphic driver (create it or get from another view)
619   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
620   {
621     // Get connection string
622   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
623     TCollection_AsciiString aDisplayName(theDisplayName);
624     if (!aDisplayName.IsEmpty())
625       SetDisplayConnection (new Aspect_DisplayConnection ());
626     else
627       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
628   #else
629     (void)theDisplayName; // avoid warning on unused argument
630     SetDisplayConnection (new Aspect_DisplayConnection ());
631   #endif
632
633     if (Draw_VirtualWindows)
634     {
635       // don't waste the time waiting for VSync when window is not displayed on the screen
636       ViewerTest_myDefaultCaps.swapInterval = 0;
637       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
638       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
639     }
640     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
641     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
642
643     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
644     toCreateViewer = Standard_True;
645   }
646   else
647   {
648     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
649   }
650
651   //Dispose the window if input parameters are default
652   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
653   {
654     Standard_Integer aTop = 0,
655                      aLeft = 0,
656                      aRight = 0,
657                      aBottom = 0,
658                      aScreenWidth = 0,
659                      aScreenHeight = 0;
660
661     // Get screen resolution
662 #if defined(_WIN32) || defined(__WIN32__)
663     RECT aWindowSize;
664     GetClientRect(GetDesktopWindow(), &aWindowSize);
665     aScreenHeight = aWindowSize.bottom;
666     aScreenWidth = aWindowSize.right;
667 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
668     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
669 #else
670     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
671     aScreenWidth = WidthOfScreen(aScreen);
672     aScreenHeight = HeightOfScreen(aScreen);
673 #endif
674
675     TCollection_AsciiString anOverlappedViewId("");
676
677     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
678     {
679       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
680
681       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
682         && aRight + 2*aPxWidth + 40 > aScreenWidth)
683       {
684         if (aBottom + aPxHeight + 40 > aScreenHeight)
685         {
686           aPxLeft = 20;
687           aPxTop = 40;
688           break;
689         }
690         aPxLeft = 20;
691         aPxTop = aBottom + 40;
692       }
693       else
694         aPxLeft = aRight + 20;
695     }
696   }
697
698   // Get viewer name
699   TCollection_AsciiString aTitle("3D View - ");
700   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
701
702   // Change name of current active window
703   if (!ViewerTest::CurrentView().IsNull())
704   {
705     TCollection_AsciiString anActiveWindowTitle("3D View - ");
706     anActiveWindowTitle = anActiveWindowTitle
707       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
708     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
709   }
710
711   // Create viewer
712   Handle(V3d_Viewer) a3DViewer;
713   // If it's the single view, we first look for empty context
714   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
715   {
716     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
717       anIter(ViewerTest_myContexts);
718     if (anIter.More())
719       ViewerTest::SetAISContext (anIter.Value());
720     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
721   }
722   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
723   {
724     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
725     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
726   }
727   else if (a3DViewer.IsNull())
728   {
729     toCreateViewer = Standard_True;
730     a3DViewer = new V3d_Viewer(aGraphicDriver);
731     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
732     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
733                                            ViewerTest_DefaultBackground.GradientColor2,
734                                            ViewerTest_DefaultBackground.FillMethod);
735   }
736
737   // AIS context setup
738   if (ViewerTest::GetAISContext().IsNull() ||
739       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
740   {
741     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
742     ViewerTest::SetAISContext (aContext);
743     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
744   }
745   else
746   {
747     ViewerTest::ResetEventManager();
748   }
749
750   // Create window
751 #if defined(_WIN32)
752   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
753                                     Handle(WNT_WClass)::DownCast (WClass()),
754                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
755                                     aPxLeft, aPxTop,
756                                     aPxWidth, aPxHeight,
757                                     Quantity_NOC_BLACK);
758 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
759   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
760                                      aPxLeft, aPxTop,
761                                      aPxWidth, aPxHeight);
762   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
763 #else
764   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
765                                   aTitle.ToCString(),
766                                   aPxLeft, aPxTop,
767                                   aPxWidth, aPxHeight);
768 #endif
769   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
770
771   // View setup
772   Handle(V3d_View) aView;
773   if (!theViewToClone.IsNull())
774   {
775     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
776   }
777   else
778   {
779     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
780   }
781
782   aView->SetWindow (VT_GetWindow());
783   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
784
785   ViewerTest::CurrentView(aView);
786   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
787
788   // Setup for X11 or NT
789   OSWindowSetup();
790
791   // Set parameters for V3d_View and V3d_Viewer
792   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
793   aV3dView->SetComputedMode(Standard_False);
794
795   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
796   if (toCreateViewer)
797   {
798     a3DViewer->SetDefaultLights();
799     a3DViewer->SetLightOn();
800   }
801
802   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
803   #if TCL_MAJOR_VERSION  < 8
804   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
805       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
806   #else
807   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
808       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
809   #endif
810   #endif
811
812   VT_GetWindow()->Map();
813
814   // Set the handle of created view in the event manager
815   ViewerTest::ResetEventManager();
816
817   ViewerTest::CurrentView()->Redraw();
818
819   aView.Nullify();
820   a3DViewer.Nullify();
821
822   return aViewNames.GetViewName();
823 }
824
825 //==============================================================================
826 //function : RedrawAllViews
827 //purpose  : Redraw all created views
828 //==============================================================================
829 void ViewerTest::RedrawAllViews()
830 {
831   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
832   for (; aViewIt.More(); aViewIt.Next())
833   {
834     const Handle(V3d_View)& aView = aViewIt.Key2();
835     aView->Redraw();
836   }
837 }
838
839 //==============================================================================
840 //function : Vinit
841 //purpose  : Create the window viewer and initialize all the global variable
842 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
843 //==============================================================================
844
845 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
846 {
847   TCollection_AsciiString aViewName, aDisplayName;
848   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
849   Handle(V3d_View) aCopyFrom;
850   TCollection_AsciiString aName, aValue;
851   int is2dMode = -1;
852   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
853   {
854     const TCollection_AsciiString anArg = theArgVec[anArgIt];
855     TCollection_AsciiString anArgCase = anArg;
856     anArgCase.LowerCase();
857     if (anArgIt + 1 < theArgsNb
858      && anArgCase == "-name")
859     {
860       aViewName = theArgVec[++anArgIt];
861     }
862     else if (anArgIt + 1 < theArgsNb
863           && (anArgCase == "-left"
864            || anArgCase == "-l"))
865     {
866       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
867     }
868     else if (anArgIt + 1 < theArgsNb
869           && (anArgCase == "-top"
870            || anArgCase == "-t"))
871     {
872       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
873     }
874     else if (anArgIt + 1 < theArgsNb
875           && (anArgCase == "-width"
876            || anArgCase == "-w"))
877     {
878       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
879     }
880     else if (anArgIt + 1 < theArgsNb
881           && (anArgCase == "-height"
882            || anArgCase == "-h"))
883     {
884       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
885     }
886     else if (anArgCase == "-exitonclose")
887     {
888       Draw_ToExitOnCloseView = true;
889       if (anArgIt + 1 < theArgsNb
890        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
891       {
892         ++anArgIt;
893       }
894     }
895     else if (anArgCase == "-closeonescape"
896           || anArgCase == "-closeonesc")
897     {
898       Draw_ToCloseViewOnEsc = true;
899       if (anArgIt + 1 < theArgsNb
900        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
901       {
902         ++anArgIt;
903       }
904     }
905     else if (anArgCase == "-2d_mode"
906           || anArgCase == "-2dmode"
907           || anArgCase == "-2d")
908     {
909       bool toEnable = true;
910       if (anArgIt + 1 < theArgsNb
911        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
912       {
913         ++anArgIt;
914       }
915       is2dMode = toEnable ? 1 : 0;
916     }
917     else if (anArgIt + 1 < theArgsNb
918           && (anArgCase == "-disp"
919            || anArgCase == "-display"))
920     {
921       aDisplayName = theArgVec[++anArgIt];
922     }
923     else if (!ViewerTest::CurrentView().IsNull()
924           &&  aCopyFrom.IsNull()
925           && (anArgCase == "-copy"
926            || anArgCase == "-clone"
927            || anArgCase == "-cloneactive"
928            || anArgCase == "-cloneactiveview"))
929     {
930       aCopyFrom = ViewerTest::CurrentView();
931     }
932     // old syntax
933     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
934     {
935       aName.LowerCase();
936       if (aName == "name")
937       {
938         aViewName = aValue;
939       }
940       else if (aName == "l"
941             || aName == "left")
942       {
943         aPxLeft = aValue.IntegerValue();
944       }
945       else if (aName == "t"
946             || aName == "top")
947       {
948         aPxTop = aValue.IntegerValue();
949       }
950       else if (aName == "disp"
951             || aName == "display")
952       {
953         aDisplayName = aValue;
954       }
955       else if (aName == "w"
956             || aName == "width")
957       {
958         aPxWidth = aValue.IntegerValue();
959       }
960       else if (aName == "h"
961             || aName == "height")
962       {
963         aPxHeight = aValue.IntegerValue();
964       }
965       else
966       {
967         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
968         return 1;
969       }
970     }
971     else if (aViewName.IsEmpty())
972     {
973       aViewName = anArg;
974     }
975     else
976     {
977       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
978       return 1;
979     }
980   }
981
982 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
983   if (!aDisplayName.IsEmpty())
984   {
985     aDisplayName.Clear();
986     std::cout << "Warning: display parameter will be ignored.\n";
987   }
988 #endif
989
990   ViewerTest_Names aViewNames (aViewName);
991   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
992   {
993     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
994     theDi.Eval (aCommand.ToCString());
995     if (is2dMode != -1)
996     {
997       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
998     }
999     return 0;
1000   }
1001
1002   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
1003                                                             aViewName, aDisplayName, aCopyFrom);
1004   if (is2dMode != -1)
1005   {
1006     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1007   }
1008   theDi << aViewId;
1009   return 0;
1010 }
1011
1012 //! Parse HLR algo type.
1013 static Standard_Boolean parseHlrAlgoType (const char* theName,
1014                                           Prs3d_TypeOfHLR& theType)
1015 {
1016   TCollection_AsciiString aName (theName);
1017   aName.LowerCase();
1018   if (aName == "polyalgo")
1019   {
1020     theType = Prs3d_TOH_PolyAlgo;
1021   }
1022   else if (aName == "algo")
1023   {
1024     theType = Prs3d_TOH_Algo;
1025   }
1026   else
1027   {
1028     return Standard_False;
1029   }
1030   return Standard_True;
1031 }
1032
1033 //==============================================================================
1034 //function : VHLR
1035 //purpose  : hidden lines removal algorithm
1036 //==============================================================================
1037
1038 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1039 {
1040   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1041   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1042   if (aView.IsNull())
1043   {
1044     std::cerr << "Error: No opened viewer!\n";
1045     return 1;
1046   }
1047
1048   Standard_Boolean hasHlrOnArg = Standard_False;
1049   Standard_Boolean hasShowHiddenArg = Standard_False;
1050   Standard_Boolean isHLROn = Standard_False;
1051   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
1052   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
1053   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1054   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1055   {
1056     TCollection_AsciiString anArg (argv[anArgIter]);
1057     anArg.LowerCase();
1058     if (anUpdateTool.parseRedrawMode (anArg))
1059     {
1060       continue;
1061     }
1062     else if (anArg == "-showhidden"
1063           && anArgIter + 1 < argc
1064           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
1065     {
1066       ++anArgIter;
1067       hasShowHiddenArg = Standard_True;
1068       continue;
1069     }
1070     else if ((anArg == "-type"
1071            || anArg == "-algo"
1072            || anArg == "-algotype")
1073           && anArgIter + 1 < argc
1074           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1075     {
1076       ++anArgIter;
1077       continue;
1078     }
1079     else if (!hasHlrOnArg
1080           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
1081     {
1082       hasHlrOnArg = Standard_True;
1083       continue;
1084     }
1085     // old syntax
1086     else if (!hasShowHiddenArg
1087           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
1088     {
1089       hasShowHiddenArg = Standard_True;
1090       continue;
1091     }
1092     else
1093     {
1094       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
1095       return 1;
1096     }
1097   }
1098   if (!hasHlrOnArg)
1099   {
1100     di << "HLR:        " << aView->ComputedMode() << "\n";
1101     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1102     di << "HlrAlgo:    ";
1103     switch (aCtx->DefaultDrawer()->TypeOfHLR())
1104     {
1105       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
1106       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1107       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
1108     }
1109     anUpdateTool.Invalidate();
1110     return 0;
1111   }
1112
1113   Standard_Boolean toRecompute = Standard_False;
1114   if (aTypeOfHLR != Prs3d_TOH_NotSet
1115    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
1116   {
1117     toRecompute = Standard_True;
1118     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1119   }
1120   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1121   {
1122     toRecompute = Standard_True;
1123     if (toShowHidden)
1124     {
1125       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
1126     }
1127     else
1128     {
1129       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
1130     }
1131   }
1132
1133   // redisplay shapes
1134   if (aView->ComputedMode() && isHLROn && toRecompute)
1135   {
1136     AIS_ListOfInteractive aListOfShapes;
1137     aCtx->DisplayedObjects (aListOfShapes);
1138     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
1139     {
1140       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
1141       {
1142         aCtx->Redisplay (aShape, Standard_False);
1143       }
1144     }
1145   }
1146
1147   aView->SetComputedMode (isHLROn);
1148   return 0;
1149 }
1150
1151 //==============================================================================
1152 //function : VHLRType
1153 //purpose  : change type of using HLR algorithm
1154 //==============================================================================
1155
1156 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1157 {
1158   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1159   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1160   if (aView.IsNull())
1161   {
1162     std::cerr << "Error: No opened viewer!\n";
1163     return 1;
1164   }
1165
1166   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1167   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1168   AIS_ListOfInteractive aListOfShapes;
1169   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1170   {
1171     TCollection_AsciiString anArg (argv[anArgIter]);
1172     anArg.LowerCase();
1173     if (anUpdateTool.parseRedrawMode (anArg))
1174     {
1175       continue;
1176     }
1177     else if ((anArg == "-type"
1178            || anArg == "-algo"
1179            || anArg == "-algotype")
1180           && anArgIter + 1 < argc
1181           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1182     {
1183       ++anArgIter;
1184       continue;
1185     }
1186     // old syntax
1187     else if (aTypeOfHLR == Prs3d_TOH_NotSet
1188           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1189     {
1190       continue;
1191     }
1192     else
1193     {
1194       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1195       TCollection_AsciiString aName (argv[anArgIter]);
1196       if (!aMap.IsBound2 (aName))
1197       {
1198         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
1199         return 1;
1200       }
1201
1202       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1203       if (aShape.IsNull())
1204       {
1205         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
1206         return 1;
1207       }
1208       aListOfShapes.Append (aShape);
1209       continue;
1210     }
1211   }
1212   if (aTypeOfHLR == Prs3d_TOH_NotSet)
1213   {
1214     std::cout << "Syntax error: wrong number of arguments!\n";
1215     return 1;
1216   }
1217
1218   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1219   if (isGlobal)
1220   {
1221     aCtx->DisplayedObjects (aListOfShapes);
1222     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1223   }
1224
1225   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1226   {
1227     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1228     if (aShape.IsNull())
1229     {
1230       continue;
1231     }
1232
1233     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1234                             && aView->ComputedMode();
1235     if (!isGlobal
1236      || aShape->TypeOfHLR() != aTypeOfHLR)
1237     {
1238       aShape->SetTypeOfHLR (aTypeOfHLR);
1239     }
1240     if (toUpdateShape)
1241     {
1242       aCtx->Redisplay (aShape, Standard_False);
1243     }
1244   }
1245   return 0;
1246 }
1247
1248 //==============================================================================
1249 //function : FindViewIdByWindowHandle
1250 //purpose  : Find theView Id in the map of views by window handle
1251 //==============================================================================
1252 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1253 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1254 {
1255   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1256        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1257   {
1258     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1259     if (aWindowHandle == theWindowHandle)
1260       return anIter.Key1();
1261   }
1262   return TCollection_AsciiString("");
1263 }
1264 #endif
1265
1266 //==============================================================================
1267 //function : ActivateView
1268 //purpose  : Make the view active
1269 //==============================================================================
1270
1271 void ActivateView (const TCollection_AsciiString& theViewName)
1272 {
1273   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1274   if (!aView.IsNull())
1275   {
1276     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1277     if (!anAISContext.IsNull())
1278     {
1279       if (!ViewerTest::CurrentView().IsNull())
1280       {
1281         TCollection_AsciiString aTitle("3D View - ");
1282         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1283         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1284       }
1285
1286       ViewerTest::CurrentView (aView);
1287       ViewerTest::SetAISContext (anAISContext);
1288       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
1289       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1290 #if defined(_WIN32)
1291       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1292 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1293       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1294 #else
1295       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1296 #endif
1297       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1298       ViewerTest::CurrentView()->Redraw();
1299     }
1300   }
1301 }
1302
1303 //==============================================================================
1304 //function : RemoveView
1305 //purpose  :
1306 //==============================================================================
1307 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1308                              const Standard_Boolean  theToRemoveContext)
1309 {
1310   if (!ViewerTest_myViews.IsBound2 (theView))
1311   {
1312     return;
1313   }
1314
1315   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1316   RemoveView (aViewName, theToRemoveContext);
1317 }
1318
1319 //==============================================================================
1320 //function : RemoveView
1321 //purpose  : Close and remove view from display, clear maps if neccessary
1322 //==============================================================================
1323 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1324 {
1325   if (!ViewerTest_myViews.IsBound1(theViewName))
1326   {
1327     cout << "Wrong view name\n";
1328     return;
1329   }
1330
1331   // Activate another view if it's active now
1332   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1333   {
1334     if (ViewerTest_myViews.Extent() > 1)
1335     {
1336       TCollection_AsciiString aNewViewName;
1337       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1338            anIter.More(); anIter.Next())
1339       {
1340         if (anIter.Key1() != theViewName)
1341         {
1342           aNewViewName = anIter.Key1();
1343           break;
1344         }
1345       }
1346       ActivateView (aNewViewName);
1347     }
1348     else
1349     {
1350       Handle(V3d_View) anEmptyView;
1351 #if defined(_WIN32) || defined(__WIN32__)
1352       Handle(WNT_Window) anEmptyWindow;
1353 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1354       Handle(Cocoa_Window) anEmptyWindow;
1355 #else
1356       Handle(Xw_Window) anEmptyWindow;
1357 #endif
1358       VT_GetWindow() = anEmptyWindow;
1359       ViewerTest::CurrentView (anEmptyView);
1360       if (isContextRemoved)
1361       {
1362         Handle(AIS_InteractiveContext) anEmptyContext;
1363         ViewerTest::SetAISContext(anEmptyContext);
1364       }
1365     }
1366   }
1367
1368   // Delete view
1369   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1370   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1371
1372   // Remove view resources
1373   ViewerTest_myViews.UnBind1(theViewName);
1374   aView->Window()->Unmap();
1375   aView->Remove();
1376
1377 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1378   XFlush (GetDisplayConnection()->GetDisplay());
1379 #endif
1380
1381   // Keep context opened only if the closed view is last to avoid
1382   // unused empty contexts
1383   if (!aCurrentContext.IsNull())
1384   {
1385     // Check if there are more difined views in the viewer
1386     aCurrentContext->CurrentViewer()->InitDefinedViews();
1387     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1388     {
1389       // Remove driver if there is no viewers that use it
1390       Standard_Boolean isRemoveDriver = Standard_True;
1391       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1392           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1393       {
1394         if (aCurrentContext != anIter.Key2() &&
1395           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1396         {
1397           isRemoveDriver = Standard_False;
1398           break;
1399         }
1400       }
1401
1402       aCurrentContext->RemoveAll (Standard_False);
1403       if(isRemoveDriver)
1404       {
1405         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1406       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1407         #if TCL_MAJOR_VERSION  < 8
1408         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1409         #else
1410         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1411         #endif
1412       #endif
1413       }
1414
1415       ViewerTest_myContexts.UnBind2(aCurrentContext);
1416     }
1417   }
1418   cout << "3D View - " << theViewName << " was deleted.\n";
1419   if (Draw_ToExitOnCloseView)
1420   {
1421     Draw_Interprete ("exit");
1422   }
1423 }
1424
1425 //==============================================================================
1426 //function : VClose
1427 //purpose  : Remove the view defined by its name
1428 //==============================================================================
1429
1430 static int VClose (Draw_Interpretor& /*theDi*/,
1431                    Standard_Integer  theArgsNb,
1432                    const char**      theArgVec)
1433 {
1434   NCollection_List<TCollection_AsciiString> aViewList;
1435   if (theArgsNb > 1)
1436   {
1437     TCollection_AsciiString anArg (theArgVec[1]);
1438     anArg.UpperCase();
1439     if (anArg.IsEqual ("ALL")
1440      || anArg.IsEqual ("*"))
1441     {
1442       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1443            anIter.More(); anIter.Next())
1444       {
1445         aViewList.Append (anIter.Key1());
1446       }
1447       if (aViewList.IsEmpty())
1448       {
1449         std::cout << "No view to close\n";
1450         return 0;
1451       }
1452     }
1453     else
1454     {
1455       ViewerTest_Names aViewName (theArgVec[1]);
1456       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1457       {
1458         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1459         return 1;
1460       }
1461       aViewList.Append (aViewName.GetViewName());
1462     }
1463   }
1464   else
1465   {
1466     // close active view
1467     if (ViewerTest::CurrentView().IsNull())
1468     {
1469       std::cerr << "No active view!\n";
1470       return 1;
1471     }
1472     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1473   }
1474
1475   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1476   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1477        anIter.More(); anIter.Next())
1478   {
1479     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1480   }
1481
1482   return 0;
1483 }
1484
1485 //==============================================================================
1486 //function : VActivate
1487 //purpose  : Activate the view defined by its ID
1488 //==============================================================================
1489
1490 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1491 {
1492   if (theArgsNb > 2)
1493   {
1494     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1495     << "Usage: " << theArgVec[0] << " ViewID\n";
1496     return 1;
1497   }
1498   if(theArgsNb == 1)
1499   {
1500     theDi.Eval("vviewlist");
1501     return 0;
1502   }
1503
1504   TCollection_AsciiString aNameString(theArgVec[1]);
1505   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1506   {
1507     TCollection_AsciiString aTitle("3D View - ");
1508     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1509     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1510     Handle(V3d_View) anEmptyView;
1511 #if defined(_WIN32) || defined(__WIN32__)
1512     Handle(WNT_Window) anEmptyWindow;
1513 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1514     Handle(Cocoa_Window) anEmptyWindow;
1515 #else
1516     Handle(Xw_Window) anEmptyWindow;
1517 #endif
1518     VT_GetWindow() = anEmptyWindow;
1519     ViewerTest::CurrentView (anEmptyView);
1520     ViewerTest::ResetEventManager();
1521     theDi << theArgVec[0] << ": all views are inactive\n";
1522     return 0;
1523   }
1524
1525   ViewerTest_Names aViewNames(aNameString);
1526
1527   // Check if this view exists in the viewer with the driver
1528   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1529   {
1530     theDi << "Wrong view name\n";
1531     return 1;
1532   }
1533
1534   // Check if it is active already
1535   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1536   {
1537     theDi << theArgVec[0] << ": the view is active already\n";
1538     return 0;
1539   }
1540
1541   ActivateView (aViewNames.GetViewName());
1542   return 0;
1543 }
1544
1545 //==============================================================================
1546 //function : VViewList
1547 //purpose  : Print current list of views per viewer and graphic driver ID
1548 //           shared between viewers
1549 //==============================================================================
1550
1551 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1552 {
1553   if (theArgsNb > 2)
1554   {
1555     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1556           << "Usage: " << theArgVec[0] << " name";
1557     return 1;
1558   }
1559   if (ViewerTest_myContexts.Size() < 1)
1560     return 0;
1561
1562   Standard_Boolean isTreeView =
1563     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1564
1565   if (isTreeView)
1566   {
1567     theDi << theArgVec[0] <<":\n";
1568   }
1569
1570   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1571        aDriverIter.More(); aDriverIter.Next())
1572   {
1573     if (isTreeView)
1574       theDi << aDriverIter.Key1() << ":\n";
1575
1576     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1577       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1578     {
1579       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1580       {
1581         if (isTreeView)
1582         {
1583           TCollection_AsciiString aContextName(aContextIter.Key1());
1584           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1585         }
1586
1587         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1588              aViewIter.More(); aViewIter.Next())
1589         {
1590           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1591           {
1592             TCollection_AsciiString aViewName(aViewIter.Key1());
1593             if (isTreeView)
1594             {
1595               if (aViewIter.Value() == ViewerTest::CurrentView())
1596                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1597               else
1598                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1599             }
1600             else
1601             {
1602               theDi << aViewName << " ";
1603             }
1604           }
1605         }
1606       }
1607     }
1608   }
1609   return 0;
1610 }
1611
1612 //==============================================================================
1613 //function : VT_ProcessKeyPress
1614 //purpose  : Handle KeyPress event from a CString
1615 //==============================================================================
1616 void VT_ProcessKeyPress (const char* buf_ret)
1617 {
1618   //cout << "KeyPress" << endl;
1619   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1620   // Letter in alphabetic order
1621
1622   if (!strcasecmp (buf_ret, "A")
1623    && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1624   {
1625     // AXO
1626     aView->SetProj(V3d_XposYnegZpos);
1627   }
1628   else if (!strcasecmp (buf_ret, "D")
1629         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1630   {
1631     // Reset
1632     aView->Reset();
1633   }
1634   else if (!strcasecmp (buf_ret, "F"))
1635   {
1636     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1637     {
1638       ViewerTest::GetAISContext()->FitSelected (aView);
1639     }
1640     else
1641     {
1642       // FitAll
1643       aView->FitAll();
1644     }
1645   }
1646   else if (!strcasecmp (buf_ret, "H"))
1647   {
1648     // HLR
1649     std::cout << "HLR" << std::endl;
1650     aView->SetComputedMode (!aView->ComputedMode());
1651     aView->Redraw();
1652   }
1653   else if (!strcasecmp (buf_ret, "P"))
1654   {
1655     // Type of HLR
1656     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1657     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1658       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1659     else
1660       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1661     if (aContext->NbSelected()==0)
1662     {
1663       AIS_ListOfInteractive aListOfShapes;
1664       aContext->DisplayedObjects(aListOfShapes);
1665       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1666         anIter.More(); anIter.Next())
1667       {
1668         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1669         if (aShape.IsNull())
1670           continue;
1671         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1672           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1673         else
1674           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1675         aContext->Redisplay (aShape, Standard_False);
1676       }
1677     }
1678     else
1679     {
1680       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1681       {
1682         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1683         if (aShape.IsNull())
1684           continue;
1685         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1686           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1687         else
1688           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1689         aContext->Redisplay (aShape, Standard_False);
1690       }
1691     }
1692
1693     aContext->UpdateCurrentViewer();
1694
1695   }
1696   else if (!strcasecmp (buf_ret, "S"))
1697   {
1698     std::cout << "setup Shaded display mode" << std::endl;
1699
1700     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1701     if(Ctx->NbSelected()==0)
1702       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1703     else{
1704       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1705         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1706       Ctx->UpdateCurrentViewer();
1707     }
1708   }
1709   else if (!strcasecmp (buf_ret, "U"))
1710   {
1711     // Unset display mode
1712     std::cout << "reset display mode to defaults" << std::endl;
1713
1714     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1715     if(Ctx->NbSelected()==0)
1716       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1717     else{
1718       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1719         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1720       Ctx->UpdateCurrentViewer();
1721     }
1722
1723   }
1724   else if (!strcasecmp (buf_ret, "T")
1725         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1726   {
1727     // Top
1728     aView->SetProj(V3d_Zpos);
1729   }
1730   else if (!strcasecmp (buf_ret, "B")
1731         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1732   {
1733     // Bottom
1734     aView->SetProj(V3d_Zneg);
1735   }
1736   else if (!strcasecmp (buf_ret, "L")
1737         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1738   {
1739     // Left
1740     aView->SetProj(V3d_Xneg);
1741   }
1742   else if (!strcasecmp (buf_ret, "R")
1743         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1744   {
1745     // Right
1746     aView->SetProj(V3d_Xpos);
1747   }
1748   else if (!strcasecmp (buf_ret, "W"))
1749   {
1750     std::cout << "setup WireFrame display mode" << std::endl;
1751     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1752     if(Ctx->NbSelected()==0)
1753       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1754     else{
1755       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1756         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1757       Ctx->UpdateCurrentViewer();
1758     }
1759   }
1760   else if (!strcasecmp (buf_ret, ","))
1761   {
1762     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1763   }
1764   else if (!strcasecmp (buf_ret, "."))
1765   {
1766     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1767   }
1768   else if (!strcasecmp (buf_ret, "/"))
1769   {
1770     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1771     if (aCamera->IsStereo())
1772     {
1773       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1774       aView->Redraw();
1775     }
1776   }
1777   else if (!strcasecmp (buf_ret, "*"))
1778   {
1779     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1780     if (aCamera->IsStereo())
1781     {
1782       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1783       aView->Redraw();
1784     }
1785   }
1786   else if (*buf_ret == THE_KEY_DELETE)
1787   {
1788     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1789     if (!aCtx.IsNull()
1790      && aCtx->NbSelected() > 0)
1791     {
1792       Draw_Interprete ("verase");
1793     }
1794   }
1795   else if (*buf_ret == THE_KEY_ESCAPE)
1796   {
1797     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1798     if (!aCtx.IsNull()
1799      && Draw_ToCloseViewOnEsc)
1800     {
1801       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
1802     }
1803   }
1804   else
1805   {
1806     // Number
1807     const Standard_Integer aSelMode = Draw::Atoi(buf_ret);
1808     if (aSelMode >= 0 && aSelMode <= 7)
1809     {
1810       bool toEnable = true;
1811       if (const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext())
1812       {
1813         AIS_ListOfInteractive aPrsList;
1814         aCtx->DisplayedObjects (aPrsList);
1815         for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
1816         {
1817           TColStd_ListOfInteger aModes;
1818           aCtx->ActivatedModes (aPrsIter.Value(), aModes);
1819           for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
1820           {
1821             if (aModeIter.Value() == aSelMode)
1822             {
1823               toEnable = false;
1824             }
1825           }
1826         }
1827       }
1828       TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
1829       Draw_Interprete (aCmd.ToCString());
1830     }
1831   }
1832 }
1833
1834 //==============================================================================
1835 //function : VT_ProcessExpose
1836 //purpose  : Redraw the View on an Expose Event
1837 //==============================================================================
1838 void VT_ProcessExpose()
1839 {
1840   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1841   if (!aView3d.IsNull())
1842   {
1843     aView3d->Redraw();
1844   }
1845 }
1846
1847 //==============================================================================
1848 //function : VT_ProcessConfigure
1849 //purpose  : Resize the View on an Configure Event
1850 //==============================================================================
1851 void VT_ProcessConfigure()
1852 {
1853   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1854   if (aView3d.IsNull())
1855   {
1856     return;
1857   }
1858
1859   aView3d->MustBeResized();
1860   aView3d->Update();
1861   aView3d->Redraw();
1862 }
1863
1864 //==============================================================================
1865 //function : VT_ProcessButton1Press
1866 //purpose  : Picking
1867 //==============================================================================
1868 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1869                                          const char**     theArgVec,
1870                                          Standard_Boolean theToPick,
1871                                          Standard_Boolean theIsShift)
1872 {
1873   if (TheIsAnimating)
1874   {
1875     TheIsAnimating = Standard_False;
1876     return Standard_False;
1877   }
1878
1879   if (theToPick)
1880   {
1881     Standard_Real X, Y, Z;
1882     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1883
1884     Draw::Set (theArgVec[1], X);
1885     Draw::Set (theArgVec[2], Y);
1886     Draw::Set (theArgVec[3], Z);
1887   }
1888
1889   if (theIsShift)
1890   {
1891     ViewerTest::CurrentEventManager()->ShiftSelect();
1892   }
1893   else
1894   {
1895     ViewerTest::CurrentEventManager()->Select();
1896   }
1897
1898   return Standard_False;
1899 }
1900
1901 //==============================================================================
1902 //function : VT_ProcessButton1Release
1903 //purpose  : End selecting
1904 //==============================================================================
1905 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1906 {
1907   if (IsDragged)
1908   {
1909     IsDragged = Standard_False;
1910     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1911     if (theIsShift)
1912     {
1913       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1914                        X_Motion, Y_Motion);
1915     }
1916     else
1917     {
1918       EM->Select (X_ButtonPress, Y_ButtonPress,
1919                   X_Motion, Y_Motion);
1920     }
1921   }
1922 }
1923
1924 //==============================================================================
1925 //function : VT_ProcessButton3Press
1926 //purpose  : Start Rotation
1927 //==============================================================================
1928 void VT_ProcessButton3Press()
1929 {
1930   if (ViewerTest_V3dView::IsCurrentViewIn2DMode())
1931   {
1932     return;
1933   }
1934
1935   Start_Rot = 1;
1936   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
1937   if (HasHlrOnBeforeRotation)
1938   {
1939     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1940   }
1941   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1942 }
1943
1944 //==============================================================================
1945 //function : VT_ProcessButton3Release
1946 //purpose  : End rotation
1947 //==============================================================================
1948 void VT_ProcessButton3Release()
1949 {
1950   if (Start_Rot)
1951   {
1952     Start_Rot = 0;
1953     if (HasHlrOnBeforeRotation)
1954     {
1955       HasHlrOnBeforeRotation = Standard_False;
1956       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1957       ViewerTest::CurrentView()->Redraw();
1958     }
1959   }
1960 }
1961
1962 //==============================================================================
1963 //function : ProcessControlButton1Motion
1964 //purpose  : Zoom
1965 //==============================================================================
1966
1967 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1968 static void ProcessControlButton1Motion()
1969 {
1970   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1971
1972   X_ButtonPress = X_Motion;
1973   Y_ButtonPress = Y_Motion;
1974 }
1975 #endif
1976
1977 //==============================================================================
1978 //function : VT_ProcessControlButton2Motion
1979 //purpose  : Panning
1980 //==============================================================================
1981 void VT_ProcessControlButton2Motion()
1982 {
1983   Standard_Integer aDx = X_Motion - X_ButtonPress;
1984   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1985
1986   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1987
1988   ViewerTest::CurrentView()->Pan (aDx, aDy);
1989
1990   X_ButtonPress = X_Motion;
1991   Y_ButtonPress = Y_Motion;
1992 }
1993
1994 //==============================================================================
1995 //function : VT_ProcessControlButton3Motion
1996 //purpose  : Rotation
1997 //==============================================================================
1998 void VT_ProcessControlButton3Motion()
1999 {
2000   if (Start_Rot)
2001   {
2002     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
2003   }
2004 }
2005
2006 //==============================================================================
2007 //function : VT_ProcessMotion
2008 //purpose  :
2009 //==============================================================================
2010 void VT_ProcessMotion()
2011 {
2012   //pre-hilights detected objects at mouse position
2013
2014   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
2015   EM->MoveTo(X_Motion, Y_Motion);
2016 }
2017
2018
2019 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
2020 {
2021   Xpix = X_Motion;Ypix=Y_Motion;
2022 }
2023
2024 //==============================================================================
2025 //function : ViewProject: implements VAxo, VTop, VLeft, ...
2026 //purpose  : Switches to an axonometric, top, left and other views
2027 //==============================================================================
2028
2029 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
2030 {
2031   if ( ViewerTest::CurrentView().IsNull() )
2032   {
2033     di<<"Call vinit before this command, please\n";
2034     return 1;
2035   }
2036
2037   ViewerTest::CurrentView()->SetProj(ori);
2038   return 0;
2039 }
2040
2041 //==============================================================================
2042 //function : VAxo
2043 //purpose  : Switch to an Axonometric view
2044 //Draw arg : No args
2045 //==============================================================================
2046
2047 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
2048 {
2049   return ViewProject(di, V3d_XposYnegZpos);
2050 }
2051
2052 //==============================================================================
2053 //function : VTop
2054 //purpose  : Switch to a Top View
2055 //Draw arg : No args
2056 //==============================================================================
2057
2058 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
2059 {
2060   return ViewProject(di, V3d_Zpos);
2061 }
2062
2063 //==============================================================================
2064 //function : VBottom
2065 //purpose  : Switch to a Bottom View
2066 //Draw arg : No args
2067 //==============================================================================
2068
2069 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
2070 {
2071   return ViewProject(di, V3d_Zneg);
2072 }
2073
2074 //==============================================================================
2075 //function : VLeft
2076 //purpose  : Switch to a Left View
2077 //Draw arg : No args
2078 //==============================================================================
2079
2080 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
2081 {
2082   return ViewProject(di, V3d_Xneg);
2083 }
2084
2085 //==============================================================================
2086 //function : VRight
2087 //purpose  : Switch to a Right View
2088 //Draw arg : No args
2089 //==============================================================================
2090
2091 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
2092 {
2093   return ViewProject(di, V3d_Xpos);
2094 }
2095
2096 //==============================================================================
2097 //function : VFront
2098 //purpose  : Switch to a Front View
2099 //Draw arg : No args
2100 //==============================================================================
2101
2102 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
2103 {
2104   return ViewProject(di, V3d_Yneg);
2105 }
2106
2107 //==============================================================================
2108 //function : VBack
2109 //purpose  : Switch to a Back View
2110 //Draw arg : No args
2111 //==============================================================================
2112
2113 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
2114 {
2115   return ViewProject(di, V3d_Ypos);
2116 }
2117
2118 //==============================================================================
2119 //function : VHelp
2120 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
2121 //Draw arg : No args
2122 //==============================================================================
2123
2124 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
2125 {
2126
2127   di << "Q : Quit the application\n";
2128
2129   di << "=========================\n";
2130   di << "F : FitAll\n";
2131   di << "T : TopView\n";
2132   di << "B : BottomView\n";
2133   di << "R : RightView\n";
2134   di << "L : LeftView\n";
2135   di << "A : AxonometricView\n";
2136   di << "D : ResetView\n";
2137
2138   di << "=========================\n";
2139   di << "S : Shading\n";
2140   di << "W : Wireframe\n";
2141   di << "H : HidelLineRemoval\n";
2142   di << "U : Unset display mode\n";
2143   di << "Delete : Remove selection from viewer\n";
2144
2145   di << "=========================\n";
2146   di << "Selection mode \n";
2147   di << "0 : Shape\n";
2148   di << "1 : Vertex\n";
2149   di << "2 : Edge\n";
2150   di << "3 : Wire\n";
2151   di << "4 : Face\n";
2152   di << "5 : Shell\n";
2153   di << "6 : Solid\n";
2154   di << "7 : Compound\n";
2155
2156   di << "=========================\n";
2157   di << "Z : Switch Z clipping On/Off\n";
2158   di << ", : Hilight next detected\n";
2159   di << ". : Hilight previous detected\n";
2160
2161   return 0;
2162 }
2163
2164 #ifdef _WIN32
2165
2166 static Standard_Boolean Ppick = 0;
2167 static Standard_Integer Pargc = 0;
2168 static const char**           Pargv = NULL;
2169
2170
2171 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
2172                                           UINT Msg,
2173                                           WPARAM wParam,
2174                                           LPARAM lParam )
2175 {
2176   if (!ViewerTest_myViews.IsEmpty()) {
2177
2178     WPARAM fwKeys = wParam;
2179
2180     switch( Msg ) {
2181     case WM_CLOSE:
2182        {
2183          // Delete view from map of views
2184          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
2185          return 0;
2186        }
2187        break;
2188     case WM_ACTIVATE:
2189       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
2190         || ViewerTest::CurrentView().IsNull())
2191       {
2192         // Activate inactive window
2193         if(GetWindowHandle(VT_GetWindow()) != hwnd)
2194         {
2195           ActivateView (FindViewIdByWindowHandle(hwnd));
2196         }
2197       }
2198       break;
2199
2200     case WM_LBUTTONUP:
2201       if (IsDragged && !DragFirst)
2202       {
2203         if (!GetActiveAISManipulator().IsNull())
2204         {
2205           GetActiveAISManipulator()->StopTransform();
2206           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2207         }
2208
2209         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2210         {
2211           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2212           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2213         }
2214
2215         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
2216       }
2217       IsDragged = Standard_False;
2218       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2219
2220     case WM_RBUTTONUP:
2221       if (IsDragged && !DragFirst)
2222       {
2223         if (!GetActiveAISManipulator().IsNull())
2224         {
2225           GetActiveAISManipulator()->StopTransform (Standard_False);
2226           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2227         }
2228         IsDragged = Standard_False;
2229       }
2230       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
2231
2232     case WM_LBUTTONDOWN:
2233       if (!GetActiveAISManipulator().IsNull())
2234       {
2235         IsDragged = ( fwKeys == MK_LBUTTON );
2236       }
2237       else
2238       {
2239         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
2240       }
2241
2242       if (IsDragged)
2243       {
2244         DragFirst = Standard_True;
2245         X_ButtonPress = LOWORD(lParam);
2246         Y_ButtonPress = HIWORD(lParam);
2247       }
2248       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2249
2250     case WM_MOUSEMOVE:
2251       if (IsDragged)
2252       {
2253         X_Motion = LOWORD (lParam);
2254         Y_Motion = HIWORD (lParam);
2255         if (!GetActiveAISManipulator().IsNull())
2256         {
2257           if (DragFirst)
2258           {
2259             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
2260           }
2261           else
2262           {
2263             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
2264             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
2265           }
2266         }
2267         else
2268         {
2269           bool toRedraw = false;
2270           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2271           {
2272             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2273             toRedraw = true;
2274           }
2275
2276           RECT aRect;
2277           if (GetClientRect (hwnd, &aRect))
2278           {
2279             int aHeight = aRect.bottom - aRect.top;
2280             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2281             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2282             toRedraw = true;
2283           }
2284           if (toRedraw)
2285           {
2286             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2287           }
2288         }
2289
2290         DragFirst = Standard_False;
2291       }
2292       else
2293         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2294       break;
2295
2296     default:
2297       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2298     }
2299     return 0;
2300   }
2301   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2302 }
2303
2304
2305 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2306                                        UINT Msg,
2307                                        WPARAM wParam,
2308                                        LPARAM lParam )
2309 {
2310   static int Up = 1;
2311   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2312   if (aView.IsNull())
2313   {
2314     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2315   }
2316
2317     PAINTSTRUCT    ps;
2318
2319     switch( Msg ) {
2320     case WM_PAINT:
2321       BeginPaint(hwnd, &ps);
2322       EndPaint(hwnd, &ps);
2323       VT_ProcessExpose();
2324       break;
2325
2326     case WM_SIZE:
2327       VT_ProcessConfigure();
2328       break;
2329     case WM_MOVE:
2330     case WM_MOVING:
2331     case WM_SIZING:
2332       switch (aView->RenderingParams().StereoMode)
2333       {
2334         case Graphic3d_StereoMode_RowInterlaced:
2335         case Graphic3d_StereoMode_ColumnInterlaced:
2336         case Graphic3d_StereoMode_ChessBoard:
2337           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2338           break;
2339         default:
2340           break;
2341       }
2342       break;
2343
2344     case WM_KEYDOWN:
2345       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2346       {
2347         char c[2];
2348         c[0] = (char) wParam;
2349         c[1] = '\0';
2350         if (wParam == VK_DELETE)
2351         {
2352           c[0] = THE_KEY_DELETE;
2353         }
2354         else if (wParam == VK_ESCAPE)
2355         {
2356           c[0] = THE_KEY_ESCAPE;
2357         }
2358         // comma
2359         else if (wParam == VK_OEM_COMMA)
2360         {
2361           c[0] = ',';
2362         }
2363         // dot
2364         else if (wParam == VK_OEM_PERIOD)
2365         {
2366           c[0] = '.';
2367         }
2368         else if (wParam == VK_DIVIDE)
2369         {
2370           c[0] = '/';
2371         }
2372         // dot
2373         else if (wParam == VK_MULTIPLY)
2374         {
2375           c[0] = '*';
2376         }
2377         VT_ProcessKeyPress (c);
2378       }
2379       break;
2380
2381     case WM_LBUTTONUP:
2382     case WM_MBUTTONUP:
2383     case WM_RBUTTONUP:
2384       Up = 1;
2385       VT_ProcessButton3Release();
2386       break;
2387
2388     case WM_LBUTTONDOWN:
2389     case WM_MBUTTONDOWN:
2390     case WM_RBUTTONDOWN:
2391       {
2392         WPARAM fwKeys = wParam;
2393
2394         Up = 0;
2395
2396         X_ButtonPress = LOWORD(lParam);
2397         Y_ButtonPress = HIWORD(lParam);
2398
2399         if (Msg == WM_LBUTTONDOWN)
2400         {
2401           if ((fwKeys & MK_CONTROL) != 0)
2402           {
2403             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2404           }
2405           else
2406           {
2407             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2408           }
2409         }
2410         else if (Msg == WM_RBUTTONDOWN)
2411         {
2412           // Start rotation
2413           VT_ProcessButton3Press();
2414         }
2415       }
2416       break;
2417
2418     case WM_MOUSEWHEEL:
2419     {
2420       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2421       if (wParam & MK_CONTROL)
2422       {
2423         if (aView->Camera()->IsStereo())
2424         {
2425           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2426           if (aFocus > 0.2
2427            && aFocus < 2.0)
2428           {
2429             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2430             aView->Redraw();
2431           }
2432         }
2433       }
2434       else
2435       {
2436         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2437       }
2438       break;
2439     }
2440
2441     case WM_MOUSEMOVE:
2442       {
2443         //cout << "\t WM_MOUSEMOVE" << endl;
2444         WPARAM fwKeys = wParam;
2445         X_Motion = LOWORD(lParam);
2446         Y_Motion = HIWORD(lParam);
2447
2448         if ( Up &&
2449           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2450           {
2451             Up = 0;
2452             X_ButtonPress = LOWORD(lParam);
2453             Y_ButtonPress = HIWORD(lParam);
2454
2455             if ((fwKeys & MK_RBUTTON) != 0) {
2456               // Start rotation
2457               VT_ProcessButton3Press();
2458             }
2459           }
2460
2461           if ((fwKeys & MK_CONTROL) != 0)
2462           {
2463             if ((fwKeys & MK_LBUTTON) != 0)
2464             {
2465               ProcessControlButton1Motion();
2466             }
2467             else if ((fwKeys & MK_MBUTTON) != 0
2468                  || ((fwKeys & MK_LBUTTON) != 0
2469                   && (fwKeys & MK_RBUTTON) != 0))
2470             {
2471               VT_ProcessControlButton2Motion();
2472             }
2473             else if ((fwKeys & MK_RBUTTON) != 0)
2474             {
2475               VT_ProcessControlButton3Motion();
2476             }
2477           }
2478           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2479           {
2480             VT_ProcessMotion();
2481           }
2482       }
2483       break;
2484
2485     default:
2486       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2487     }
2488     return 0L;
2489 }
2490
2491 //==============================================================================
2492 //function : ViewerMainLoop
2493 //purpose  : Get a Event on the view and dispatch it
2494 //==============================================================================
2495
2496
2497 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2498 {
2499   Ppick = (argc > 0)? 1 : 0;
2500   Pargc = argc;
2501   Pargv = argv;
2502
2503   if ( Ppick ) {
2504     MSG msg;
2505     msg.wParam = 1;
2506
2507     cout << "Start picking" << endl;
2508
2509     while ( Ppick == 1 ) {
2510       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2511       if (GetMessageW (&msg, NULL, 0, 0))
2512       {
2513         TranslateMessage (&msg);
2514         DispatchMessageW (&msg);
2515       }
2516     }
2517
2518     cout << "Picking done" << endl;
2519   }
2520
2521   return Ppick;
2522 }
2523
2524 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2525
2526 int min( int a, int b )
2527 {
2528   if( a<b )
2529     return a;
2530   else
2531     return b;
2532 }
2533
2534 int max( int a, int b )
2535 {
2536   if( a>b )
2537     return a;
2538   else
2539     return b;
2540 }
2541
2542 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2543
2544 {
2545   static XEvent aReport;
2546   Standard_Boolean pick = argc > 0;
2547   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2548   XNextEvent (aDisplay, &aReport);
2549
2550   // Handle event for the chosen display connection
2551   switch (aReport.type) {
2552       case ClientMessage:
2553         {
2554           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2555           {
2556             // Close the window
2557             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2558           }
2559         }
2560         return 0;
2561      case FocusIn:
2562       {
2563          // Activate inactive view
2564          Window aWindow = GetWindowHandle(VT_GetWindow());
2565          if(aWindow != aReport.xfocus.window)
2566          {
2567            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2568          }
2569       }
2570       break;
2571       case Expose:
2572         {
2573           VT_ProcessExpose();
2574         }
2575         break;
2576       case ConfigureNotify:
2577         {
2578           VT_ProcessConfigure();
2579         }
2580         break;
2581       case KeyPress:
2582         {
2583
2584           KeySym ks_ret ;
2585           char buf_ret[11] ;
2586           int ret_len ;
2587           XComposeStatus status_in_out;
2588
2589           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2590             (char *) buf_ret , 10 ,
2591             &ks_ret , &status_in_out ) ;
2592
2593
2594           buf_ret[ret_len] = '\0' ;
2595
2596           if (ret_len)
2597           {
2598             VT_ProcessKeyPress (buf_ret);
2599           }
2600         }
2601         break;
2602       case ButtonPress:
2603         {
2604           X_ButtonPress = aReport.xbutton.x;
2605           Y_ButtonPress = aReport.xbutton.y;
2606
2607           if (aReport.xbutton.button == Button1)
2608           {
2609             if (aReport.xbutton.state & ControlMask)
2610             {
2611               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2612             }
2613             else
2614             {
2615               IsDragged = Standard_True;
2616               DragFirst = Standard_True;
2617             }
2618           }
2619           else if (aReport.xbutton.button == Button3)
2620           {
2621             // Start rotation
2622             VT_ProcessButton3Press();
2623           }
2624         }
2625         break;
2626       case ButtonRelease:
2627         {
2628           if( IsDragged )
2629           {
2630             if( !DragFirst )
2631             {
2632               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2633               {
2634                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2635                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2636               }
2637             }
2638
2639             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2640             if( aContext.IsNull() )
2641             {
2642               cout << "The context is null. Please use vinit before createmesh" << endl;
2643               return 0;
2644             }
2645
2646             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2647             if( aReport.xbutton.button==1 )
2648               if( DragFirst )
2649                 if( ShiftPressed )
2650                 {
2651                   aContext->ShiftSelect (Standard_True);
2652                 }
2653                 else
2654                 {
2655                   aContext->Select (Standard_True);
2656                 }
2657               else
2658                 if( ShiftPressed )
2659                 {
2660                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2661                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2662                                         ViewerTest::CurrentView(), Standard_True);
2663                 }
2664                 else
2665                 {
2666                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2667                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2668                                    ViewerTest::CurrentView(), Standard_True);
2669                 }
2670             else
2671               VT_ProcessButton3Release();
2672
2673             IsDragged = Standard_False;
2674           }
2675           else
2676             VT_ProcessButton3Release();
2677         }
2678         break;
2679       case MotionNotify:
2680         {
2681           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2682           {
2683             break;
2684           }
2685           if( IsDragged )
2686           {
2687             if( !DragFirst )
2688             {
2689               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2690               {
2691                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2692               }
2693             }
2694
2695             X_Motion = aReport.xmotion.x;
2696             Y_Motion = aReport.xmotion.y;
2697             DragFirst = Standard_False;
2698
2699             Window aWindow = GetWindowHandle(VT_GetWindow());
2700             Window aRoot;
2701             int anX, anY;
2702             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2703             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2704             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2705             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2706             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2707           }
2708           else
2709           {
2710             X_Motion = aReport.xmotion.x;
2711             Y_Motion = aReport.xmotion.y;
2712
2713             // remove all the ButtonMotionMaskr
2714             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2715
2716             if ( aReport.xmotion.state & ControlMask ) {
2717               if ( aReport.xmotion.state & Button1Mask ) {
2718                 ProcessControlButton1Motion();
2719               }
2720               else if ( aReport.xmotion.state & Button2Mask ) {
2721                 VT_ProcessControlButton2Motion();
2722               }
2723               else if ( aReport.xmotion.state & Button3Mask ) {
2724                 VT_ProcessControlButton3Motion();
2725               }
2726             }
2727             else
2728             {
2729               VT_ProcessMotion();
2730             }
2731           }
2732         }
2733         break;
2734 }
2735 return pick;
2736 }
2737
2738 //==============================================================================
2739 //function : VProcessEvents
2740 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2741 //       event in the Viewer window
2742 //==============================================================================
2743
2744 static void VProcessEvents(ClientData,int)
2745 {
2746   NCollection_Vector<int> anEventNumbers;
2747   // Get number of messages from every display
2748   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2749        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2750   {
2751     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2752   }
2753     // Handle events for every display
2754   int anEventIter = 0;
2755   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2756        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2757   {
2758     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2759          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2760     {
2761       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2762       int anEventResult = ViewerMainLoop( 0, NULL);
2763       // If window is closed or context was not found finish current event processing loop
2764       if (!anEventResult)
2765         return;
2766     }
2767   }
2768
2769   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2770
2771 }
2772 #endif
2773
2774 //==============================================================================
2775 //function : OSWindowSetup
2776 //purpose  : Setup for the X11 window to be able to cath the event
2777 //==============================================================================
2778
2779
2780 static void OSWindowSetup()
2781 {
2782 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2783   // X11
2784
2785   Window  window   = VT_GetWindow()->XWindow();
2786   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2787   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2788   XSynchronize(aDisplay, 1);
2789
2790   // X11 : For keyboard on SUN
2791   XWMHints wmhints;
2792   wmhints.flags = InputHint;
2793   wmhints.input = 1;
2794
2795   XSetWMHints( aDisplay, window, &wmhints);
2796
2797   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2798     ButtonPressMask | ButtonReleaseMask |
2799     StructureNotifyMask |
2800     PointerMotionMask |
2801     Button1MotionMask | Button2MotionMask |
2802     Button3MotionMask | FocusChangeMask
2803     );
2804   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2805   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2806
2807   XSynchronize(aDisplay, 0);
2808
2809 #else
2810   // _WIN32
2811 #endif
2812
2813 }
2814
2815 //==============================================================================
2816 //function : VFit
2817 //purpose  :
2818 //==============================================================================
2819
2820 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2821 {
2822   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2823   if (aView.IsNull())
2824   {
2825     std::cout << "Error: no active viewer!\n";
2826     return 1;
2827   }
2828
2829   Standard_Boolean toFit = Standard_True;
2830   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2831   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2832   {
2833     TCollection_AsciiString anArg (theArgv[anArgIter]);
2834     anArg.LowerCase();
2835     if (anUpdateTool.parseRedrawMode (anArg))
2836     {
2837       continue;
2838     }
2839     else if (anArg == "-selected")
2840     {
2841       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2842       toFit = Standard_False;
2843     }
2844     else
2845     {
2846       std::cout << "Syntax error at '" << anArg << "'\n";
2847     }
2848   }
2849
2850   if (toFit)
2851   {
2852     aView->FitAll (0.01, Standard_False);
2853   }
2854   return 0;
2855 }
2856
2857 //=======================================================================
2858 //function : VFitArea
2859 //purpose  : Fit view to show area located between two points
2860 //         : given in world 2D or 3D coordinates.
2861 //=======================================================================
2862 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2863 {
2864   Handle(V3d_View) aView = ViewerTest::CurrentView();
2865   if (aView.IsNull())
2866   {
2867     std::cerr << theArgVec[0] << "Error: No active view.\n";
2868     return 1;
2869   }
2870
2871   // Parse arguments.
2872   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2873   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2874
2875   if (theArgNb == 5)
2876   {
2877     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2878     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2879     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2880     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2881   }
2882   else if (theArgNb == 7)
2883   {
2884     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2885     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2886     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2887     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2888     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2889     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2890   }
2891   else
2892   {
2893     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2894     theDI.PrintHelp(theArgVec[0]);
2895     return 1;
2896   }
2897
2898   // Convert model coordinates to view space
2899   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2900   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2901   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2902
2903   // Determine fit area
2904   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2905   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2906
2907   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2908
2909   if (aDiagonal < Precision::Confusion())
2910   {
2911     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2912     return 1;
2913   }
2914
2915   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2916   return 0;
2917 }
2918
2919 //==============================================================================
2920 //function : VZFit
2921 //purpose  : ZFitall, no DRAW arguments
2922 //Draw arg : No args
2923 //==============================================================================
2924 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2925 {
2926   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2927
2928   if (aCurrentView.IsNull())
2929   {
2930     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2931     return 1;
2932   }
2933
2934   if (theArgsNb == 1)
2935   {
2936     aCurrentView->ZFitAll();
2937     aCurrentView->Redraw();
2938     return 0;
2939   }
2940
2941   Standard_Real aScale = 1.0;
2942
2943   if (theArgsNb >= 2)
2944   {
2945     aScale = Draw::Atoi (theArgVec[1]);
2946   }
2947
2948   aCurrentView->ZFitAll (aScale);
2949   aCurrentView->Redraw();
2950
2951   return 0;
2952 }
2953
2954 //==============================================================================
2955 //function : VRepaint
2956 //purpose  :
2957 //==============================================================================
2958 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2959 {
2960   Handle(V3d_View) aView = ViewerTest::CurrentView();
2961   if (aView.IsNull())
2962   {
2963     std::cout << "Error: no active viewer!\n";
2964     return 1;
2965   }
2966
2967   Standard_Boolean isImmediateUpdate = Standard_False;
2968   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2969   {
2970     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2971     anArg.LowerCase();
2972     if (anArg == "-immediate")
2973     {
2974       isImmediateUpdate = Standard_True;
2975       if (anArgIter + 1 < theArgNb
2976        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2977       {
2978         ++anArgIter;
2979       }
2980     }
2981     else
2982     {
2983       std::cout << "Syntax error at '" << anArg << "'\n";
2984     }
2985   }
2986
2987   if (isImmediateUpdate)
2988   {
2989     aView->RedrawImmediate();
2990   }
2991   else
2992   {
2993     aView->Redraw();
2994   }
2995   return 0;
2996 }
2997
2998 //==============================================================================
2999 //function : VClear
3000 //purpose  : Remove all the object from the viewer
3001 //Draw arg : No args
3002 //==============================================================================
3003
3004 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3005 {
3006   Handle(V3d_View) V = ViewerTest::CurrentView();
3007   if(!V.IsNull())
3008     ViewerTest::Clear();
3009   return 0;
3010 }
3011
3012 //==============================================================================
3013 //function : VPick
3014 //purpose  :
3015 //==============================================================================
3016
3017 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3018 { if (ViewerTest::CurrentView().IsNull() ) return 1;
3019
3020 if ( argc < 4 ) {
3021   di << argv[0] << "Invalid number of arguments\n";
3022   return 1;
3023 }
3024
3025 while (ViewerMainLoop( argc, argv)) {
3026 }
3027
3028 return 0;
3029 }
3030
3031 //==============================================================================
3032 //function : VSetBg
3033 //purpose  : Load image as background
3034 //==============================================================================
3035
3036 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3037 {
3038   if (argc < 2 || argc > 3)
3039   {
3040     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
3041     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
3042     return 1;
3043   }
3044
3045   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3046   if(AISContext.IsNull())
3047   {
3048     di << "use 'vinit' command before " << argv[0] << "\n";
3049     return 1;
3050   }
3051
3052   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
3053   if (argc == 3)
3054   {
3055     const char* szType = argv[2];
3056     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3057     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3058     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3059     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3060     else
3061     {
3062       di << "Wrong fill type : " << szType << "\n";
3063       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3064       return 1;
3065     }
3066   }
3067
3068   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3069   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
3070
3071   return 0;
3072 }
3073
3074 //==============================================================================
3075 //function : VSetBgMode
3076 //purpose  : Change background image fill type
3077 //==============================================================================
3078
3079 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3080 {
3081   if (argc != 2)
3082   {
3083     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
3084     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
3085     return 1;
3086   }
3087
3088   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3089   if(AISContext.IsNull())
3090   {
3091     di << "use 'vinit' command before " << argv[0] << "\n";
3092     return 1;
3093   }
3094   Aspect_FillMethod aFillType = Aspect_FM_NONE;
3095   const char* szType = argv[1];
3096   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3097   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3098   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3099   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3100   else
3101   {
3102     di << "Wrong fill type : " << szType << "\n";
3103     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3104     return 1;
3105   }
3106   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3107   V3dView->SetBgImageStyle(aFillType, Standard_True);
3108   return 0;
3109 }
3110
3111 //==============================================================================
3112 //function : VSetGradientBg
3113 //purpose  : Mount gradient background
3114 //==============================================================================
3115 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3116 {
3117   if (argc != 8 )
3118   {
3119     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
3120     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
3121     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3122     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3123     return 1;
3124   }
3125
3126   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3127   if(AISContext.IsNull())
3128   {
3129     di << "use 'vinit' command before " << argv[0] << "\n";
3130     return 1;
3131   }
3132   if (argc == 8)
3133   {
3134
3135     Standard_Real R1 = Draw::Atof(argv[1])/255.;
3136     Standard_Real G1 = Draw::Atof(argv[2])/255.;
3137     Standard_Real B1 = Draw::Atof(argv[3])/255.;
3138     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
3139
3140     Standard_Real R2 = Draw::Atof(argv[4])/255.;
3141     Standard_Real G2 = Draw::Atof(argv[5])/255.;
3142     Standard_Real B2 = Draw::Atof(argv[6])/255.;
3143
3144     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
3145     int aType = Draw::Atoi(argv[7]);
3146     if( aType < 0 || aType > 8 )
3147     {
3148       di << "Wrong fill type \n";
3149       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3150       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3151       return 1;
3152     }
3153
3154     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3155
3156     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3157     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
3158   }
3159
3160   return 0;
3161 }
3162
3163 //==============================================================================
3164 //function : VSetGradientBgMode
3165 //purpose  : Change gradient background fill style
3166 //==============================================================================
3167 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3168 {
3169   if (argc != 2 )
3170   {
3171     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
3172     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3173     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3174     return 1;
3175   }
3176
3177   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3178   if(AISContext.IsNull())
3179   {
3180     di << "use 'vinit' command before " << argv[0] << "\n";
3181     return 1;
3182   }
3183   if (argc == 2)
3184   {
3185     int aType = Draw::Atoi(argv[1]);
3186     if( aType < 0 || aType > 8 )
3187     {
3188       di << "Wrong fill type \n";
3189       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3190       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3191       return 1;
3192     }
3193
3194     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3195
3196     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3197     V3dView->SetBgGradientStyle( aMethod, 1 );
3198   }
3199
3200   return 0;
3201 }
3202
3203 //==============================================================================
3204 //function : VSetColorBg
3205 //purpose  : Set color background
3206 //==============================================================================
3207 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3208 {
3209   if (argc != 4 )
3210   {
3211     di << "Usage : " << argv[0] << " R G B : Set color background\n";
3212     di << "R,G,B = [0..255]\n";
3213     return 1;
3214   }
3215
3216   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3217   if(AISContext.IsNull())
3218   {
3219     di << "use 'vinit' command before " << argv[0] << "\n";
3220     return 1;
3221   }
3222   if (argc == 4)
3223   {
3224
3225     Standard_Real R = Draw::Atof(argv[1])/255.;
3226     Standard_Real G = Draw::Atof(argv[2])/255.;
3227     Standard_Real B = Draw::Atof(argv[3])/255.;
3228     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
3229
3230     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3231     V3dView->SetBackgroundColor( aColor );
3232     V3dView->Update();
3233   }
3234
3235   return 0;
3236 }
3237
3238 //==============================================================================
3239 //function : VSetDefaultBg
3240 //purpose  : Set default viewer background fill color
3241 //==============================================================================
3242 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3243 {
3244   if (theArgNb != 4
3245    && theArgNb != 8)
3246   {
3247     std::cout << "Error: wrong syntax! See usage:\n";
3248     theDI.PrintHelp (theArgVec[0]);
3249     return 1;
3250   }
3251
3252   ViewerTest_DefaultBackground.FillMethod =
3253     theArgNb == 4 ? Aspect_GFM_NONE
3254                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
3255
3256   if (theArgNb == 4)
3257   {
3258     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
3259     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
3260     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
3261     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
3262   }
3263   else
3264   {
3265     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
3266     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
3267     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
3268     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
3269
3270     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
3271     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
3272     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
3273     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
3274   }
3275
3276   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
3277        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
3278   {
3279     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
3280     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
3281     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
3282                                          ViewerTest_DefaultBackground.GradientColor2,
3283                                          ViewerTest_DefaultBackground.FillMethod);
3284   }
3285
3286   return 0;
3287 }
3288
3289 //==============================================================================
3290 //function : VScale
3291 //purpose  : View Scaling
3292 //==============================================================================
3293
3294 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3295 {
3296   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3297   if ( V3dView.IsNull() ) return 1;
3298
3299   if ( argc != 4 ) {
3300     di << argv[0] << "Invalid number of arguments\n";
3301     return 1;
3302   }
3303   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3304   return 0;
3305 }
3306 //==============================================================================
3307 //function : VZBuffTrihedron
3308 //purpose  :
3309 //==============================================================================
3310
3311 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3312                             Standard_Integer  theArgNb,
3313                             const char**      theArgVec)
3314 {
3315   Handle(V3d_View) aView = ViewerTest::CurrentView();
3316   if (aView.IsNull())
3317   {
3318     std::cout << "Error: no active viewer!\n";
3319     return 1;
3320   }
3321
3322   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3323
3324   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3325   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3326   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3327   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3328   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3329   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3330   Standard_Real                 aScale        = 0.1;
3331   Standard_Real                 aSizeRatio    = 0.8;
3332   Standard_Real                 anArrowDiam   = 0.05;
3333   Standard_Integer              aNbFacets     = 12;
3334   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3335   {
3336     Standard_CString        anArg = theArgVec[anArgIter];
3337     TCollection_AsciiString aFlag (anArg);
3338     aFlag.LowerCase();
3339     if (anUpdateTool.parseRedrawMode (aFlag))
3340     {
3341       continue;
3342     }
3343     else if (aFlag == "-on")
3344     {
3345       continue;
3346     }
3347     else if (aFlag == "-off")
3348     {
3349       aView->TriedronErase();
3350       return 0;
3351     }
3352     else if (aFlag == "-pos"
3353           || aFlag == "-position"
3354           || aFlag == "-corner")
3355     {
3356       if (++anArgIter >= theArgNb)
3357       {
3358         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3359         return 1;
3360       }
3361
3362       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3363       aPosName.LowerCase();
3364       if (aPosName == "center")
3365       {
3366         aPosition = Aspect_TOTP_CENTER;
3367       }
3368       else if (aPosName == "left_lower"
3369             || aPosName == "lower_left"
3370             || aPosName == "leftlower"
3371             || aPosName == "lowerleft")
3372       {
3373         aPosition = Aspect_TOTP_LEFT_LOWER;
3374       }
3375       else if (aPosName == "left_upper"
3376             || aPosName == "upper_left"
3377             || aPosName == "leftupper"
3378             || aPosName == "upperleft")
3379       {
3380         aPosition = Aspect_TOTP_LEFT_UPPER;
3381       }
3382       else if (aPosName == "right_lower"
3383             || aPosName == "lower_right"
3384             || aPosName == "rightlower"
3385             || aPosName == "lowerright")
3386       {
3387         aPosition = Aspect_TOTP_RIGHT_LOWER;
3388       }
3389       else if (aPosName == "right_upper"
3390             || aPosName == "upper_right"
3391             || aPosName == "rightupper"
3392             || aPosName == "upperright")
3393       {
3394         aPosition = Aspect_TOTP_RIGHT_UPPER;
3395       }
3396       else
3397       {
3398         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3399         return 1;
3400       }
3401     }
3402     else if (aFlag == "-type")
3403     {
3404       if (++anArgIter >= theArgNb)
3405       {
3406         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3407         return 1;
3408       }
3409
3410       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3411       aTypeName.LowerCase();
3412       if (aTypeName == "wireframe"
3413        || aTypeName == "wire")
3414       {
3415         aVisType = V3d_WIREFRAME;
3416       }
3417       else if (aTypeName == "zbuffer"
3418             || aTypeName == "shaded")
3419       {
3420         aVisType = V3d_ZBUFFER;
3421       }
3422       else
3423       {
3424         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3425       }
3426     }
3427     else if (aFlag == "-scale")
3428     {
3429       if (++anArgIter >= theArgNb)
3430       {
3431         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3432         return 1;
3433       }
3434
3435       aScale = Draw::Atof (theArgVec[anArgIter]);
3436     }
3437     else if (aFlag == "-size"
3438           || aFlag == "-sizeratio")
3439     {
3440       if (++anArgIter >= theArgNb)
3441       {
3442         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3443         return 1;
3444       }
3445
3446       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3447     }
3448     else if (aFlag == "-arrowdiam"
3449           || aFlag == "-arrowdiameter")
3450     {
3451       if (++anArgIter >= theArgNb)
3452       {
3453         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3454         return 1;
3455       }
3456
3457       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3458     }
3459     else if (aFlag == "-nbfacets")
3460     {
3461       if (++anArgIter >= theArgNb)
3462       {
3463         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3464         return 1;
3465       }
3466
3467       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3468     }
3469     else if (aFlag == "-colorlabel"
3470           || aFlag == "-colorlabels")
3471     {
3472       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3473                                                            theArgVec + anArgIter + 1,
3474                                                            aLabelsColor);
3475       if (aNbParsed == 0)
3476       {
3477         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3478         return 1;
3479       }
3480       anArgIter += aNbParsed;
3481     }
3482     else if (aFlag == "-colorarrowx")
3483     {
3484       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3485                                                            theArgVec + anArgIter + 1,
3486                                                            anArrowColorX);
3487       if (aNbParsed == 0)
3488       {
3489         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3490         return 1;
3491       }
3492       anArgIter += aNbParsed;
3493     }
3494     else if (aFlag == "-colorarrowy")
3495     {
3496       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3497                                                            theArgVec + anArgIter + 1,
3498                                                            anArrowColorY);
3499       if (aNbParsed == 0)
3500       {
3501         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3502         return 1;
3503       }
3504       anArgIter += aNbParsed;
3505     }
3506     else if (aFlag == "-colorarrowz")
3507     {
3508       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3509                                                            theArgVec + anArgIter + 1,
3510                                                            anArrowColorZ);
3511       if (aNbParsed == 0)
3512       {
3513         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3514         return 1;
3515       }
3516       anArgIter += aNbParsed;
3517     }
3518     else
3519     {
3520       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3521       return 1;
3522     }
3523   }
3524
3525   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3526                                aSizeRatio, anArrowDiam, aNbFacets);
3527   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3528   aView->ZFitAll();
3529   return 0;
3530 }
3531
3532 //==============================================================================
3533 //function : VRotate
3534 //purpose  : Camera Rotating
3535 //==============================================================================
3536
3537 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3538 {
3539   Handle(V3d_View) aView = ViewerTest::CurrentView();
3540   if (aView.IsNull())
3541   {
3542     std::cout << "No active view!\n";
3543     return 1;
3544   }
3545
3546   Standard_Boolean hasFlags = Standard_False;
3547   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3548   {
3549     Standard_CString        anArg (theArgVec[anArgIter]);
3550     TCollection_AsciiString aFlag (anArg);
3551     aFlag.LowerCase();
3552     if (aFlag == "-mousestart"
3553      || aFlag == "-mousefrom")
3554     {
3555       hasFlags = Standard_True;
3556       if (anArgIter + 2 >= theArgNb)
3557       {
3558         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3559         return 1;
3560       }
3561
3562       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3563       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3564       aView->StartRotation (anX, anY);
3565     }
3566     else if (aFlag == "-mousemove")
3567     {
3568       hasFlags = Standard_True;
3569       if (anArgIter + 2 >= theArgNb)
3570       {
3571         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3572         return 1;
3573       }
3574
3575       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3576       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3577       aView->Rotation (anX, anY);
3578     }
3579     else if (theArgNb != 4
3580           && theArgNb != 7)
3581     {
3582       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3583       return 1;
3584     }
3585   }
3586
3587   if (hasFlags)
3588   {
3589     return 0;
3590   }
3591   else if (theArgNb == 4)
3592   {
3593     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3594     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3595     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3596     aView->Rotate (anAX, anAY, anAZ);
3597     return 0;
3598   }
3599   else if (theArgNb == 7)
3600   {
3601     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3602     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3603     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3604
3605     Standard_Real anX = Draw::Atof (theArgVec[4]);
3606     Standard_Real anY = Draw::Atof (theArgVec[5]);
3607     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3608
3609     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3610     return 0;
3611   }
3612
3613   std::cout << "Error: Invalid number of arguments\n";
3614   return 1;
3615 }
3616
3617 //==============================================================================
3618 //function : VZoom
3619 //purpose  : View zoom in / out (relative to current zoom)
3620 //==============================================================================
3621
3622 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3623   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3624   if ( V3dView.IsNull() ) {
3625     return 1;
3626   }
3627
3628   if ( argc == 2 ) {
3629     Standard_Real coef = Draw::Atof(argv[1]);
3630     if ( coef <= 0.0 ) {
3631       di << argv[1] << "Invalid value\n";
3632       return 1;
3633     }
3634     V3dView->SetZoom( Draw::Atof(argv[1]) );
3635     return 0;
3636   } else {
3637     di << argv[0] << " Invalid number of arguments\n";
3638     return 1;
3639   }
3640 }
3641
3642 //==============================================================================
3643 //function : VPan
3644 //purpose  : View panning (in pixels)
3645 //==============================================================================
3646
3647 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3648   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3649   if ( V3dView.IsNull() ) return 1;
3650
3651   if ( argc == 3 ) {
3652     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3653     return 0;
3654   } else {
3655     di << argv[0] << " Invalid number of arguments\n";
3656     return 1;
3657   }
3658 }
3659
3660 //==============================================================================
3661 //function : VPlace
3662 //purpose  : Place the point (in pixels) at the center of the window
3663 //==============================================================================
3664 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3665 {
3666   Handle(V3d_View) aView = ViewerTest::CurrentView();
3667   if (aView.IsNull())
3668   {
3669     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3670     return 1;
3671   }
3672
3673   if (theArgNb != 3)
3674   {
3675     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3676     return 1;
3677   }
3678
3679   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3680
3681   return 0;
3682 }
3683
3684 //==============================================================================
3685 //function : VExport
3686 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3687 //==============================================================================
3688
3689 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3690 {
3691   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3692   if (V3dView.IsNull())
3693     return 1;
3694
3695   if (argc == 1)
3696   {
3697     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3698     return 1;
3699   }
3700
3701   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3702   TCollection_AsciiString aFormatStr;
3703
3704   TCollection_AsciiString aFileName (argv[1]);
3705   Standard_Integer aLen = aFileName.Length();
3706
3707   if (argc > 2)
3708   {
3709     aFormatStr = TCollection_AsciiString (argv[2]);
3710   }
3711   else if (aLen >= 4)
3712   {
3713     if (aFileName.Value (aLen - 2) == '.')
3714     {
3715       aFormatStr = aFileName.ToCString() + aLen - 2;
3716     }
3717     else if (aFileName.Value (aLen - 3) == '.')
3718     {
3719       aFormatStr = aFileName.ToCString() + aLen - 3;
3720     }
3721     else
3722     {
3723       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3724       return 1;
3725     }
3726   }
3727   else
3728   {
3729     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3730     return 1;
3731   }
3732
3733   aFormatStr.UpperCase();
3734   if (aFormatStr == "PS")
3735     anExpFormat = Graphic3d_EF_PostScript;
3736   else if (aFormatStr == "EPS")
3737     anExpFormat = Graphic3d_EF_EnhPostScript;
3738   else if (aFormatStr == "TEX")
3739     anExpFormat = Graphic3d_EF_TEX;
3740   else if (aFormatStr == "PDF")
3741     anExpFormat = Graphic3d_EF_PDF;
3742   else if (aFormatStr == "SVG")
3743     anExpFormat = Graphic3d_EF_SVG;
3744   else if (aFormatStr == "PGF")
3745     anExpFormat = Graphic3d_EF_PGF;
3746   else if (aFormatStr == "EMF")
3747     anExpFormat = Graphic3d_EF_EMF;
3748   else
3749   {
3750     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3751     return 1;
3752   }
3753
3754   Standard_DISABLE_DEPRECATION_WARNINGS
3755   try
3756   {
3757     if (!V3dView->Export (argv[1], anExpFormat))
3758     {
3759       di << "Error: export of image to " << aFormatStr << " failed!\n";
3760     }
3761   }
3762   catch (Standard_Failure const& anException)
3763   {
3764     di << "Error: export of image to " << aFormatStr << " failed";
3765     di << " (exception: " << anException.GetMessageString() << ")";
3766   }
3767   Standard_ENABLE_DEPRECATION_WARNINGS
3768   return 0;
3769 }
3770
3771 static int VColorScale (Draw_Interpretor& theDI,
3772                         Standard_Integer  theArgNb,
3773                         const char**      theArgVec)
3774 {
3775   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3776   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3777   if (aContext.IsNull())
3778   {
3779     std::cout << "Error: no active view!\n";
3780     return 1;
3781   }
3782   if (theArgNb <= 1)
3783   {
3784     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3785     return 1;
3786   }
3787
3788   Handle(AIS_ColorScale) aColorScale;
3789   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3790   {
3791     // find existing object
3792     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3793     if (aColorScale.IsNull())
3794     {
3795       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3796       return 1;
3797     }
3798   }
3799
3800   if (theArgNb <= 2)
3801   {
3802     if (aColorScale.IsNull())
3803     {
3804       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3805       return 1;
3806     }
3807
3808     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3809           << "Min range: "            << aColorScale->GetMin() << "\n"
3810           << "Max range: "            << aColorScale->GetMax() << "\n"
3811           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3812           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3813           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3814           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3815           << "Label position: ";
3816     switch (aColorScale->GetLabelPosition())
3817     {
3818       case Aspect_TOCSP_NONE:
3819         theDI << "None\n";
3820         break;
3821       case Aspect_TOCSP_LEFT:
3822         theDI << "Left\n";
3823         break;
3824       case Aspect_TOCSP_RIGHT:
3825         theDI << "Right\n";
3826         break;
3827       case Aspect_TOCSP_CENTER:
3828         theDI << "Center\n";
3829         break;
3830     }
3831     return 0;
3832   }
3833
3834   if (aColorScale.IsNull())
3835   {
3836     aColorScale = new AIS_ColorScale();
3837     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3838     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3839   }
3840
3841   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3842   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3843   {
3844     Standard_CString        anArg = theArgVec[anArgIter];
3845     TCollection_AsciiString aFlag (anArg);
3846     aFlag.LowerCase();
3847     if (anUpdateTool.parseRedrawMode (aFlag))
3848     {
3849       continue;
3850     }
3851     else if (aFlag == "-range")
3852     {
3853       if (anArgIter + 3 >= theArgNb)
3854       {
3855         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3856         return 1;
3857       }
3858
3859       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3860       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3861       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3862       if (!aRangeMin.IsRealValue()
3863        || !aRangeMax.IsRealValue())
3864       {
3865         std::cout << "Error: the range values should be real!\n";
3866         return 1;
3867       }
3868       else if (!aNbIntervals.IsIntegerValue())
3869       {
3870         std::cout << "Error: the number of intervals should be integer!\n";
3871         return 1;
3872       }
3873
3874       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3875       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3876     }
3877     else if (aFlag == "-font")
3878     {
3879       if (anArgIter + 1 >= theArgNb)
3880       {
3881         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3882         return 1;
3883       }
3884       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3885       if (!aFontArg.IsIntegerValue())
3886       {
3887         std::cout << "Error: HeightFont value should be integer!\n";
3888         return 1;
3889       }
3890
3891       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3892       anArgIter += 1;
3893     }
3894     else if (aFlag == "-textpos")
3895     {
3896       if (anArgIter + 1 >= theArgNb)
3897       {
3898         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3899         return 1;
3900       }
3901
3902       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3903       aTextPosArg.LowerCase();
3904       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3905       if (aTextPosArg == "none")
3906       {
3907         aLabPosition = Aspect_TOCSP_NONE;
3908       }
3909       else if (aTextPosArg == "left")
3910       {
3911         aLabPosition = Aspect_TOCSP_LEFT;
3912       }
3913       else if (aTextPosArg == "right")
3914       {
3915         aLabPosition = Aspect_TOCSP_RIGHT;
3916       }
3917       else if (aTextPosArg == "center")
3918       {
3919         aLabPosition = Aspect_TOCSP_CENTER;
3920       }
3921       else
3922       {
3923         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3924         return 1;
3925       }
3926       aColorScale->SetLabelPosition (aLabPosition);
3927     }
3928     else if (aFlag == "-logarithmic"
3929           || aFlag == "-log")
3930     {
3931       if (anArgIter + 1 >= theArgNb)
3932       {
3933         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3934         return 1;
3935       }
3936
3937       Standard_Boolean IsLog;
3938       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3939       {
3940         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3941         return 1;
3942       }
3943       aColorScale->SetLogarithmic (IsLog);
3944     }
3945     else if (aFlag == "-huerange"
3946           || aFlag == "-hue")
3947     {
3948       if (anArgIter + 2 >= theArgNb)
3949       {
3950         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3951         return 1;
3952       }
3953
3954       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3955       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3956       aColorScale->SetHueRange (aHueMin, aHueMax);
3957     }
3958     else if (aFlag == "-colorrange")
3959     {
3960       Quantity_Color aColorMin, aColorMax;
3961       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3962                                                             theArgVec + (anArgIter + 1),
3963                                                             aColorMin);
3964       anArgIter += aNbParsed1;
3965       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3966                                                             theArgVec + (anArgIter + 1),
3967                                                             aColorMax);
3968       anArgIter += aNbParsed2;
3969       if (aNbParsed1 == 0
3970        || aNbParsed2 == 0)
3971       {
3972         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3973         return 1;
3974       }
3975
3976       aColorScale->SetColorRange (aColorMin, aColorMax);
3977     }
3978     else if (aFlag == "-reversed"
3979           || aFlag == "-inverted"
3980           || aFlag == "-topdown"
3981           || aFlag == "-bottomup")
3982     {
3983       Standard_Boolean toEnable = Standard_True;
3984       if (anArgIter + 1 < theArgNb
3985        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3986       {
3987         ++anArgIter;
3988       }
3989       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3990     }
3991     else if (aFlag == "-smooth"
3992           || aFlag == "-smoothtransition")
3993     {
3994       Standard_Boolean toEnable = Standard_True;
3995       if (anArgIter + 1 < theArgNb
3996        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3997       {
3998         ++anArgIter;
3999       }
4000       aColorScale->SetSmoothTransition (toEnable);
4001     }
4002     else if (aFlag == "-xy")
4003     {
4004       if (anArgIter + 2 >= theArgNb)
4005       {
4006         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4007         return 1;
4008       }
4009
4010       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
4011       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
4012       if (!anX.IsIntegerValue()
4013        || !anY.IsIntegerValue())
4014       {
4015         std::cout << "Error: coordinates should be integer values!\n";
4016         return 1;
4017       }
4018
4019       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
4020     }
4021     else if (aFlag == "-width"
4022           || aFlag == "-w"
4023           || aFlag == "-breadth")
4024     {
4025       if (anArgIter + 1 >= theArgNb)
4026       {
4027         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4028         return 1;
4029       }
4030
4031       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
4032       if (!aBreadth.IsIntegerValue())
4033       {
4034         std::cout << "Error: a width should be an integer value!\n";
4035         return 1;
4036       }
4037       aColorScale->SetBreadth (aBreadth.IntegerValue());
4038     }
4039     else if (aFlag == "-height"
4040           || aFlag == "-h")
4041     {
4042       if (anArgIter + 1 >= theArgNb)
4043       {
4044         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4045         return 1;
4046       }
4047
4048       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
4049       if (!aHeight.IsIntegerValue())
4050       {
4051         std::cout << "Error: a width should be an integer value!\n";
4052         return 1;
4053       }
4054       aColorScale->SetHeight (aHeight.IntegerValue());
4055     }
4056     else if (aFlag == "-color")
4057     {
4058       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4059       {
4060         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
4061         return 1;
4062       }
4063       else if (anArgIter + 2 >= theArgNb)
4064       {
4065         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4066         return 1;
4067       }
4068
4069       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
4070       if (!anInd.IsIntegerValue())
4071       {
4072         std::cout << "Error: Index value should be integer!\n";
4073         return 1;
4074       }
4075       const Standard_Integer anIndex = anInd.IntegerValue();
4076       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
4077       {
4078         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
4079         return 1;
4080       }
4081
4082       Quantity_Color aColor;
4083       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4084                                                            theArgVec + (anArgIter + 1),
4085                                                            aColor);
4086       if (aNbParsed == 0)
4087       {
4088         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4089         return 1;
4090       }
4091       aColorScale->SetIntervalColor (aColor, anIndex);
4092       aColorScale->SetColorType (Aspect_TOCSD_USER);
4093       anArgIter += aNbParsed;
4094     }
4095     else if (aFlag == "-label")
4096     {
4097       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4098       {
4099         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4100         return 1;
4101       }
4102       else if (anArgIter + 2 >= theArgNb)
4103       {
4104         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4105         return 1;
4106       }
4107
4108       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4109       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4110       {
4111         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4112         return 1;
4113       }
4114
4115       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4116       aColorScale->SetLabel     (aText, anIndex);
4117       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4118       anArgIter += 2;
4119     }
4120     else if (aFlag == "-labelat"
4121           || aFlag == "-labat"
4122           || aFlag == "-labelatborder"
4123           || aFlag == "-labatborder"
4124           || aFlag == "-labelatcenter"
4125           || aFlag == "-labatcenter")
4126     {
4127       Standard_Boolean toEnable = Standard_True;
4128       if (aFlag == "-labelat"
4129        || aFlag == "-labat")
4130       {
4131         Standard_Integer aLabAtBorder = -1;
4132         if (++anArgIter >= theArgNb)
4133         {
4134           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4135           anAtBorder.LowerCase();
4136           if (anAtBorder == "border")
4137           {
4138             aLabAtBorder = 1;
4139           }
4140           else if (anAtBorder == "center")
4141           {
4142             aLabAtBorder = 0;
4143           }
4144         }
4145         if (aLabAtBorder == -1)
4146         {
4147           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4148           return 1;
4149         }
4150         toEnable = (aLabAtBorder == 1);
4151       }
4152       else if (anArgIter + 1 < theArgNb
4153             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4154       {
4155         ++anArgIter;
4156       }
4157       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4158                                   || aFlag == "-labatcenter"
4159                                    ? !toEnable
4160                                    :  toEnable);
4161     }
4162     else if (aFlag == "-colors")
4163     {
4164       Aspect_SequenceOfColor aSeq;
4165       for (;;)
4166       {
4167         Quantity_Color aColor;
4168         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4169                                                              theArgVec + (anArgIter + 1),
4170                                                              aColor);
4171         if (aNbParsed == 0)
4172         {
4173           break;
4174         }
4175         anArgIter += aNbParsed;
4176         aSeq.Append (aColor);
4177       }
4178       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4179       {
4180         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4181                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4182         return 1;
4183       }
4184
4185       aColorScale->SetColors    (aSeq);
4186       aColorScale->SetColorType (Aspect_TOCSD_USER);
4187     }
4188     else if (aFlag == "-labels"
4189           || aFlag == "-freelabels")
4190     {
4191       if (anArgIter + 1 >= theArgNb)
4192       {
4193         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4194         return 1;
4195       }
4196
4197       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4198                                  ? aColorScale->GetNumberOfIntervals() + 1
4199                                  : aColorScale->GetNumberOfIntervals();
4200       if (aFlag == "-freelabels")
4201       {
4202         ++anArgIter;
4203         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4204       }
4205       if (anArgIter + aNbLabels >= theArgNb)
4206       {
4207         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4208         return 1;
4209       }
4210
4211       TColStd_SequenceOfExtendedString aSeq;
4212       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4213       {
4214         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4215       }
4216       aColorScale->SetLabels (aSeq);
4217       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4218     }
4219     else if (aFlag == "-title")
4220     {
4221       if (anArgIter + 1 >= theArgNb)
4222       {
4223         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4224         return 1;
4225       }
4226
4227       Standard_Boolean isTwoArgs = Standard_False;
4228       if (anArgIter + 2 < theArgNb)
4229       {
4230         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4231         aSecondArg.LowerCase();
4232       Standard_DISABLE_DEPRECATION_WARNINGS
4233         if (aSecondArg == "none")
4234         {
4235           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4236           isTwoArgs = Standard_True;
4237         }
4238         else if (aSecondArg == "left")
4239         {
4240           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4241           isTwoArgs = Standard_True;
4242         }
4243         else if (aSecondArg == "right")
4244         {
4245           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4246           isTwoArgs = Standard_True;
4247         }
4248         else if (aSecondArg == "center")
4249         {
4250           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4251           isTwoArgs = Standard_True;
4252         }
4253       Standard_ENABLE_DEPRECATION_WARNINGS
4254       }
4255
4256       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4257       if (isTwoArgs)
4258       {
4259         anArgIter += 1;
4260       }
4261       anArgIter += 1;
4262     }
4263     else if (aFlag == "-demoversion"
4264           || aFlag == "-demo")
4265     {
4266       aColorScale->SetPosition (0, 0);
4267       aColorScale->SetTextHeight (16);
4268       aColorScale->SetRange (0.0, 100.0);
4269       aColorScale->SetNumberOfIntervals (10);
4270       aColorScale->SetBreadth (0);
4271       aColorScale->SetHeight  (0);
4272       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4273       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4274       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4275     }
4276     else if (aFlag == "-findcolor")
4277     {
4278       if (anArgIter + 1 >= theArgNb)
4279       {
4280         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4281         return 1;
4282       }
4283
4284       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4285
4286       if (!anArg1.IsRealValue())
4287       {
4288         std::cout << "Error: the value should be real!\n";
4289         return 1;
4290       }
4291
4292       Quantity_Color aColor;
4293       aColorScale->FindColor (anArg1.RealValue(), aColor);
4294       theDI << Quantity_Color::StringName (aColor.Name());
4295       return 0;
4296     }
4297     else
4298     {
4299       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4300       return 1;
4301     }
4302   }
4303
4304   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4305   aView->Window()->Size (aWinWidth, aWinHeight);
4306   if (aColorScale->GetBreadth() == 0)
4307   {
4308     aColorScale->SetBreadth (aWinWidth);
4309   }
4310   if (aColorScale->GetHeight() == 0)
4311   {
4312     aColorScale->SetHeight (aWinHeight);
4313   }
4314   aColorScale->SetToUpdate();
4315   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4316   return 0;
4317 }
4318
4319 //==============================================================================
4320 //function : VGraduatedTrihedron
4321 //purpose  : Displays or hides a graduated trihedron
4322 //==============================================================================
4323 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4324                                   Quantity_Color& theColor)
4325 {
4326   Quantity_NameOfColor aColorName;
4327   TCollection_AsciiString aVal = theValue;
4328   aVal.UpperCase();
4329   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4330   {
4331     return Standard_False;
4332   }
4333   theColor = Quantity_Color (aColorName);
4334   return Standard_True;
4335 }
4336
4337 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4338 {
4339   if (theArgNum < 2)
4340   {
4341     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4342               << theArgs[0] <<"' for more information.\n";
4343     return 1;  //TCL_ERROR
4344   }
4345
4346   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4347   TCollection_AsciiString aParseKey;
4348   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4349   {
4350     TCollection_AsciiString anArg (theArgs [anArgIt]);
4351
4352     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4353     {
4354       aParseKey = anArg;
4355       aParseKey.Remove (1);
4356       aParseKey.LowerCase();
4357       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4358       continue;
4359     }
4360
4361     if (aParseKey.IsEmpty())
4362     {
4363       continue;
4364     }
4365
4366     aMapOfArgs(aParseKey)->Append (anArg);
4367   }
4368
4369   // Check parameters
4370   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4371        aMapIt.More(); aMapIt.Next())
4372   {
4373     const TCollection_AsciiString& aKey = aMapIt.Key();
4374     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4375
4376     // Bool key, without arguments
4377     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4378         && anArgs->IsEmpty())
4379     {
4380       continue;
4381     }
4382
4383     // One argument
4384     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4385           && anArgs->Length() == 1)
4386     {
4387       continue;
4388     }
4389
4390     // On/off arguments
4391     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4392         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4393         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4394         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4395         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4396     {
4397       continue;
4398     }
4399
4400     // One string argument
4401     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4402           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4403           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4404     {
4405       continue;
4406     }
4407
4408     // One integer argument
4409     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4410           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4411           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4412           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4413          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4414     {
4415       continue;
4416     }
4417
4418     // One real argument
4419     if ( aKey.IsEqual ("arrowlength")
4420          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4421     {
4422       continue;
4423     }
4424
4425     // Two string arguments
4426     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4427          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4428     {
4429       continue;
4430     }
4431
4432     TCollection_AsciiString aLowerKey;
4433     aLowerKey  = "-";
4434     aLowerKey += aKey;
4435     aLowerKey.LowerCase();
4436     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4437     std::cout << "Type help for more information.\n";
4438     return 1;
4439   }
4440
4441   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4442   if (anAISContext.IsNull())
4443   {
4444     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4445     return 1;
4446   }
4447
4448   Standard_Boolean toDisplay = Standard_True;
4449   Quantity_Color aColor;
4450   Graphic3d_GraduatedTrihedron aTrihedronData;
4451   // Process parameters
4452   Handle(TColStd_HSequenceOfAsciiString) aValues;
4453   if (aMapOfArgs.Find ("off", aValues))
4454   {
4455     toDisplay = Standard_False;
4456   }
4457
4458   // AXES NAMES
4459   if (aMapOfArgs.Find ("xname", aValues))
4460   {
4461     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4462   }
4463   if (aMapOfArgs.Find ("yname", aValues))
4464   {
4465     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4466   }
4467   if (aMapOfArgs.Find ("zname", aValues))
4468   {
4469     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4470   }
4471   if (aMapOfArgs.Find ("xdrawname", aValues))
4472   {
4473     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4474   }
4475   if (aMapOfArgs.Find ("ydrawname", aValues))
4476   {
4477     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4478   }
4479   if (aMapOfArgs.Find ("zdrawname", aValues))
4480   {
4481     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4482   }
4483   if (aMapOfArgs.Find ("xnameoffset", aValues))
4484   {
4485     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4486   }
4487   if (aMapOfArgs.Find ("ynameoffset", aValues))
4488   {
4489     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4490   }
4491   if (aMapOfArgs.Find ("znameoffset", aValues))
4492   {
4493     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4494   }
4495
4496   // COLORS
4497   if (aMapOfArgs.Find ("xnamecolor", aValues))
4498   {
4499     if (!GetColor (aValues->Value(1), aColor))
4500     {
4501       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4502       return 1;
4503     }
4504     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4505   }
4506   if (aMapOfArgs.Find ("ynamecolor", aValues))
4507   {
4508     if (!GetColor (aValues->Value(1), aColor))
4509     {
4510       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4511       return 1;
4512     }
4513     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4514   }
4515   if (aMapOfArgs.Find ("znamecolor", aValues))
4516   {
4517     if (!GetColor (aValues->Value(1), aColor))
4518     {
4519       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4520       return 1;
4521     }
4522     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4523   }
4524   if (aMapOfArgs.Find ("xcolor", aValues))
4525   {
4526     if (!GetColor (aValues->Value(1), aColor))
4527     {
4528       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4529       return 1;
4530     }
4531     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4532   }
4533   if (aMapOfArgs.Find ("ycolor", aValues))
4534   {
4535     if (!GetColor (aValues->Value(1), aColor))
4536     {
4537       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4538       return 1;
4539     }
4540     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4541   }
4542   if (aMapOfArgs.Find ("zcolor", aValues))
4543   {
4544     if (!GetColor (aValues->Value(1), aColor))
4545     {
4546       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4547       return 1;
4548     }
4549     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4550   }
4551
4552   // TICKMARKS
4553   if (aMapOfArgs.Find ("xticks", aValues))
4554   {
4555     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4556   }
4557   if (aMapOfArgs.Find ("yticks", aValues))
4558   {
4559     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4560   }
4561   if (aMapOfArgs.Find ("zticks", aValues))
4562   {
4563     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4564   }
4565   if (aMapOfArgs.Find ("xticklength", aValues))
4566   {
4567     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4568   }
4569   if (aMapOfArgs.Find ("yticklength", aValues))
4570   {
4571     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4572   }
4573   if (aMapOfArgs.Find ("zticklength", aValues))
4574   {
4575     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4576   }
4577   if (aMapOfArgs.Find ("xdrawticks", aValues))
4578   {
4579     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4580   }
4581   if (aMapOfArgs.Find ("ydrawticks", aValues))
4582   {
4583     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4584   }
4585   if (aMapOfArgs.Find ("zdrawticks", aValues))
4586   {
4587     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4588   }
4589
4590   // VALUES
4591   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4592   {
4593     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4594   }
4595   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4596   {
4597     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4598   }
4599   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4600   {
4601     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4602   }
4603   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4604   {
4605     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4606   }
4607   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4608   {
4609     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4610   }
4611   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4612   {
4613     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4614   }
4615
4616   // ARROWS
4617   if (aMapOfArgs.Find ("arrowlength", aValues))
4618   {
4619     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4620   }
4621
4622   // FONTS
4623   if (aMapOfArgs.Find ("namefont", aValues))
4624   {
4625     aTrihedronData.SetNamesFont (aValues->Value(1));
4626   }
4627   if (aMapOfArgs.Find ("valuesfont", aValues))
4628   {
4629     aTrihedronData.SetValuesFont (aValues->Value(1));
4630   }
4631
4632   if (aMapOfArgs.Find ("drawgrid", aValues))
4633   {
4634     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4635   }
4636   if (aMapOfArgs.Find ("drawaxes", aValues))
4637   {
4638     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4639   }
4640
4641   // The final step: display of erase trihedron
4642   if (toDisplay)
4643   {
4644     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4645   }
4646   else
4647   {
4648     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4649   }
4650
4651   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4652   ViewerTest::CurrentView()->Redraw();
4653
4654   return 0;
4655 }
4656
4657 //==============================================================================
4658 //function : VTile
4659 //purpose  :
4660 //==============================================================================
4661 static int VTile (Draw_Interpretor& theDI,
4662                   Standard_Integer  theArgNb,
4663                   const char**      theArgVec)
4664 {
4665   Handle(V3d_View) aView = ViewerTest::CurrentView();
4666   if (aView.IsNull())
4667   {
4668     std::cerr << "Error: no active viewer.\n";
4669     return 1;
4670   }
4671
4672   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4673   if (theArgNb < 2)
4674   {
4675     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4676           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4677           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4678     return 0;
4679   }
4680
4681   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4682   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4683   {
4684     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4685     anArg.LowerCase();
4686     if (anArg == "-lowerleft"
4687      || anArg == "-upperleft")
4688     {
4689       if (anArgIter + 3 < theArgNb)
4690       {
4691         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4692         return 1;
4693       }
4694       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4695       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4696       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4697     }
4698     else if (anArg == "-total"
4699           || anArg == "-totalsize"
4700           || anArg == "-viewsize")
4701     {
4702       if (anArgIter + 3 < theArgNb)
4703       {
4704         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4705         return 1;
4706       }
4707       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4708       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4709       if (aTile.TotalSize.x() < 1
4710        || aTile.TotalSize.y() < 1)
4711       {
4712         std::cerr << "Error: total size is incorrect.\n";
4713         return 1;
4714       }
4715     }
4716     else if (anArg == "-tilesize")
4717     {
4718       if (anArgIter + 3 < theArgNb)
4719       {
4720         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4721         return 1;
4722       }
4723
4724       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4725       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4726       if (aTile.TileSize.x() < 1
4727        || aTile.TileSize.y() < 1)
4728       {
4729         std::cerr << "Error: tile size is incorrect.\n";
4730         return 1;
4731       }
4732     }
4733     else if (anArg == "-unset")
4734     {
4735       aView->Camera()->SetTile (Graphic3d_CameraTile());
4736       aView->Redraw();
4737       return 0;
4738     }
4739   }
4740
4741   if (aTile.TileSize.x() < 1
4742    || aTile.TileSize.y() < 1)
4743   {
4744     std::cerr << "Error: tile size is undefined.\n";
4745     return 1;
4746   }
4747   else if (aTile.TotalSize.x() < 1
4748         || aTile.TotalSize.y() < 1)
4749   {
4750     std::cerr << "Error: total size is undefined.\n";
4751     return 1;
4752   }
4753
4754   aView->Camera()->SetTile (aTile);
4755   aView->Redraw();
4756   return 0;
4757 }
4758
4759 //! Format ZLayer ID.
4760 inline const char* formZLayerId (const Standard_Integer theLayerId)
4761 {
4762   switch (theLayerId)
4763   {
4764     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4765     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4766     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4767     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4768     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4769     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4770   }
4771   return "";
4772 }
4773
4774 //! Print the ZLayer information.
4775 inline void printZLayerInfo (Draw_Interpretor& theDI,
4776                              const Graphic3d_ZLayerSettings& theLayer)
4777 {
4778   if (!theLayer.Name().IsEmpty())
4779   {
4780     theDI << "  Name: " << theLayer.Name() << "\n";
4781   }
4782   if (theLayer.IsImmediate())
4783   {
4784     theDI << "  Immediate: TRUE\n";
4785   }
4786   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4787   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
4788   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
4789   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4790   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4791   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4792   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4793   {
4794     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4795   }
4796 }
4797
4798 //==============================================================================
4799 //function : VZLayer
4800 //purpose  : Test z layer operations for v3d viewer
4801 //==============================================================================
4802 static int VZLayer (Draw_Interpretor& theDI,
4803                     Standard_Integer  theArgNb,
4804                     const char**      theArgVec)
4805 {
4806   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4807   if (aContextAIS.IsNull())
4808   {
4809     std::cout << "No active viewer!\n";
4810     return 1;
4811   }
4812
4813   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4814   if (theArgNb < 2)
4815   {
4816     TColStd_SequenceOfInteger aLayers;
4817     aViewer->GetAllZLayers (aLayers);
4818     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4819     {
4820       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4821       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4822       printZLayerInfo (theDI, aSettings);
4823     }
4824     return 1;
4825   }
4826
4827   Standard_Integer anArgIter = 1;
4828   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4829   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4830   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4831   {
4832     ++anArgIter;
4833   }
4834
4835   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4836   if (aFirstArg.IsIntegerValue())
4837   {
4838     ++anArgIter;
4839     aLayerId = aFirstArg.IntegerValue();
4840   }
4841   else
4842   {
4843     aFirstArg.LowerCase();
4844     if (aFirstArg == "default"
4845      || aFirstArg == "def")
4846     {
4847       aLayerId = Graphic3d_ZLayerId_Default;
4848       ++anArgIter;
4849     }
4850     else if (aFirstArg == "top")
4851     {
4852       aLayerId = Graphic3d_ZLayerId_Top;
4853       ++anArgIter;
4854     }
4855     else if (aFirstArg == "topmost")
4856     {
4857       aLayerId = Graphic3d_ZLayerId_Topmost;
4858       ++anArgIter;
4859     }
4860     else if (aFirstArg == "overlay"
4861           || aFirstArg == "toposd")
4862     {
4863       aLayerId = Graphic3d_ZLayerId_TopOSD;
4864       ++anArgIter;
4865     }
4866     else if (aFirstArg == "underlay"
4867           || aFirstArg == "botosd")
4868     {
4869       aLayerId = Graphic3d_ZLayerId_BotOSD;
4870       ++anArgIter;
4871     }
4872     else
4873     {
4874       TColStd_SequenceOfInteger aLayers;
4875       aViewer->GetAllZLayers (aLayers);
4876       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4877       {
4878         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4879         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4880         {
4881           aLayerId = aLayeriter.Value();
4882           ++anArgIter;
4883           break;
4884         }
4885       }
4886     }
4887   }
4888
4889   for (; anArgIter < theArgNb; ++anArgIter)
4890   {
4891     // perform operation
4892     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4893     anArg.LowerCase();
4894     if (anUpdateTool.parseRedrawMode (anArg))
4895     {
4896       //
4897     }
4898     else if (anArg == "-add"
4899           || anArg == "add")
4900     {
4901       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4902       if (!aViewer->AddZLayer (aLayerId))
4903       {
4904         std::cout << "Error: can not add a new z layer!\n";
4905         return 0;
4906       }
4907
4908       theDI << aLayerId;
4909     }
4910     else if (anArg == "-del"
4911           || anArg == "-delete"
4912           || anArg == "del")
4913     {
4914       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4915       {
4916         if (++anArgIter >= theArgNb)
4917         {
4918           std::cout << "Syntax error: id of z layer to remove is missing\n";
4919           return 1;
4920         }
4921
4922         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4923       }
4924
4925       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4926        || aLayerId == Graphic3d_ZLayerId_Default
4927        || aLayerId == Graphic3d_ZLayerId_Top
4928        || aLayerId == Graphic3d_ZLayerId_Topmost
4929        || aLayerId == Graphic3d_ZLayerId_TopOSD
4930        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4931       {
4932         std::cout << "Syntax error: standard Z layer can not be removed\n";
4933         return 1;
4934       }
4935
4936       // move all object displayed in removing layer to default layer
4937       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4938            anObjIter.More(); anObjIter.Next())
4939       {
4940         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4941         if (aPrs.IsNull()
4942          || aPrs->ZLayer() != aLayerId)
4943         {
4944           continue;
4945         }
4946         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4947       }
4948
4949       if (!aViewer->RemoveZLayer (aLayerId))
4950       {
4951         std::cout << "Z layer can not be removed!\n";
4952       }
4953       else
4954       {
4955         theDI << aLayerId << " ";
4956       }
4957     }
4958     else if (anArg == "-get"
4959           || anArg == "get")
4960     {
4961       TColStd_SequenceOfInteger aLayers;
4962       aViewer->GetAllZLayers (aLayers);
4963       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4964       {
4965         theDI << aLayeriter.Value() << " ";
4966       }
4967
4968       theDI << "\n";
4969     }
4970     else if (anArg == "-name")
4971     {
4972       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4973       {
4974         std::cout << "Syntax error: id of Z layer is missing\n";
4975         return 1;
4976       }
4977
4978       if (++anArgIter >= theArgNb)
4979       {
4980         std::cout << "Syntax error: name is missing\n";
4981         return 1;
4982       }
4983
4984       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4985       aSettings.SetName (theArgVec[anArgIter]);
4986       aViewer->SetZLayerSettings (aLayerId, aSettings);
4987     }
4988     else if (anArg == "-origin")
4989     {
4990       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4991       {
4992         std::cout << "Syntax error: id of Z layer is missing\n";
4993         return 1;
4994       }
4995
4996       if (anArgIter + 2 >= theArgNb)
4997       {
4998         std::cout << "Syntax error: origin coordinates are missing\n";
4999         return 1;
5000       }
5001
5002       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5003       gp_XYZ anOrigin;
5004       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5005       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5006       anOrigin.SetZ (0.0);
5007       if (anArgIter + 3 < theArgNb)
5008       {
5009         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5010         anArgIter += 3;
5011       }
5012       else
5013       {
5014         anArgIter += 2;
5015       }
5016       aSettings.SetOrigin (anOrigin);
5017       aViewer->SetZLayerSettings (aLayerId, aSettings);
5018     }
5019     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5020           && anArgIter + 1 < theArgNb
5021           && (anArg == "-cullingdistance"
5022            || anArg == "-cullingdist"
5023            || anArg == "-culldistance"
5024            || anArg == "-culldist"
5025            || anArg == "-distcull"
5026            || anArg == "-distculling"
5027            || anArg == "-distanceculling"))
5028     {
5029       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5030       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5031       aSettings.SetCullingDistance (aDist);
5032       aViewer->SetZLayerSettings (aLayerId, aSettings);
5033     }
5034     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5035           && anArgIter + 1 < theArgNb
5036           && (anArg == "-cullingsize"
5037            || anArg == "-cullsize"
5038            || anArg == "-sizecull"
5039            || anArg == "-sizeculling"))
5040     {
5041       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5042       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5043       aSettings.SetCullingSize (aSize);
5044       aViewer->SetZLayerSettings (aLayerId, aSettings);
5045     }
5046     else if (anArg == "-settings"
5047           || anArg == "settings")
5048     {
5049       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5050       {
5051         if (++anArgIter >= theArgNb)
5052         {
5053           std::cout << "Syntax error: id of Z layer is missing\n";
5054           return 1;
5055         }
5056
5057         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5058       }
5059
5060       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5061       printZLayerInfo (theDI, aSettings);
5062     }
5063     else if (anArg == "-enable"
5064           || anArg == "enable"
5065           || anArg == "-disable"
5066           || anArg == "disable")
5067     {
5068       const Standard_Boolean toEnable = anArg == "-enable"
5069                                      || anArg == "enable";
5070       if (++anArgIter >= theArgNb)
5071       {
5072         std::cout << "Syntax error: option name is missing\n";
5073         return 1;
5074       }
5075
5076       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5077       aSubOp.LowerCase();
5078       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5079       {
5080         if (++anArgIter >= theArgNb)
5081         {
5082           std::cout << "Syntax error: id of Z layer is missing\n";
5083           return 1;
5084         }
5085
5086         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5087       }
5088
5089       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5090       if (aSubOp == "depthtest"
5091        || aSubOp == "test")
5092       {
5093         aSettings.SetEnableDepthTest (toEnable);
5094       }
5095       else if (aSubOp == "depthwrite"
5096             || aSubOp == "write")
5097       {
5098         aSettings.SetEnableDepthWrite (toEnable);
5099       }
5100       else if (aSubOp == "depthclear"
5101             || aSubOp == "clear")
5102       {
5103         aSettings.SetClearDepth (toEnable);
5104       }
5105       else if (aSubOp == "depthoffset"
5106             || aSubOp == "offset")
5107       {
5108         Graphic3d_PolygonOffset aParams;
5109         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5110         if (toEnable)
5111         {
5112           if (anArgIter + 2 >= theArgNb)
5113           {
5114             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5115             return 1;
5116           }
5117
5118           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5119           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5120         }
5121         aSettings.SetPolygonOffset (aParams);
5122       }
5123       else if (aSubOp == "positiveoffset"
5124             || aSubOp == "poffset")
5125       {
5126         if (toEnable)
5127         {
5128           aSettings.SetDepthOffsetPositive();
5129         }
5130         else
5131         {
5132           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5133         }
5134       }
5135       else if (aSubOp == "negativeoffset"
5136             || aSubOp == "noffset")
5137       {
5138         if (toEnable)
5139         {
5140           aSettings.SetDepthOffsetNegative();
5141         }
5142         else
5143         {
5144           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5145         }
5146       }
5147       else if (aSubOp == "textureenv")
5148       {
5149         aSettings.SetEnvironmentTexture (toEnable);
5150       }
5151
5152       aViewer->SetZLayerSettings (aLayerId, aSettings);
5153     }
5154     else
5155     {
5156       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5157       return 1;
5158     }
5159   }
5160
5161   return 0;
5162 }
5163
5164 // The interactive presentation of 2d layer item
5165 // for "vlayerline" command it provides a presentation of
5166 // line with user-defined linewidth, linetype and transparency.
5167 class V3d_LineItem : public AIS_InteractiveObject
5168 {
5169 public:
5170   // CASCADE RTTI
5171   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5172
5173   // constructor
5174   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5175                                Standard_Real X2, Standard_Real Y2,
5176                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5177                                Standard_Real theWidth    = 0.5,
5178                                Standard_Real theTransp   = 1.0);
5179
5180   private:
5181
5182   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5183                 const Handle(Prs3d_Presentation)& thePresentation,
5184                 const Standard_Integer theMode) Standard_OVERRIDE;
5185
5186   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5187                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5188   {}
5189
5190 private:
5191
5192   Standard_Real       myX1, myY1, myX2, myY2;
5193   Aspect_TypeOfLine   myType;
5194   Standard_Real       myWidth;
5195 };
5196
5197 // default constructor for line item
5198 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5199                            Standard_Real X2, Standard_Real Y2,
5200                            Aspect_TypeOfLine theType,
5201                            Standard_Real theWidth,
5202                            Standard_Real theTransp) :
5203   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5204   myType(theType), myWidth(theWidth)
5205 {
5206   SetTransparency (1-theTransp);
5207 }
5208
5209 // render line
5210 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5211                             const Handle(Prs3d_Presentation)& thePresentation,
5212                             const Standard_Integer /*theMode*/)
5213 {
5214   thePresentation->Clear();
5215   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5216   Standard_Integer aWidth, aHeight;
5217   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5218   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5219   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5220   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5221   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5222   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5223   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5224   aGroup->AddPrimitiveArray (aPrim);
5225 }
5226
5227 //=============================================================================
5228 //function : VLayerLine
5229 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5230 //         : linewidth, transparency coefficient
5231 //============================================================================
5232 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5233 {
5234   // get the active view
5235   Handle(V3d_View) aView = ViewerTest::CurrentView();
5236   if (aView.IsNull())
5237   {
5238     di << "Call vinit before!\n";
5239     return 1;
5240   }
5241   else if (argc < 5)
5242   {
5243     di << "Use: " << argv[0];
5244     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5245     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5246     di << "              0 - solid  \n";
5247     di << "              1 - dashed \n";
5248     di << "              2 - dot    \n";
5249     di << "              3 - dashdot\n";
5250     di << " transparency : { 0.0 - 1.0 } \n";
5251     di << "                  0.0 - transparent\n";
5252     di << "                  1.0 - visible    \n";
5253     return 1;
5254   }
5255
5256   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5257   // get the input params
5258   Standard_Real X1 = Draw::Atof(argv[1]);
5259   Standard_Real Y1 = Draw::Atof(argv[2]);
5260   Standard_Real X2 = Draw::Atof(argv[3]);
5261   Standard_Real Y2 = Draw::Atof(argv[4]);
5262
5263   Standard_Real aWidth = 0.5;
5264   Standard_Real aTransparency = 1.0;
5265
5266   // has width
5267   if (argc > 5)
5268     aWidth = Draw::Atof(argv[5]);
5269
5270   // select appropriate line type
5271   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5272   if (argc > 6
5273   && !ViewerTest::ParseLineType (argv[6], aLineType))
5274   {
5275     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5276     return 1;
5277   }
5278
5279   // has transparency
5280   if (argc > 7)
5281   {
5282     aTransparency = Draw::Atof(argv[7]);
5283     if (aTransparency < 0 || aTransparency > 1.0)
5284       aTransparency = 1.0;
5285   }
5286
5287   static Handle (V3d_LineItem) aLine;
5288   if (!aLine.IsNull())
5289   {
5290     aContext->Erase (aLine, Standard_False);
5291   }
5292   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5293                             aLineType, aWidth,
5294                             aTransparency);
5295
5296   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5297   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5298   aLine->SetToUpdate();
5299   aContext->Display (aLine, Standard_True);
5300
5301   return 0;
5302 }
5303
5304
5305 //==============================================================================
5306 //function : VGrid
5307 //purpose  :
5308 //==============================================================================
5309
5310 static int VGrid (Draw_Interpretor& /*theDI*/,
5311                   Standard_Integer  theArgNb,
5312                   const char**      theArgVec)
5313 {
5314   // get the active view
5315   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5316   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5317   if (aView.IsNull() || aViewer.IsNull())
5318   {
5319     std::cerr << "No active view. Please call vinit.\n";
5320     return 1;
5321   }
5322
5323   Aspect_GridType     aType = aViewer->GridType();
5324   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5325   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5326   Standard_Integer anIter = 1;
5327   for (; anIter < theArgNb; ++anIter)
5328   {
5329     const char* aValue = theArgVec[anIter];
5330     if (anUpdateTool.parseRedrawMode (aValue))
5331     {
5332       continue;
5333     }
5334     else if (*aValue == 'r')
5335     {
5336       aType = Aspect_GT_Rectangular;
5337     }
5338     else if (*aValue == 'c')
5339     {
5340       aType = Aspect_GT_Circular;
5341     }
5342     else if (*aValue == 'l')
5343     {
5344       aMode = Aspect_GDM_Lines;
5345     }
5346     else if (*aValue == 'p')
5347     {
5348       aMode = Aspect_GDM_Points;
5349     }
5350     else if (strcmp (aValue, "off" ) == 0)
5351     {
5352       aViewer->DeactivateGrid();
5353       return 0;
5354     }
5355     else
5356     {
5357       break;
5358     }
5359   }
5360
5361   Standard_Integer aTail = (theArgNb - anIter);
5362   if (aTail == 0)
5363   {
5364     aViewer->ActivateGrid (aType, aMode);
5365     return 0;
5366   }
5367   else if (aTail != 2 && aTail != 5)
5368   {
5369     std::cerr << "Incorrect arguments number! Usage:\n"
5370               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5371     return 1;
5372   }
5373
5374   Standard_Real anOriginX, anOriginY, aRotAngle;
5375   if (aType == Aspect_GT_Rectangular)
5376   {
5377     Standard_Real aRStepX, aRStepY;
5378     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5379
5380     anOriginX = Draw::Atof (theArgVec[anIter++]);
5381     anOriginY = Draw::Atof (theArgVec[anIter++]);
5382     if (aTail == 5)
5383     {
5384       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5385       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5386       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5387     }
5388     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5389     aViewer->ActivateGrid (aType, aMode);
5390   }
5391   else if (aType == Aspect_GT_Circular)
5392   {
5393     Standard_Real aRadiusStep;
5394     Standard_Integer aDivisionNumber;
5395     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5396
5397     anOriginX = Draw::Atof (theArgVec[anIter++]);
5398     anOriginY = Draw::Atof (theArgVec[anIter++]);
5399     if (aTail == 5)
5400     {
5401       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5402       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5403       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5404     }
5405
5406     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5407     aViewer->ActivateGrid (aType, aMode);
5408   }
5409
5410   return 0;
5411 }
5412
5413 //==============================================================================
5414 //function : VPriviledgedPlane
5415 //purpose  :
5416 //==============================================================================
5417
5418 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5419                               Standard_Integer  theArgNb,
5420                               const char**      theArgVec)
5421 {
5422   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5423   {
5424     std::cerr << "Error: wrong number of arguments! See usage:\n";
5425     theDI.PrintHelp (theArgVec[0]);
5426     return 1;
5427   }
5428
5429   // get the active viewer
5430   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5431   if (aViewer.IsNull())
5432   {
5433     std::cerr << "Error: no active viewer. Please call vinit.\n";
5434     return 1;
5435   }
5436
5437   if (theArgNb == 1)
5438   {
5439     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5440     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5441     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5442     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5443     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5444           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5445           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5446     return 0;
5447   }
5448
5449   Standard_Integer anArgIdx = 1;
5450   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5451   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5452   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5453   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5454   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5455   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5456
5457   gp_Ax3 aPriviledgedPlane;
5458   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5459   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5460   if (theArgNb > 7)
5461   {
5462     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5463     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5464     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5465     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5466     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5467   }
5468   else
5469   {
5470     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5471   }
5472
5473   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5474
5475   return 0;
5476 }
5477
5478 //==============================================================================
5479 //function : VConvert
5480 //purpose  :
5481 //==============================================================================
5482
5483 static int VConvert (Draw_Interpretor& theDI,
5484                      Standard_Integer  theArgNb,
5485                      const char**      theArgVec)
5486 {
5487   // get the active view
5488   Handle(V3d_View) aView = ViewerTest::CurrentView();
5489   if (aView.IsNull())
5490   {
5491     std::cerr << "Error: no active view. Please call vinit.\n";
5492     return 1;
5493   }
5494
5495   enum { Model, Ray, View, Window, Grid } aMode = Model;
5496
5497   // access coordinate arguments
5498   TColStd_SequenceOfReal aCoord;
5499   Standard_Integer anArgIdx = 1;
5500   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5501   {
5502     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5503     if (!anArg.IsRealValue())
5504     {
5505       break;
5506     }
5507     aCoord.Append (anArg.RealValue());
5508   }
5509
5510   // non-numeric argument too early
5511   if (aCoord.IsEmpty())
5512   {
5513     std::cerr << "Error: wrong number of arguments! See usage:\n";
5514     theDI.PrintHelp (theArgVec[0]);
5515     return 1;
5516   }
5517
5518   // collect all other arguments and options
5519   for (; anArgIdx < theArgNb; ++anArgIdx)
5520   {
5521     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5522     anArg.LowerCase();
5523     if      (anArg == "window") aMode = Window;
5524     else if (anArg == "view")   aMode = View;
5525     else if (anArg == "grid")   aMode = Grid;
5526     else if (anArg == "ray")    aMode = Ray;
5527     else
5528     {
5529       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5530       theDI.PrintHelp (theArgVec[0]);
5531       return 1;
5532     }
5533   }
5534
5535   // complete input checks
5536   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5537       (aCoord.Length() == 2 && theArgNb > 4) ||
5538       (aCoord.Length() == 3 && theArgNb > 5))
5539   {
5540     std::cerr << "Error: wrong number of arguments! See usage:\n";
5541     theDI.PrintHelp (theArgVec[0]);
5542     return 1;
5543   }
5544
5545   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5546   Standard_Integer aXYp[2] = {0, 0};
5547
5548   // convert one-dimensional coordinate
5549   if (aCoord.Length() == 1)
5550   {
5551     switch (aMode)
5552     {
5553       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5554       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5555       default:
5556         std::cerr << "Error: wrong arguments! See usage:\n";
5557         theDI.PrintHelp (theArgVec[0]);
5558         return 1;
5559     }
5560   }
5561
5562   // convert 2D coordinates from projection or view reference space
5563   if (aCoord.Length() == 2)
5564   {
5565     switch (aMode)
5566     {
5567       case Model :
5568         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5569         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5570         return 0;
5571
5572       case View :
5573         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5574         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5575         return 0;
5576
5577       case Window :
5578         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5579         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5580         return 0;
5581
5582       case Grid :
5583         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5584         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5585         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5586         return 0;
5587
5588       case Ray :
5589         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5590                                 (Standard_Integer) aCoord (2),
5591                                 aXYZ[0], aXYZ[1], aXYZ[2],
5592                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5593         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5594         return 0;
5595
5596       default:
5597         std::cerr << "Error: wrong arguments! See usage:\n";
5598         theDI.PrintHelp (theArgVec[0]);
5599         return 1;
5600     }
5601   }
5602
5603   // convert 3D coordinates from view reference space
5604   else if (aCoord.Length() == 3)
5605   {
5606     switch (aMode)
5607     {
5608       case Window :
5609         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5610         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5611         return 0;
5612
5613       case Grid :
5614         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5615         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5616         return 0;
5617
5618       default:
5619         std::cerr << "Error: wrong arguments! See usage:\n";
5620         theDI.PrintHelp (theArgVec[0]);
5621         return 1;
5622     }
5623   }
5624
5625   return 0;
5626 }
5627
5628 //==============================================================================
5629 //function : VFps
5630 //purpose  :
5631 //==============================================================================
5632
5633 static int VFps (Draw_Interpretor& theDI,
5634                  Standard_Integer  theArgNb,
5635                  const char**      theArgVec)
5636 {
5637   // get the active view
5638   Handle(V3d_View) aView = ViewerTest::CurrentView();
5639   if (aView.IsNull())
5640   {
5641     std::cerr << "No active view. Please call vinit.\n";
5642     return 1;
5643   }
5644
5645   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5646   if (aFramesNb <= 0)
5647   {
5648     std::cerr << "Incorrect arguments!\n";
5649     return 1;
5650   }
5651
5652   // the time is meaningless for first call
5653   // due to async OpenGl rendering
5654   aView->Redraw();
5655
5656   // redraw view in loop to estimate average values
5657   OSD_Timer aTimer;
5658   aTimer.Start();
5659   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5660   {
5661     aView->Redraw();
5662   }
5663   aTimer.Stop();
5664   Standard_Real aCpu;
5665   const Standard_Real aTime = aTimer.ElapsedTime();
5666   aTimer.OSD_Chronometer::Show (aCpu);
5667
5668   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5669   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5670
5671   // return statistics
5672   theDI << "FPS: " << aFpsAver << "\n"
5673         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5674
5675   // compute additional statistics in ray-tracing mode
5676   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5677
5678   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5679   {
5680     Standard_Integer aSizeX;
5681     Standard_Integer aSizeY;
5682
5683     aView->Window()->Size (aSizeX, aSizeY);
5684
5685     // 1 shadow ray and 1 secondary ray pew each bounce
5686     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5687
5688     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5689   }
5690
5691   return 0;
5692 }
5693
5694 //==============================================================================
5695 //function : VGlDebug
5696 //purpose  :
5697 //==============================================================================
5698
5699 static int VGlDebug (Draw_Interpretor& theDI,
5700                      Standard_Integer  theArgNb,
5701                      const char**      theArgVec)
5702 {
5703   Handle(OpenGl_GraphicDriver) aDriver;
5704   Handle(V3d_View) aView = ViewerTest::CurrentView();
5705   if (!aView.IsNull())
5706   {
5707     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5708   }
5709   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5710   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5711
5712   if (theArgNb < 2)
5713   {
5714     TCollection_AsciiString aDebActive, aSyncActive;
5715     if (aCaps == NULL)
5716     {
5717       aCaps = aDefCaps;
5718     }
5719     else
5720     {
5721       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5722                                                                   "GL_ARB_debug_output");
5723       aDebActive = isActive ? " (active)" : " (inactive)";
5724       if (isActive)
5725       {
5726         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5727         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5728       }
5729     }
5730
5731     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5732           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5733           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5734           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5735     return 0;
5736   }
5737
5738   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5739   {
5740     Standard_CString        anArg     = theArgVec[anArgIter];
5741     TCollection_AsciiString anArgCase (anArg);
5742     anArgCase.LowerCase();
5743     Standard_Boolean toEnableDebug = Standard_True;
5744     if (anArgCase == "-glsl"
5745      || anArgCase == "-glslwarn"
5746      || anArgCase == "-glslwarns"
5747      || anArgCase == "-glslwarnings")
5748     {
5749       Standard_Boolean toShowWarns = Standard_True;
5750       if (++anArgIter < theArgNb
5751       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5752       {
5753         --anArgIter;
5754       }
5755       aDefCaps->glslWarnings = toShowWarns;
5756       if (aCaps != NULL)
5757       {
5758         aCaps->glslWarnings = toShowWarns;
5759       }
5760     }
5761     else if (anArgCase == "-extra"
5762           || anArgCase == "-extramsg"
5763           || anArgCase == "-extramessages")
5764     {
5765       Standard_Boolean toShow = Standard_True;
5766       if (++anArgIter < theArgNb
5767       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5768       {
5769         --anArgIter;
5770       }
5771       aDefCaps->suppressExtraMsg = !toShow;
5772       if (aCaps != NULL)
5773       {
5774         aCaps->suppressExtraMsg = !toShow;
5775       }
5776     }
5777     else if (anArgCase == "-noextra"
5778           || anArgCase == "-noextramsg"
5779           || anArgCase == "-noextramessages")
5780     {
5781       Standard_Boolean toSuppress = Standard_True;
5782       if (++anArgIter < theArgNb
5783       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5784       {
5785         --anArgIter;
5786       }
5787       aDefCaps->suppressExtraMsg = toSuppress;
5788       if (aCaps != NULL)
5789       {
5790         aCaps->suppressExtraMsg = toSuppress;
5791       }
5792     }
5793     else if (anArgCase == "-sync")
5794     {
5795       Standard_Boolean toSync = Standard_True;
5796       if (++anArgIter < theArgNb
5797       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5798       {
5799         --anArgIter;
5800       }
5801       aDefCaps->contextSyncDebug = toSync;
5802       if (toSync)
5803       {
5804         aDefCaps->contextDebug = Standard_True;
5805       }
5806     }
5807     else if (anArgCase == "-debug")
5808     {
5809       if (++anArgIter < theArgNb
5810       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5811       {
5812         --anArgIter;
5813       }
5814       aDefCaps->contextDebug = toEnableDebug;
5815     }
5816     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5817           && (anArgIter + 1 == theArgNb))
5818     {
5819       // simple alias to turn on almost everything
5820       aDefCaps->contextDebug     = toEnableDebug;
5821       aDefCaps->contextSyncDebug = toEnableDebug;
5822       aDefCaps->glslWarnings     = toEnableDebug;
5823     }
5824     else
5825     {
5826       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5827       return 1;
5828     }
5829   }
5830
5831   return 0;
5832 }
5833
5834 //==============================================================================
5835 //function : VVbo
5836 //purpose  :
5837 //==============================================================================
5838
5839 static int VVbo (Draw_Interpretor& theDI,
5840                  Standard_Integer  theArgNb,
5841                  const char**      theArgVec)
5842 {
5843   const Standard_Boolean toSet    = (theArgNb > 1);
5844   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5845   if (toSet)
5846   {
5847     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5848   }
5849
5850   // get the context
5851   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5852   if (aContextAIS.IsNull())
5853   {
5854     if (!toSet)
5855     {
5856       std::cerr << "No active view!\n";
5857     }
5858     return 1;
5859   }
5860   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5861   if (!aDriver.IsNull())
5862   {
5863     if (!toSet)
5864     {
5865       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5866     }
5867     else
5868     {
5869       aDriver->ChangeOptions().vboDisable = toUseVbo;
5870     }
5871   }
5872
5873   return 0;
5874 }
5875
5876 //==============================================================================
5877 //function : VCaps
5878 //purpose  :
5879 //==============================================================================
5880
5881 static int VCaps (Draw_Interpretor& theDI,
5882                   Standard_Integer  theArgNb,
5883                   const char**      theArgVec)
5884 {
5885   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5886   Handle(OpenGl_GraphicDriver)   aDriver;
5887   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5888   if (!aContext.IsNull())
5889   {
5890     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5891     aCaps   = &aDriver->ChangeOptions();
5892   }
5893
5894   if (theArgNb < 2)
5895   {
5896     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5897     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5898     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5899     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5900     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5901     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5902     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5903     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5904     return 0;
5905   }
5906
5907   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5908   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5909   {
5910     Standard_CString        anArg     = theArgVec[anArgIter];
5911     TCollection_AsciiString anArgCase (anArg);
5912     anArgCase.LowerCase();
5913     if (anUpdateTool.parseRedrawMode (anArg))
5914     {
5915       continue;
5916     }
5917     else if (anArgCase == "-vsync"
5918           || anArgCase == "-swapinterval")
5919     {
5920       Standard_Boolean toEnable = Standard_True;
5921       if (++anArgIter < theArgNb
5922       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5923       {
5924         --anArgIter;
5925       }
5926       aCaps->swapInterval = toEnable;
5927     }
5928     else if (anArgCase == "-ffp")
5929     {
5930       Standard_Boolean toEnable = Standard_True;
5931       if (++anArgIter < theArgNb
5932       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5933       {
5934         --anArgIter;
5935       }
5936       aCaps->ffpEnable = toEnable;
5937     }
5938     else if (anArgCase == "-vbo")
5939     {
5940       Standard_Boolean toEnable = Standard_True;
5941       if (++anArgIter < theArgNb
5942       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5943       {
5944         --anArgIter;
5945       }
5946       aCaps->vboDisable = !toEnable;
5947     }
5948     else if (anArgCase == "-sprite"
5949           || anArgCase == "-sprites")
5950     {
5951       Standard_Boolean toEnable = Standard_True;
5952       if (++anArgIter < theArgNb
5953       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5954       {
5955         --anArgIter;
5956       }
5957       aCaps->pntSpritesDisable = !toEnable;
5958     }
5959     else if (anArgCase == "-softmode")
5960     {
5961       Standard_Boolean toEnable = Standard_True;
5962       if (++anArgIter < theArgNb
5963       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5964       {
5965         --anArgIter;
5966       }
5967       aCaps->contextNoAccel = toEnable;
5968     }
5969     else if (anArgCase == "-winbuffer"
5970           || anArgCase == "-windowbuffer"
5971           || anArgCase == "-usewinbuffer"
5972           || anArgCase == "-usewindowbuffer"
5973           || anArgCase == "-usesystembuffer")
5974     {
5975       Standard_Boolean toEnable = Standard_True;
5976       if (++anArgIter < theArgNb
5977       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5978       {
5979         --anArgIter;
5980       }
5981       aCaps->useSystemBuffer = toEnable;
5982     }
5983     else if (anArgCase == "-accel"
5984           || anArgCase == "-acceleration")
5985     {
5986       Standard_Boolean toEnable = Standard_True;
5987       if (++anArgIter < theArgNb
5988       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5989       {
5990         --anArgIter;
5991       }
5992       aCaps->contextNoAccel = !toEnable;
5993     }
5994     else if (anArgCase == "-compat"
5995           || anArgCase == "-compatprofile"
5996           || anArgCase == "-compatible"
5997           || anArgCase == "-compatibleprofile")
5998     {
5999       Standard_Boolean toEnable = Standard_True;
6000       if (++anArgIter < theArgNb
6001       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6002       {
6003         --anArgIter;
6004       }
6005       aCaps->contextCompatible = toEnable;
6006       if (!aCaps->contextCompatible)
6007       {
6008         aCaps->ffpEnable = Standard_False;
6009       }
6010     }
6011     else if (anArgCase == "-core"
6012           || anArgCase == "-coreprofile")
6013     {
6014       Standard_Boolean toEnable = Standard_True;
6015       if (++anArgIter < theArgNb
6016       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6017       {
6018         --anArgIter;
6019       }
6020       aCaps->contextCompatible = !toEnable;
6021       if (!aCaps->contextCompatible)
6022       {
6023         aCaps->ffpEnable = Standard_False;
6024       }
6025     }
6026     else if (anArgCase == "-stereo"
6027           || anArgCase == "-quadbuffer")
6028     {
6029       Standard_Boolean toEnable = Standard_True;
6030       if (++anArgIter < theArgNb
6031       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6032       {
6033         --anArgIter;
6034       }
6035       aCaps->contextStereo = toEnable;
6036     }
6037     else
6038     {
6039       std::cout << "Error: unknown argument '" << anArg << "'\n";
6040       return 1;
6041     }
6042   }
6043   if (aCaps != &ViewerTest_myDefaultCaps)
6044   {
6045     ViewerTest_myDefaultCaps = *aCaps;
6046   }
6047   return 0;
6048 }
6049
6050 //==============================================================================
6051 //function : VMemGpu
6052 //purpose  :
6053 //==============================================================================
6054
6055 static int VMemGpu (Draw_Interpretor& theDI,
6056                     Standard_Integer  theArgNb,
6057                     const char**      theArgVec)
6058 {
6059   // get the context
6060   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6061   if (aContextAIS.IsNull())
6062   {
6063     std::cerr << "No active view. Please call vinit.\n";
6064     return 1;
6065   }
6066
6067   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
6068   if (aDriver.IsNull())
6069   {
6070     std::cerr << "Graphic driver not available.\n";
6071     return 1;
6072   }
6073
6074   Standard_Size aFreeBytes = 0;
6075   TCollection_AsciiString anInfo;
6076   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
6077   {
6078     std::cerr << "Information not available.\n";
6079     return 1;
6080   }
6081
6082   if (theArgNb > 1 && *theArgVec[1] == 'f')
6083   {
6084     theDI << Standard_Real (aFreeBytes);
6085   }
6086   else
6087   {
6088     theDI << anInfo;
6089   }
6090
6091   return 0;
6092 }
6093
6094 // ==============================================================================
6095 // function : VReadPixel
6096 // purpose  :
6097 // ==============================================================================
6098 static int VReadPixel (Draw_Interpretor& theDI,
6099                        Standard_Integer  theArgNb,
6100                        const char**      theArgVec)
6101 {
6102   // get the active view
6103   Handle(V3d_View) aView = ViewerTest::CurrentView();
6104   if (aView.IsNull())
6105   {
6106     std::cerr << "No active view. Please call vinit.\n";
6107     return 1;
6108   }
6109   else if (theArgNb < 3)
6110   {
6111     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
6112     return 1;
6113   }
6114
6115   Image_Format         aFormat     = Image_Format_RGBA;
6116   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
6117
6118   Standard_Integer aWidth, aHeight;
6119   aView->Window()->Size (aWidth, aHeight);
6120   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
6121   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
6122   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
6123   {
6124     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
6125     return 1;
6126   }
6127
6128   Standard_Boolean toShowName = Standard_False;
6129   Standard_Boolean toShowHls  = Standard_False;
6130   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6131   {
6132     TCollection_AsciiString aParam (theArgVec[anIter]);
6133     aParam.LowerCase();
6134     if (aParam == "rgb")
6135     {
6136       aFormat     = Image_Format_RGB;
6137       aBufferType = Graphic3d_BT_RGB;
6138     }
6139     else if (aParam == "hls")
6140     {
6141       aFormat     = Image_Format_RGB;
6142       aBufferType = Graphic3d_BT_RGB;
6143       toShowHls   = Standard_True;
6144     }
6145     else if (aParam == "rgbf")
6146     {
6147       aFormat     = Image_Format_RGBF;
6148       aBufferType = Graphic3d_BT_RGB;
6149     }
6150     else if (aParam == "rgba")
6151     {
6152       aFormat     = Image_Format_RGBA;
6153       aBufferType = Graphic3d_BT_RGBA;
6154     }
6155     else if (aParam == "rgbaf")
6156     {
6157       aFormat     = Image_Format_RGBAF;
6158       aBufferType = Graphic3d_BT_RGBA;
6159     }
6160     else if (aParam == "depth")
6161     {
6162       aFormat     = Image_Format_GrayF;
6163       aBufferType = Graphic3d_BT_Depth;
6164     }
6165     else if (aParam == "name")
6166     {
6167       toShowName = Standard_True;
6168     }
6169   }
6170
6171   Image_PixMap anImage;
6172   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6173   {
6174     std::cerr << "Image allocation failed\n";
6175     return 1;
6176   }
6177   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6178   {
6179     std::cerr << "Image dump failed\n";
6180     return 1;
6181   }
6182
6183   // redirect possible warning messages that could have been added by ToPixMap
6184   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6185   // contaminate result of the command
6186   Standard_CString aWarnLog = theDI.Result();
6187   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6188   {
6189     std::cout << aWarnLog << std::endl;
6190   }
6191   theDI.Reset();
6192
6193   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6194   if (toShowName)
6195   {
6196     if (aBufferType == Graphic3d_BT_RGBA)
6197     {
6198       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6199     }
6200     else
6201     {
6202       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6203     }
6204   }
6205   else
6206   {
6207     switch (aBufferType)
6208     {
6209       default:
6210       case Graphic3d_BT_RGB:
6211       {
6212         if (toShowHls)
6213         {
6214           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6215         }
6216         else
6217         {
6218           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6219         }
6220         break;
6221       }
6222       case Graphic3d_BT_RGBA:
6223       {
6224         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6225         break;
6226       }
6227       case Graphic3d_BT_Depth:
6228       {
6229         theDI << aColor.GetRGB().Red();
6230         break;
6231       }
6232     }
6233   }
6234
6235   return 0;
6236 }
6237
6238 //! Auxiliary presentation for an image plane.
6239 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6240 {
6241 public:
6242   //! Main constructor.
6243   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6244                        const Standard_Real theWidth,
6245                        const Standard_Real theHeight,
6246                        const TCollection_AsciiString& theLabel)
6247   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6248   {
6249     SetDisplayMode (0);
6250     SetHilightMode (1);
6251     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6252     {
6253       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6254       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6255       Graphic3d_MaterialAspect aMat;
6256       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6257       aMat.SetAmbient  (1.0);
6258       aMat.SetDiffuse  (1.0);
6259       aMat.SetSpecular (1.0);
6260       aMat.SetEmissive (1.0);
6261       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6262       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6263       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6264       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6265       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6266       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6267       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6268       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6269       aFillAspect->SetFrontMaterial (aMat);
6270       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6271       aFillAspect->SetTextureMapOn();
6272     }
6273     {
6274       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6275       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6276       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6277       myDrawer->SetTextAspect (aTextAspect);
6278     }
6279     {
6280       const gp_Dir aNorm (0.0, 0.0, 1.0);
6281       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6282       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6283       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6284       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6285       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6286       myTris->AddEdge (1);
6287       myTris->AddEdge (2);
6288       myTris->AddEdge (3);
6289       myTris->AddEdge (3);
6290       myTris->AddEdge (2);
6291       myTris->AddEdge (4);
6292
6293       myRect = new Graphic3d_ArrayOfPolylines (4);
6294       myRect->AddVertex (myTris->Vertice (1));
6295       myRect->AddVertex (myTris->Vertice (3));
6296       myRect->AddVertex (myTris->Vertice (4));
6297       myRect->AddVertex (myTris->Vertice (2));
6298     }
6299   }
6300
6301   //! Returns TRUE for accepted display modes.
6302   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6303
6304   //! Compute presentation.
6305   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6306   {
6307     switch (theMode)
6308     {
6309       case 0:
6310       {
6311         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6312         aGroup->AddPrimitiveArray (myTris);
6313         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6314         aGroup->AddPrimitiveArray (myRect);
6315         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6316         return;
6317       }
6318       case 1:
6319       {
6320         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6321         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6322         aGroup->AddPrimitiveArray (myRect);
6323         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6324         return;
6325       }
6326     }
6327   }
6328
6329   //! Compute selection.
6330   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6331   {
6332     if (theMode == 0)
6333     {
6334       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6335       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6336       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6337       theSel->Add (aSensitive);
6338     }
6339   }
6340
6341 private:
6342   Handle(Graphic3d_ArrayOfTriangles) myTris;
6343   Handle(Graphic3d_ArrayOfPolylines) myRect;
6344   TCollection_AsciiString myLabel;
6345   Standard_Real myWidth;
6346   Standard_Real myHeight;
6347 };
6348
6349 //==============================================================================
6350 //function : VDiffImage
6351 //purpose  : The draw-command compares two images.
6352 //==============================================================================
6353
6354 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6355 {
6356   if (theArgNb < 3)
6357   {
6358     std::cout << "Syntax error: not enough arguments.\n";
6359     return 1;
6360   }
6361
6362   Standard_Integer anArgIter = 1;
6363   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6364   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6365   TCollection_AsciiString aDiffImagePath;
6366   Standard_Real    aTolColor        = -1.0;
6367   Standard_Integer toBlackWhite     = -1;
6368   Standard_Integer isBorderFilterOn = -1;
6369   Standard_Boolean isOldSyntax = Standard_False;
6370   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6371   for (; anArgIter < theArgNb; ++anArgIter)
6372   {
6373     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6374     anArg.LowerCase();
6375     if (anArgIter + 1 < theArgNb
6376      && (anArg == "-toleranceofcolor"
6377       || anArg == "-tolerancecolor"
6378       || anArg == "-tolerance"
6379       || anArg == "-toler"))
6380     {
6381       aTolColor = Atof (theArgVec[++anArgIter]);
6382       if (aTolColor < 0.0 || aTolColor > 1.0)
6383       {
6384         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6385         return 1;
6386       }
6387     }
6388     else if (anArg == "-blackwhite")
6389     {
6390       Standard_Boolean toEnable = Standard_True;
6391       if (anArgIter + 1 < theArgNb
6392        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6393       {
6394         ++anArgIter;
6395       }
6396       toBlackWhite = toEnable ? 1 : 0;
6397     }
6398     else if (anArg == "-borderfilter")
6399     {
6400       Standard_Boolean toEnable = Standard_True;
6401       if (anArgIter + 1 < theArgNb
6402        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6403       {
6404         ++anArgIter;
6405       }
6406       isBorderFilterOn = toEnable ? 1 : 0;
6407     }
6408     else if (anArg == "-exitonclose")
6409     {
6410       Draw_ToExitOnCloseView = true;
6411       if (anArgIter + 1 < theArgNb
6412        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6413       {
6414         ++anArgIter;
6415       }
6416     }
6417     else if (anArg == "-closeonescape"
6418           || anArg == "-closeonesc")
6419     {
6420       Draw_ToCloseViewOnEsc = true;
6421       if (anArgIter + 1 < theArgNb
6422        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6423       {
6424         ++anArgIter;
6425       }
6426     }
6427     else if (anArgIter + 3 < theArgNb
6428           && anArg == "-display")
6429     {
6430       aViewName   = theArgVec[++anArgIter];
6431       aPrsNameRef = theArgVec[++anArgIter];
6432       aPrsNameNew = theArgVec[++anArgIter];
6433       if (anArgIter + 1 < theArgNb
6434       && *theArgVec[anArgIter + 1] != '-')
6435       {
6436         aPrsNameDiff = theArgVec[++anArgIter];
6437       }
6438     }
6439     else if (aTolColor < 0.0
6440           && anArg.IsRealValue())
6441     {
6442       isOldSyntax = Standard_True;
6443       aTolColor = anArg.RealValue();
6444       if (aTolColor < 0.0 || aTolColor > 1.0)
6445       {
6446         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6447         return 1;
6448       }
6449     }
6450     else if (isOldSyntax
6451           && toBlackWhite == -1
6452           && (anArg == "0" || anArg == "1"))
6453     {
6454       toBlackWhite = anArg == "1" ? 1 : 0;
6455     }
6456     else if (isOldSyntax
6457           && isBorderFilterOn == -1
6458           && (anArg == "0" || anArg == "1"))
6459     {
6460       isBorderFilterOn = anArg == "1" ? 1 : 0;
6461     }
6462     else if (aDiffImagePath.IsEmpty())
6463     {
6464       aDiffImagePath = theArgVec[anArgIter];
6465     }
6466     else
6467     {
6468       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6469       return 1;
6470     }
6471   }
6472
6473   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6474   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6475   if (!anImgRef->Load (anImgPathRef))
6476   {
6477     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6478     return 1;
6479   }
6480   if (!anImgNew->Load (anImgPathNew))
6481   {
6482     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6483     return 1;
6484   }
6485
6486   // compare the images
6487   Image_Diff aComparer;
6488   Standard_Integer aDiffColorsNb = -1;
6489   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6490   {
6491     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6492     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6493     aDiffColorsNb = aComparer.Compare();
6494     theDI << aDiffColorsNb << "\n";
6495   }
6496
6497   // save image of difference
6498   Handle(Image_AlienPixMap) aDiff;
6499   if (aDiffColorsNb > 0
6500   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6501   {
6502     aDiff = new Image_AlienPixMap();
6503     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6504     {
6505       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6506       return 1;
6507     }
6508     aComparer.SaveDiffImage (*aDiff);
6509     if (!aDiffImagePath.IsEmpty()
6510      && !aDiff->Save (aDiffImagePath))
6511     {
6512       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6513       return 1;
6514     }
6515   }
6516
6517   if (aViewName.IsEmpty())
6518   {
6519     return 0;
6520   }
6521
6522   ViewerTest_Names aViewNames (aViewName);
6523   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6524   {
6525     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6526     theDI.Eval (aCommand.ToCString());
6527   }
6528
6529   Standard_Integer aPxLeft = 0;
6530   Standard_Integer aPxTop  = 0;
6531   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6532   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6533                               ? int(anImgRef->SizeY() * 2)
6534                               : int(anImgRef->SizeY());
6535   TCollection_AsciiString aDisplayName;
6536   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
6537                                                             aViewName, aDisplayName);
6538
6539   Standard_Real aRatio = anImgRef->Ratio();
6540   Standard_Real aSizeX = 1.0;
6541   Standard_Real aSizeY = aSizeX / aRatio;
6542   {
6543     OSD_Path aPath (anImgPathRef);
6544     TCollection_AsciiString aLabelRef;
6545     if (!aPath.Name().IsEmpty())
6546     {
6547       aLabelRef = aPath.Name() + aPath.Extension();
6548     }
6549     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6550
6551     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6552     gp_Trsf aTrsfRef;
6553     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6554     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6555     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6556   }
6557   {
6558     OSD_Path aPath (anImgPathNew);
6559     TCollection_AsciiString aLabelNew;
6560     if (!aPath.Name().IsEmpty())
6561     {
6562       aLabelNew = aPath.Name() + aPath.Extension();
6563     }
6564     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6565
6566     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6567     gp_Trsf aTrsfRef;
6568     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6569     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6570     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6571   }
6572   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6573   if (!aDiff.IsNull())
6574   {
6575     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6576     gp_Trsf aTrsfDiff;
6577     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6578     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6579   }
6580   if (!aPrsNameDiff.IsEmpty())
6581   {
6582     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6583   }
6584   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6585   ViewerTest::CurrentView()->FitAll();
6586   return 0;
6587 }
6588
6589 //=======================================================================
6590 //function : VSelect
6591 //purpose  : Emulates different types of selection by mouse:
6592 //           1) single click selection
6593 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6594 //           3) selection with polygon having corners at
6595 //           pixel positions (x1,y1),...,(xn,yn)
6596 //           4) any of these selections with shift button pressed
6597 //=======================================================================
6598 static Standard_Integer VSelect (Draw_Interpretor& di,
6599                                  Standard_Integer argc,
6600                                  const char ** argv)
6601 {
6602   if(argc < 3)
6603   {
6604     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6605     return 1;
6606   }
6607
6608   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6609   if(myAIScontext.IsNull())
6610   {
6611     di << "use 'vinit' command before " << argv[0] << "\n";
6612     return 1;
6613   }
6614
6615   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6616   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6617   TCollection_AsciiString anArg;
6618   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6619   anArg.LowerCase();
6620   if (anArg == "-allowoverlap")
6621   {
6622     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6623       : argc == 7;
6624     if (!isValidated)
6625     {
6626       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6627       return 1;
6628     }
6629
6630     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6631     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6632     aCoordsNb -= 2;
6633   }
6634
6635   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6636   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6637   if(aCoordsNb == 2)
6638   {
6639     if(isShiftSelection)
6640       aCurrentEventManager->ShiftSelect();
6641     else
6642       aCurrentEventManager->Select();
6643   }
6644   else if(aCoordsNb == 4)
6645   {
6646     if(isShiftSelection)
6647       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6648     else
6649       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6650   }
6651   else
6652   {
6653     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6654
6655     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6656       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6657
6658     if(isShiftSelection)
6659       aCurrentEventManager->ShiftSelect(aPolyline);
6660     else
6661       aCurrentEventManager->Select(aPolyline);
6662   }
6663   return 0;
6664 }
6665
6666 //=======================================================================
6667 //function : VMoveTo
6668 //purpose  : Emulates cursor movement to defined pixel position
6669 //=======================================================================
6670 static Standard_Integer VMoveTo (Draw_Interpretor& di,
6671                                 Standard_Integer argc,
6672                                 const char ** argv)
6673 {
6674   if(argc != 3)
6675   {
6676     di << "Usage : " << argv[0] << " x y\n";
6677     return 1;
6678   }
6679
6680   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6681   if(aContext.IsNull())
6682   {
6683     di << "use 'vinit' command before " << argv[0] << "\n";
6684     return 1;
6685   }
6686   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6687   return 0;
6688 }
6689
6690 namespace
6691 {
6692   //! Global map storing all animations registered in ViewerTest.
6693   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6694
6695   //! The animation calling the Draw Harness command.
6696   class ViewerTest_AnimationProc : public AIS_Animation
6697   {
6698   public:
6699
6700     //! Main constructor.
6701     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6702                               Draw_Interpretor* theDI,
6703                               const TCollection_AsciiString& theCommand)
6704     : AIS_Animation (theAnimationName),
6705       myDrawInter(theDI),
6706       myCommand  (theCommand)
6707     {
6708       //
6709     }
6710
6711   protected:
6712
6713     //! Evaluate the command.
6714     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6715     {
6716       TCollection_AsciiString aCmd = myCommand;
6717       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6718       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6719       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6720       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6721       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6722       myDrawInter->Eval (aCmd.ToCString());
6723     }
6724
6725     //! Find the keyword in the command and replace it with value.
6726     //! @return the position of the keyword to pass value
6727     void replace (TCollection_AsciiString&       theCmd,
6728                   const TCollection_AsciiString& theKey,
6729                   const TCollection_AsciiString& theVal)
6730     {
6731       TCollection_AsciiString aCmd (theCmd);
6732       aCmd.LowerCase();
6733       const Standard_Integer aPos = aCmd.Search (theKey);
6734       if (aPos == -1)
6735       {
6736         return;
6737       }
6738
6739       TCollection_AsciiString aPart1, aPart2;
6740       Standard_Integer aPart1To = aPos - 1;
6741       if (aPart1To >= 1
6742        && aPart1To <= theCmd.Length())
6743       {
6744         aPart1 = theCmd.SubString (1, aPart1To);
6745       }
6746
6747       Standard_Integer aPart2From = aPos + theKey.Length();
6748       if (aPart2From >= 1
6749        && aPart2From <= theCmd.Length())
6750       {
6751         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6752       }
6753
6754       theCmd = aPart1 + theVal + aPart2;
6755     }
6756
6757   protected:
6758
6759     Draw_Interpretor*       myDrawInter;
6760     TCollection_AsciiString myCommand;
6761
6762   };
6763
6764   //! Replace the animation with the new one.
6765   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6766                                 Handle(AIS_Animation)&       theAnimation,
6767                                 const Handle(AIS_Animation)& theAnimationNew)
6768   {
6769     theAnimationNew->CopyFrom (theAnimation);
6770     if (!theParentAnimation.IsNull())
6771     {
6772       theParentAnimation->Replace (theAnimation, theAnimationNew);
6773     }
6774     else
6775     {
6776       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6777       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6778     }
6779     theAnimation = theAnimationNew;
6780   }
6781
6782   //! Parse the point.
6783   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6784   {
6785     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6786     if (!anXYZ[0].IsRealValue()
6787      || !anXYZ[1].IsRealValue()
6788      || !anXYZ[2].IsRealValue())
6789     {
6790       return Standard_False;
6791     }
6792
6793     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6794     return Standard_True;
6795   }
6796
6797   //! Parse the quaternion.
6798   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6799   {
6800     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6801     if (!anXYZW[0].IsRealValue()
6802      || !anXYZW[1].IsRealValue()
6803      || !anXYZW[2].IsRealValue()
6804      || !anXYZW[3].IsRealValue())
6805     {
6806       return Standard_False;
6807     }
6808
6809     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6810     return Standard_True;
6811   }
6812
6813   //! Auxiliary class for flipping image upside-down.
6814   class ImageFlipper
6815   {
6816   public:
6817
6818     //! Empty constructor.
6819     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6820
6821     //! Perform flipping.
6822     Standard_Boolean FlipY (Image_PixMap& theImage)
6823     {
6824       if (theImage.IsEmpty()
6825        || theImage.SizeX() == 0
6826        || theImage.SizeY() == 0)
6827       {
6828         return Standard_False;
6829       }
6830
6831       const Standard_Size aRowSize = theImage.SizeRowBytes();
6832       if (myTmp.Size() < aRowSize
6833       && !myTmp.Allocate (aRowSize))
6834       {
6835         return Standard_False;
6836       }
6837
6838       // for odd height middle row should be left as is
6839       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6840       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6841       {
6842         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6843         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6844         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
6845         memcpy (aTop,               aBot,         aRowSize);
6846         memcpy (aBot,               myTmp.Data(), aRowSize);
6847       }
6848       return Standard_True;
6849     }
6850
6851   private:
6852     NCollection_Buffer myTmp;
6853   };
6854
6855 }
6856
6857 //=================================================================================================
6858 //function : VViewParams
6859 //purpose  : Gets or sets AIS View characteristics
6860 //=================================================================================================
6861 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6862 {
6863   Handle(V3d_View) aView = ViewerTest::CurrentView();
6864   if (aView.IsNull())
6865   {
6866     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6867     return 1;
6868   }
6869
6870   Standard_Boolean toSetProj     = Standard_False;
6871   Standard_Boolean toSetUp       = Standard_False;
6872   Standard_Boolean toSetAt       = Standard_False;
6873   Standard_Boolean toSetEye      = Standard_False;
6874   Standard_Boolean toSetScale    = Standard_False;
6875   Standard_Boolean toSetSize     = Standard_False;
6876   Standard_Boolean toSetCenter2d = Standard_False;
6877   Standard_Real    aViewScale = aView->Scale();
6878   Standard_Real    aViewSize  = 1.0;
6879   Graphic3d_Vec2i  aCenter2d;
6880   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6881   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6882   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6883   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6884   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6885   if (theArgsNb == 1)
6886   {
6887     // print all of the available view parameters
6888     char aText[4096];
6889     Sprintf (aText,
6890              "Scale: %g\n"
6891              "Proj:  %12g %12g %12g\n"
6892              "Up:    %12g %12g %12g\n"
6893              "At:    %12g %12g %12g\n"
6894              "Eye:   %12g %12g %12g\n",
6895               aViewScale,
6896               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6897               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6898               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6899               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6900     theDi << aText;
6901     return 0;
6902   }
6903
6904   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6905   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6906   {
6907     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6908     anArg.LowerCase();
6909     if (anUpdateTool.parseRedrawMode (anArg))
6910     {
6911       continue;
6912     }
6913     else if (anArg == "-cmd"
6914           || anArg == "-command"
6915           || anArg == "-args")
6916     {
6917       char aText[4096];
6918       Sprintf (aText,
6919                "-scale %g "
6920                "-proj %g %g %g "
6921                "-up %g %g %g "
6922                "-at %g %g %g\n",
6923                 aViewScale,
6924                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6925                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6926                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6927       theDi << aText;
6928     }
6929     else if (anArg == "-scale"
6930           || anArg == "-size")
6931     {
6932       if (anArgIter + 1 < theArgsNb
6933        && *theArgVec[anArgIter + 1] != '-')
6934       {
6935         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6936         if (aValueArg.IsRealValue())
6937         {
6938           ++anArgIter;
6939           if (anArg == "-scale")
6940           {
6941             toSetScale = Standard_True;
6942             aViewScale = aValueArg.RealValue();
6943           }
6944           else if (anArg == "-size")
6945           {
6946             toSetSize = Standard_True;
6947             aViewSize = aValueArg.RealValue();
6948           }
6949           continue;
6950         }
6951       }
6952       if (anArg == "-scale")
6953       {
6954         theDi << "Scale: " << aView->Scale() << "\n";
6955       }
6956       else if (anArg == "-size")
6957       {
6958         Graphic3d_Vec2d aSizeXY;
6959         aView->Size (aSizeXY.x(), aSizeXY.y());
6960         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6961       }
6962     }
6963     else if (anArg == "-eye"
6964           || anArg == "-at"
6965           || anArg == "-up"
6966           || anArg == "-proj")
6967     {
6968       if (anArgIter + 3 < theArgsNb)
6969       {
6970         gp_XYZ anXYZ;
6971         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6972         {
6973           anArgIter += 3;
6974           if (anArg == "-eye")
6975           {
6976             toSetEye = Standard_True;
6977             aViewEye = anXYZ;
6978           }
6979           else if (anArg == "-at")
6980           {
6981             toSetAt = Standard_True;
6982             aViewAt = anXYZ;
6983           }
6984           else if (anArg == "-up")
6985           {
6986             toSetUp = Standard_True;
6987             aViewUp = anXYZ;
6988           }
6989           else if (anArg == "-proj")
6990           {
6991             toSetProj = Standard_True;
6992             aViewProj = anXYZ;
6993           }
6994           continue;
6995         }
6996       }
6997
6998       if (anArg == "-eye")
6999       {
7000         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
7001       }
7002       else if (anArg == "-at")
7003       {
7004         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
7005       }
7006       else if (anArg == "-up")
7007       {
7008         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
7009       }
7010       else if (anArg == "-proj")
7011       {
7012         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
7013       }
7014     }
7015     else if (anArg == "-center")
7016     {
7017       if (anArgIter + 2 < theArgsNb)
7018       {
7019         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
7020         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
7021         if (anX.IsIntegerValue()
7022          && anY.IsIntegerValue())
7023         {
7024           toSetCenter2d = Standard_True;
7025           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
7026         }
7027       }
7028     }
7029     else
7030     {
7031       std::cout << "Syntax error at '" << anArg << "'\n";
7032       return 1;
7033     }
7034   }
7035
7036   // change view parameters in proper order
7037   if (toSetScale)
7038   {
7039     aView->SetScale (aViewScale);
7040   }
7041   if (toSetSize)
7042   {
7043     aView->SetSize (aViewSize);
7044   }
7045   if (toSetEye)
7046   {
7047     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7048   }
7049   if (toSetAt)
7050   {
7051     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7052   }
7053   if (toSetProj)
7054   {
7055     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7056   }
7057   if (toSetUp)
7058   {
7059     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7060   }
7061   if (toSetCenter2d)
7062   {
7063     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
7064   }
7065
7066   return 0;
7067 }
7068
7069 //==============================================================================
7070 //function : V2DMode
7071 //purpose  :
7072 //==============================================================================
7073 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7074 {
7075   bool is2dMode = true;
7076   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7077   if (aV3dView.IsNull())
7078   {
7079     std::cout << "Error: no active view.\n";
7080     return 1;
7081   }
7082   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7083   {
7084     const TCollection_AsciiString anArg = theArgVec[anArgIt];
7085     TCollection_AsciiString anArgCase = anArg;
7086     anArgCase.LowerCase();
7087     if (anArgIt + 1 < theArgsNb
7088      && anArgCase == "-name")
7089     {
7090       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
7091       TCollection_AsciiString aViewName = aViewNames.GetViewName();
7092       if (!ViewerTest_myViews.IsBound1 (aViewName))
7093       {
7094         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
7095         return 1;
7096       }
7097       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7098     }
7099     else if (anArgCase == "-mode")
7100     {
7101       if (anArgIt + 1 < theArgsNb
7102        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
7103       {
7104         ++anArgIt;
7105       }
7106     }
7107     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
7108     {
7109       //
7110     }
7111     else
7112     {
7113       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
7114       return 1;
7115     }
7116   }
7117
7118   aV3dView->SetView2DMode (is2dMode);
7119   return 0;
7120 }
7121
7122 //==============================================================================
7123 //function : VAnimation
7124 //purpose  :
7125 //==============================================================================
7126 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7127                                     Standard_Integer  theArgNb,
7128                                     const char**      theArgVec)
7129 {
7130   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7131   if (theArgNb < 2)
7132   {
7133     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7134          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7135     {
7136       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
7137     }
7138     return 0;
7139   }
7140   if (aCtx.IsNull())
7141   {
7142     std::cout << "Error: no active view\n";
7143     return 1;
7144   }
7145
7146   Standard_Integer anArgIter = 1;
7147   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7148   if (aNameArg.IsEmpty())
7149   {
7150     std::cout << "Syntax error: animation name is not defined.\n";
7151     return 1;
7152   }
7153
7154   TCollection_AsciiString aNameArgLower = aNameArg;
7155   aNameArgLower.LowerCase();
7156   if (aNameArgLower == "-reset"
7157    || aNameArgLower == "-clear")
7158   {
7159     ViewerTest_AnimationTimelineMap.Clear();
7160     return 0;
7161   }
7162   else if (aNameArg.Value (1) == '-')
7163   {
7164     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
7165     return 1;
7166   }
7167
7168   const char* aNameSplitter = "/";
7169   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7170   if (aSplitPos == -1)
7171   {
7172     aNameSplitter = ".";
7173     aSplitPos = aNameArg.Search (aNameSplitter);
7174   }
7175
7176   // find existing or create a new animation by specified name within syntax "parent.child".
7177   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
7178   for (; !aNameArg.IsEmpty();)
7179   {
7180     TCollection_AsciiString aNameParent;
7181     if (aSplitPos != -1)
7182     {
7183       if (aSplitPos == aNameArg.Length())
7184       {
7185         std::cout << "Syntax error: animation name is not defined.\n";
7186         return 1;
7187       }
7188
7189       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7190       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7191
7192       aSplitPos = aNameArg.Search (aNameSplitter);
7193     }
7194     else
7195     {
7196       aNameParent = aNameArg;
7197       aNameArg.Clear();
7198     }
7199
7200     if (anAnimation.IsNull())
7201     {
7202       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7203       {
7204         anAnimation = new AIS_Animation (aNameParent);
7205         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7206       }
7207       aRootAnimation = anAnimation;
7208     }
7209     else
7210     {
7211       aParentAnimation = anAnimation;
7212       anAnimation = aParentAnimation->Find (aNameParent);
7213       if (anAnimation.IsNull())
7214       {
7215         anAnimation = new AIS_Animation (aNameParent);
7216         aParentAnimation->Add (anAnimation);
7217       }
7218     }
7219   }
7220
7221   if (anArgIter >= theArgNb)
7222   {
7223     // just print the list of children
7224     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7225     {
7226       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7227     }
7228     return 0;
7229   }
7230
7231   // animation parameters
7232   Standard_Boolean toPlay = Standard_False;
7233   Standard_Real aPlaySpeed     = 1.0;
7234   Standard_Real aPlayStartTime = anAnimation->StartPts();
7235   Standard_Real aPlayDuration  = anAnimation->Duration();
7236   Standard_Boolean isFreeCamera = Standard_False;
7237   Standard_Boolean isLockLoop   = Standard_False;
7238
7239   // video recording parameters
7240   TCollection_AsciiString aRecFile;
7241   Image_VideoParams aRecParams;
7242
7243   Handle(V3d_View) aView = ViewerTest::CurrentView();
7244   for (; anArgIter < theArgNb; ++anArgIter)
7245   {
7246     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7247     anArg.LowerCase();
7248     // general options
7249     if (anArg == "-reset"
7250      || anArg == "-clear")
7251     {
7252       anAnimation->Clear();
7253     }
7254     else if (anArg == "-remove"
7255           || anArg == "-del"
7256           || anArg == "-delete")
7257     {
7258       if (!aParentAnimation.IsNull())
7259       {
7260         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7261       }
7262       else
7263       {
7264         aParentAnimation->Remove (anAnimation);
7265       }
7266     }
7267     // playback options
7268     else if (anArg == "-play")
7269     {
7270       toPlay = Standard_True;
7271       if (++anArgIter < theArgNb)
7272       {
7273         if (*theArgVec[anArgIter] == '-')
7274         {
7275           --anArgIter;
7276           continue;
7277         }
7278         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7279
7280         if (++anArgIter < theArgNb)
7281         {
7282           if (*theArgVec[anArgIter] == '-')
7283           {
7284             --anArgIter;
7285             continue;
7286           }
7287           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7288         }
7289       }
7290     }
7291     else if (anArg == "-resume")
7292     {
7293       toPlay = Standard_True;
7294       aPlayStartTime = anAnimation->ElapsedTime();
7295       if (++anArgIter < theArgNb)
7296       {
7297         if (*theArgVec[anArgIter] == '-')
7298         {
7299           --anArgIter;
7300           continue;
7301         }
7302
7303         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7304       }
7305     }
7306     else if (anArg == "-playspeed"
7307           || anArg == "-speed")
7308     {
7309       if (++anArgIter >= theArgNb)
7310       {
7311         std::cout << "Syntax error at " << anArg << ".\n";
7312         return 1;
7313       }
7314       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7315     }
7316     else if (anArg == "-lock"
7317           || anArg == "-lockloop"
7318           || anArg == "-playlockloop")
7319     {
7320       isLockLoop = Standard_True;
7321     }
7322     else if (anArg == "-freecamera"
7323           || anArg == "-playfreecamera"
7324           || anArg == "-freelook")
7325     {
7326       isFreeCamera = Standard_True;
7327     }
7328     // video recodring options
7329     else if (anArg == "-rec"
7330           || anArg == "-record")
7331     {
7332       if (++anArgIter >= theArgNb)
7333       {
7334         std::cout << "Syntax error at " << anArg << ".\n";
7335         return 1;
7336       }
7337
7338       aRecFile = theArgVec[anArgIter];
7339       if (aRecParams.FpsNum <= 0)
7340       {
7341         aRecParams.FpsNum = 24;
7342       }
7343
7344       if (anArgIter + 2 < theArgNb
7345       && *theArgVec[anArgIter + 1] != '-'
7346       && *theArgVec[anArgIter + 2] != '-')
7347       {
7348         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7349         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7350         if (aWidthArg .IsIntegerValue()
7351          && aHeightArg.IsIntegerValue())
7352         {
7353           aRecParams.Width  = aWidthArg .IntegerValue();
7354           aRecParams.Height = aHeightArg.IntegerValue();
7355           anArgIter += 2;
7356         }
7357       }
7358     }
7359     else if (anArg == "-fps")
7360     {
7361       if (++anArgIter >= theArgNb)
7362       {
7363         std::cout << "Syntax error at " << anArg << ".\n";
7364         return 1;
7365       }
7366
7367       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7368       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7369       if (aSplitIndex == 0)
7370       {
7371         aRecParams.FpsNum = aFpsArg.IntegerValue();
7372       }
7373       else
7374       {
7375         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7376         aFpsArg.Split (aFpsArg.Length() - 1);
7377         const TCollection_AsciiString aNumStr = aFpsArg;
7378         aRecParams.FpsNum = aNumStr.IntegerValue();
7379         aRecParams.FpsDen = aDenStr.IntegerValue();
7380         if (aRecParams.FpsDen < 1)
7381         {
7382           std::cout << "Syntax error at " << anArg << ".\n";
7383           return 1;
7384         }
7385       }
7386     }
7387     else if (anArg == "-format")
7388     {
7389       if (++anArgIter >= theArgNb)
7390       {
7391         std::cout << "Syntax error at " << anArg << ".\n";
7392         return 1;
7393       }
7394       aRecParams.Format = theArgVec[anArgIter];
7395     }
7396     else if (anArg == "-pix_fmt"
7397           || anArg == "-pixfmt"
7398           || anArg == "-pixelformat")
7399     {
7400       if (++anArgIter >= theArgNb)
7401       {
7402         std::cout << "Syntax error at " << anArg << ".\n";
7403         return 1;
7404       }
7405       aRecParams.PixelFormat = theArgVec[anArgIter];
7406     }
7407     else if (anArg == "-codec"
7408           || anArg == "-vcodec"
7409           || anArg == "-videocodec")
7410     {
7411       if (++anArgIter >= theArgNb)
7412       {
7413         std::cout << "Syntax error at " << anArg << ".\n";
7414         return 1;
7415       }
7416       aRecParams.VideoCodec = theArgVec[anArgIter];
7417     }
7418     else if (anArg == "-crf"
7419           || anArg == "-preset"
7420           || anArg == "-qp")
7421     {
7422       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7423       if (++anArgIter >= theArgNb)
7424       {
7425         std::cout << "Syntax error at " << anArg << ".\n";
7426         return 1;
7427       }
7428
7429       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7430     }
7431     // animation definition options
7432     else if (anArg == "-start"
7433           || anArg == "-starttime"
7434           || anArg == "-startpts")
7435     {
7436       if (++anArgIter >= theArgNb)
7437       {
7438         std::cout << "Syntax error at " << anArg << ".\n";
7439         return 1;
7440       }
7441
7442       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7443       aRootAnimation->UpdateTotalDuration();
7444     }
7445     else if (anArg == "-end"
7446           || anArg == "-endtime"
7447           || anArg == "-endpts")
7448     {
7449       if (++anArgIter >= theArgNb)
7450       {
7451         std::cout << "Syntax error at " << anArg << ".\n";
7452         return 1;
7453       }
7454
7455       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7456       aRootAnimation->UpdateTotalDuration();
7457     }
7458     else if (anArg == "-dur"
7459           || anArg == "-duration")
7460     {
7461       if (++anArgIter >= theArgNb)
7462       {
7463         std::cout << "Syntax error at " << anArg << ".\n";
7464         return 1;
7465       }
7466
7467       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7468       aRootAnimation->UpdateTotalDuration();
7469     }
7470     else if (anArg == "-command"
7471           || anArg == "-cmd"
7472           || anArg == "-invoke"
7473           || anArg == "-eval"
7474           || anArg == "-proc")
7475     {
7476       if (++anArgIter >= theArgNb)
7477       {
7478         std::cout << "Syntax error at " << anArg << ".\n";
7479         return 1;
7480       }
7481
7482       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7483       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7484     }
7485     else if (anArg == "-objecttrsf"
7486           || anArg == "-objectransformation"
7487           || anArg == "-objtransformation"
7488           || anArg == "-objtrsf"
7489           || anArg == "-object"
7490           || anArg == "-obj")
7491     {
7492       if (++anArgIter >= theArgNb)
7493       {
7494         std::cout << "Syntax error at " << anArg << ".\n";
7495         return 1;
7496       }
7497
7498       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7499       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7500       if (!aMapOfAIS.IsBound2 (anObjName))
7501       {
7502         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7503         return 1;
7504       }
7505
7506       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
7507       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7508       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7509       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7510       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7511       Standard_Boolean isTrsfSet = Standard_False;
7512       Standard_Integer aTrsfArgIter = anArgIter + 1;
7513       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7514       {
7515         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7516         aTrsfArg.LowerCase();
7517         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7518         if (aTrsfArg.StartsWith ("-rotation")
7519          || aTrsfArg.StartsWith ("-rot"))
7520         {
7521           isTrsfSet = Standard_True;
7522           if (aTrsfArgIter + 4 >= theArgNb
7523           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7524           {
7525             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7526             return 1;
7527           }
7528           aTrsfArgIter += 4;
7529         }
7530         else if (aTrsfArg.StartsWith ("-location")
7531               || aTrsfArg.StartsWith ("-loc"))
7532         {
7533           isTrsfSet = Standard_True;
7534           if (aTrsfArgIter + 3 >= theArgNb
7535           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7536           {
7537             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7538             return 1;
7539           }
7540           aTrsfArgIter += 3;
7541         }
7542         else if (aTrsfArg.StartsWith ("-scale"))
7543         {
7544           isTrsfSet = Standard_True;
7545           if (++aTrsfArgIter >= theArgNb)
7546           {
7547             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7548             return 1;
7549           }
7550
7551           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7552           if (!aScaleStr.IsRealValue())
7553           {
7554             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7555             return 1;
7556           }
7557           aScales[anIndex] = aScaleStr.RealValue();
7558         }
7559         else
7560         {
7561           anArgIter = aTrsfArgIter - 1;
7562           break;
7563         }
7564       }
7565       if (!isTrsfSet)
7566       {
7567         std::cout << "Syntax error at " << anArg << ".\n";
7568         return 1;
7569       }
7570       else if (aTrsfArgIter >= theArgNb)
7571       {
7572         anArgIter = theArgNb;
7573       }
7574
7575       aTrsfs[0].SetRotation        (aRotQuats[0]);
7576       aTrsfs[1].SetRotation        (aRotQuats[1]);
7577       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7578       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7579       aTrsfs[0].SetScaleFactor     (aScales[0]);
7580       aTrsfs[1].SetScaleFactor     (aScales[1]);
7581
7582       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7583       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7584     }
7585     else if (anArg == "-viewtrsf"
7586           || anArg == "-view")
7587     {
7588       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7589       if (aCamAnimation.IsNull())
7590       {
7591         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7592         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7593       }
7594
7595       Handle(Graphic3d_Camera) aCams[2] =
7596       {
7597         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7598         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7599       };
7600
7601       Standard_Boolean isTrsfSet = Standard_False;
7602       Standard_Integer aViewArgIter = anArgIter + 1;
7603       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7604       {
7605         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7606         aViewArg.LowerCase();
7607         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7608         if (aViewArg.StartsWith ("-scale"))
7609         {
7610           isTrsfSet = Standard_True;
7611           if (++aViewArgIter >= theArgNb)
7612           {
7613             std::cout << "Syntax error at " << anArg << ".\n";
7614             return 1;
7615           }
7616
7617           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7618           if (!aScaleStr.IsRealValue())
7619           {
7620             std::cout << "Syntax error at " << aViewArg << ".\n";
7621             return 1;
7622           }
7623           Standard_Real aScale = aScaleStr.RealValue();
7624           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7625           aCams[anIndex]->SetScale (aScale);
7626         }
7627         else if (aViewArg.StartsWith ("-eye")
7628               || aViewArg.StartsWith ("-center")
7629               || aViewArg.StartsWith ("-at")
7630               || aViewArg.StartsWith ("-up"))
7631         {
7632           isTrsfSet = Standard_True;
7633           gp_XYZ anXYZ;
7634           if (aViewArgIter + 3 >= theArgNb
7635           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7636           {
7637             std::cout << "Syntax error at " << aViewArg << ".\n";
7638             return 1;
7639           }
7640           aViewArgIter += 3;
7641
7642           if (aViewArg.StartsWith ("-eye"))
7643           {
7644             aCams[anIndex]->SetEye (anXYZ);
7645           }
7646           else if (aViewArg.StartsWith ("-center")
7647                 || aViewArg.StartsWith ("-at"))
7648           {
7649             aCams[anIndex]->SetCenter (anXYZ);
7650           }
7651           else if (aViewArg.StartsWith ("-up"))
7652           {
7653             aCams[anIndex]->SetUp (anXYZ);
7654           }
7655         }
7656         else
7657         {
7658           anArgIter = aViewArgIter - 1;
7659           break;
7660         }
7661       }
7662       if (!isTrsfSet)
7663       {
7664         std::cout << "Syntax error at " << anArg << ".\n";
7665         return 1;
7666       }
7667       else if (aViewArgIter >= theArgNb)
7668       {
7669         anArgIter = theArgNb;
7670       }
7671
7672       aCamAnimation->SetCameraStart(aCams[0]);
7673       aCamAnimation->SetCameraEnd  (aCams[1]);
7674     }
7675     else
7676     {
7677       std::cout << "Syntax error at " << anArg << ".\n";
7678       return 1;
7679     }
7680   }
7681
7682   if (!toPlay && aRecFile.IsEmpty())
7683   {
7684     return 0;
7685   }
7686
7687   // Start animation timeline and process frame updating.
7688   TheIsAnimating = Standard_True;
7689   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7690   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7691   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7692   if (isFreeCamera)
7693   {
7694     aView->Camera()->Copy (aCameraBack);
7695   }
7696
7697   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7698   if (aRecParams.FpsNum <= 0)
7699   {
7700     while (!anAnimation->IsStopped())
7701     {
7702       aCameraBack->Copy (aView->Camera());
7703       const Standard_Real aPts = anAnimation->UpdateTimer();
7704       if (isFreeCamera)
7705       {
7706         aView->Camera()->Copy (aCameraBack);
7707       }
7708
7709       if (aPts >= anUpperPts)
7710       {
7711         anAnimation->Pause();
7712         break;
7713       }
7714
7715       if (aView->IsInvalidated())
7716       {
7717         aView->Redraw();
7718       }
7719       else
7720       {
7721         aView->RedrawImmediate();
7722       }
7723
7724       if (!isLockLoop)
7725       {
7726         // handle user events
7727         theDI.Eval ("after 1 set waiter 1");
7728         theDI.Eval ("vwait waiter");
7729       }
7730       if (!TheIsAnimating)
7731       {
7732         anAnimation->Pause();
7733         theDI << aPts;
7734         break;
7735       }
7736     }
7737
7738     if (aView->IsInvalidated())
7739     {
7740       aView->Redraw();
7741     }
7742     else
7743     {
7744       aView->RedrawImmediate();
7745     }
7746   }
7747   else
7748   {
7749     OSD_Timer aPerfTimer;
7750     aPerfTimer.Start();
7751
7752     Handle(Image_VideoRecorder) aRecorder;
7753     ImageFlipper aFlipper;
7754     Handle(Draw_ProgressIndicator) aProgress;
7755     if (!aRecFile.IsEmpty())
7756     {
7757       if (aRecParams.Width  <= 0
7758        || aRecParams.Height <= 0)
7759       {
7760         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7761       }
7762
7763       aRecorder = new Image_VideoRecorder();
7764       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7765       {
7766         std::cout << "Error: failed to open video file for recording\n";
7767         return 0;
7768       }
7769
7770       aProgress = new Draw_ProgressIndicator (theDI, 1);
7771     }
7772
7773     // Manage frame-rated animation here
7774     Standard_Real aPts = aPlayStartTime;
7775     int64_t aNbFrames = 0;
7776     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7777     Standard_Integer aSecondsProgress = 0;
7778     for (; aPts <= anUpperPts && aPSentry.More();)
7779     {
7780       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
7781       aPts = aPlayStartTime + aRecPts;
7782       ++aNbFrames;
7783       if (!anAnimation->Update (aPts))
7784       {
7785         break;
7786       }
7787
7788       if (!aRecorder.IsNull())
7789       {
7790         V3d_ImageDumpOptions aDumpParams;
7791         aDumpParams.Width          = aRecParams.Width;
7792         aDumpParams.Height         = aRecParams.Height;
7793         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
7794         aDumpParams.StereoOptions  = V3d_SDO_MONO;
7795         aDumpParams.ToAdjustAspect = Standard_True;
7796         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
7797         {
7798           std::cout << "Error: view dump is failed!\n";
7799           return 0;
7800         }
7801         aFlipper.FlipY (aRecorder->ChangeFrame());
7802         if (!aRecorder->PushFrame())
7803         {
7804           return 0;
7805         }
7806       }
7807       else
7808       {
7809         aView->Redraw();
7810       }
7811
7812       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7813       {
7814         aPSentry.Next();
7815         ++aSecondsProgress;
7816       }
7817     }
7818
7819     aPerfTimer.Stop();
7820     anAnimation->Stop();
7821     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7822     theDI << "Average FPS: " << aRecFps << "\n"
7823           << "Nb. Frames: "  << Standard_Real(aNbFrames);
7824
7825     aView->Redraw();
7826   }
7827
7828   aView->SetImmediateUpdate (wasImmediateUpdate);
7829   TheIsAnimating = Standard_False;
7830   return 0;
7831 }
7832
7833
7834 //=======================================================================
7835 //function : VChangeSelected
7836 //purpose  : Adds the shape to selection or remove one from it
7837 //=======================================================================
7838 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7839                                 Standard_Integer argc,
7840                                 const char ** argv)
7841 {
7842   if(argc != 2)
7843   {
7844     di<<"Usage : " << argv[0] << " shape \n";
7845     return 1;
7846   }
7847   //get AIS_Shape:
7848   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7849   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
7850   TCollection_AsciiString aName(argv[1]);
7851   Handle(AIS_InteractiveObject) anAISObject;
7852
7853   if(!aMap.IsBound2(aName))
7854   {
7855     di<<"Use 'vdisplay' before";
7856     return 1;
7857   }
7858   else
7859   {
7860     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
7861     if(anAISObject.IsNull()){
7862       di<<"No interactive object \n";
7863       return 1;
7864     }
7865
7866     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
7867   }
7868   return 0;
7869 }
7870
7871 //=======================================================================
7872 //function : VNbSelected
7873 //purpose  : Returns number of selected objects
7874 //=======================================================================
7875 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7876                                 Standard_Integer argc,
7877                                 const char ** argv)
7878 {
7879   if(argc != 1)
7880   {
7881     di << "Usage : " << argv[0] << "\n";
7882     return 1;
7883   }
7884   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7885   if(aContext.IsNull())
7886   {
7887     di << "use 'vinit' command before " << argv[0] << "\n";
7888     return 1;
7889   }
7890   di << aContext->NbSelected() << "\n";
7891   return 0;
7892 }
7893
7894 //=======================================================================
7895 //function : VPurgeDisplay
7896 //purpose  : Switches altialiasing on or off
7897 //=======================================================================
7898 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7899                                 Standard_Integer argc,
7900                                 const char ** argv)
7901 {
7902   if (argc > 1)
7903   {
7904     di << "Usage : " << argv[0] << "\n";
7905     return 1;
7906   }
7907   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7908   if (aContext.IsNull())
7909   {
7910     di << "use 'vinit' command before " << argv[0] << "\n";
7911     return 1;
7912   }
7913
7914   di << aContext->PurgeDisplay() << "\n";
7915   return 0;
7916 }
7917
7918 //=======================================================================
7919 //function : VSetViewSize
7920 //purpose  :
7921 //=======================================================================
7922 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7923                                 Standard_Integer argc,
7924                                 const char ** argv)
7925 {
7926   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7927   if(aContext.IsNull())
7928   {
7929     di << "use 'vinit' command before " << argv[0] << "\n";
7930     return 1;
7931   }
7932   if(argc != 2)
7933   {
7934     di<<"Usage : " << argv[0] << " Size\n";
7935     return 1;
7936   }
7937   Standard_Real aSize = Draw::Atof (argv[1]);
7938   if (aSize <= 0.)
7939   {
7940     di<<"Bad Size value  : " << aSize << "\n";
7941     return 1;
7942   }
7943
7944   Handle(V3d_View) aView = ViewerTest::CurrentView();
7945   aView->SetSize(aSize);
7946   return 0;
7947 }
7948
7949 //=======================================================================
7950 //function : VMoveView
7951 //purpose  :
7952 //=======================================================================
7953 static Standard_Integer VMoveView (Draw_Interpretor& di,
7954                                 Standard_Integer argc,
7955                                 const char ** argv)
7956 {
7957   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7958   if(aContext.IsNull())
7959   {
7960     di << "use 'vinit' command before " << argv[0] << "\n";
7961     return 1;
7962   }
7963   if(argc < 4 || argc > 5)
7964   {
7965     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7966     return 1;
7967   }
7968   Standard_Real Dx = Draw::Atof (argv[1]);
7969   Standard_Real Dy = Draw::Atof (argv[2]);
7970   Standard_Real Dz = Draw::Atof (argv[3]);
7971   Standard_Boolean aStart = Standard_True;
7972   if (argc == 5)
7973   {
7974       aStart = (Draw::Atoi (argv[4]) > 0);
7975   }
7976
7977   Handle(V3d_View) aView = ViewerTest::CurrentView();
7978   aView->Move(Dx,Dy,Dz,aStart);
7979   return 0;
7980 }
7981
7982 //=======================================================================
7983 //function : VTranslateView
7984 //purpose  :
7985 //=======================================================================
7986 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7987                                 Standard_Integer argc,
7988                                 const char ** argv)
7989 {
7990   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7991   if(aContext.IsNull())
7992   {
7993     di << "use 'vinit' command before " << argv[0] << "\n";
7994     return 1;
7995   }
7996   if(argc < 4 || argc > 5)
7997   {
7998     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7999     return 1;
8000   }
8001   Standard_Real Dx = Draw::Atof (argv[1]);
8002   Standard_Real Dy = Draw::Atof (argv[2]);
8003   Standard_Real Dz = Draw::Atof (argv[3]);
8004   Standard_Boolean aStart = Standard_True;
8005   if (argc == 5)
8006   {
8007       aStart = (Draw::Atoi (argv[4]) > 0);
8008   }
8009
8010   Handle(V3d_View) aView = ViewerTest::CurrentView();
8011   aView->Translate(Dx,Dy,Dz,aStart);
8012   return 0;
8013 }
8014
8015 //=======================================================================
8016 //function : VTurnView
8017 //purpose  :
8018 //=======================================================================
8019 static Standard_Integer VTurnView (Draw_Interpretor& di,
8020                                 Standard_Integer argc,
8021                                 const char ** argv)
8022 {
8023   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8024   if(aContext.IsNull()) {
8025     di << "use 'vinit' command before " << argv[0] << "\n";
8026     return 1;
8027   }
8028   if(argc < 4 || argc > 5){
8029     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
8030     return 1;
8031   }
8032   Standard_Real Ax = Draw::Atof (argv[1]);
8033   Standard_Real Ay = Draw::Atof (argv[2]);
8034   Standard_Real Az = Draw::Atof (argv[3]);
8035   Standard_Boolean aStart = Standard_True;
8036   if (argc == 5)
8037   {
8038       aStart = (Draw::Atoi (argv[4]) > 0);
8039   }
8040
8041   Handle(V3d_View) aView = ViewerTest::CurrentView();
8042   aView->Turn(Ax,Ay,Az,aStart);
8043   return 0;
8044 }
8045
8046 //==============================================================================
8047 //function : VTextureEnv
8048 //purpose  : ENables or disables environment mapping
8049 //==============================================================================
8050 class OCC_TextureEnv : public Graphic3d_TextureEnv
8051 {
8052 public:
8053   OCC_TextureEnv(const Standard_CString FileName);
8054   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8055   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8056                             const Standard_Boolean theModulateFlag,
8057                             const Graphic3d_TypeOfTextureFilter theFilter,
8058                             const Standard_ShortReal theXScale,
8059                             const Standard_ShortReal theYScale,
8060                             const Standard_ShortReal theXShift,
8061                             const Standard_ShortReal theYShift,
8062                             const Standard_ShortReal theAngle);
8063   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
8064 };
8065 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
8066
8067 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8068   : Graphic3d_TextureEnv(theFileName)
8069 {
8070 }
8071
8072 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8073   : Graphic3d_TextureEnv(theTexId)
8074 {
8075 }
8076
8077 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8078                                           const Standard_Boolean theModulateFlag,
8079                                           const Graphic3d_TypeOfTextureFilter theFilter,
8080                                           const Standard_ShortReal theXScale,
8081                                           const Standard_ShortReal theYScale,
8082                                           const Standard_ShortReal theXShift,
8083                                           const Standard_ShortReal theYShift,
8084                                           const Standard_ShortReal theAngle)
8085 {
8086   myParams->SetRepeat     (theRepeatFlag);
8087   myParams->SetModulate   (theModulateFlag);
8088   myParams->SetFilter     (theFilter);
8089   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
8090   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8091   myParams->SetRotation   (theAngle);
8092 }
8093
8094 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
8095 {
8096   // get the active view
8097   Handle(V3d_View) aView = ViewerTest::CurrentView();
8098   if (aView.IsNull())
8099   {
8100     std::cerr << "No active view. Please call vinit.\n";
8101     return 1;
8102   }
8103
8104   // Checking the input arguments
8105   Standard_Boolean anEnableFlag = Standard_False;
8106   Standard_Boolean isOk         = theArgNb >= 2;
8107   if (isOk)
8108   {
8109     TCollection_AsciiString anEnableOpt(theArgVec[1]);
8110     anEnableFlag = anEnableOpt.IsEqual("on");
8111     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
8112   }
8113   if (anEnableFlag)
8114   {
8115     isOk = (theArgNb == 3 || theArgNb == 11);
8116     if (isOk)
8117     {
8118       TCollection_AsciiString aTextureOpt(theArgVec[2]);
8119       isOk = (!aTextureOpt.IsIntegerValue() ||
8120              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8121
8122       if (isOk && theArgNb == 11)
8123       {
8124         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
8125                                 aModulateOpt(theArgVec[4]),
8126                                 aFilterOpt  (theArgVec[5]),
8127                                 aSScaleOpt  (theArgVec[6]),
8128                                 aTScaleOpt  (theArgVec[7]),
8129                                 aSTransOpt  (theArgVec[8]),
8130                                 aTTransOpt  (theArgVec[9]),
8131                                 anAngleOpt  (theArgVec[10]);
8132         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
8133                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8134                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
8135                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
8136                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
8137                 anAngleOpt.IsRealValue());
8138       }
8139     }
8140   }
8141
8142   if (!isOk)
8143   {
8144     std::cerr << "Usage :" << std::endl;
8145     std::cerr << theArgVec[0] << " off" << std::endl;
8146     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;
8147     return 1;
8148   }
8149
8150   if (anEnableFlag)
8151   {
8152     TCollection_AsciiString aTextureOpt(theArgVec[2]);
8153     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8154                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8155                                      new OCC_TextureEnv(theArgVec[2]);
8156
8157     if (theArgNb == 11)
8158     {
8159       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8160       aTexEnv->SetTextureParameters(
8161         aRepeatOpt.  IsEqual("repeat"),
8162         aModulateOpt.IsEqual("modulate"),
8163         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8164                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8165                                                                            Graphic3d_TOTF_TRILINEAR,
8166         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8167         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8168         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8169         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8170         (Standard_ShortReal)Draw::Atof(theArgVec[10])
8171         );
8172     }
8173     aView->SetTextureEnv(aTexEnv);
8174   }
8175   else // Disabling environment mapping
8176   {
8177     Handle(Graphic3d_TextureEnv) aTexture;
8178     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8179   }
8180
8181   aView->Redraw();
8182   return 0;
8183 }
8184
8185 namespace
8186 {
8187   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8188
8189   //! Remove registered clipping plane from all views and objects.
8190   static void removePlane (MapOfPlanes& theRegPlanes,
8191                            const TCollection_AsciiString& theName)
8192   {
8193     Handle(Graphic3d_ClipPlane) aClipPlane;
8194     if (!theRegPlanes.Find (theName, aClipPlane))
8195     {
8196       std::cout << "Warning: no such plane.\n";
8197       return;
8198     }
8199
8200     theRegPlanes.UnBind (theName);
8201     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8202          anIObjIt.More(); anIObjIt.Next())
8203     {
8204       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
8205       aPrs->RemoveClipPlane (aClipPlane);
8206     }
8207
8208     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8209          aViewIt.More(); aViewIt.Next())
8210     {
8211       const Handle(V3d_View)& aView = aViewIt.Key2();
8212       aView->RemoveClipPlane(aClipPlane);
8213     }
8214
8215     ViewerTest::RedrawAllViews();
8216   }
8217 }
8218
8219 //===============================================================================================
8220 //function : VClipPlane
8221 //purpose  :
8222 //===============================================================================================
8223 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8224 {
8225   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8226   static MapOfPlanes aRegPlanes;
8227
8228   if (theArgsNb < 2)
8229   {
8230     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8231     {
8232       theDi << aPlaneIter.Key() << " ";
8233     }
8234     return 0;
8235   }
8236
8237   TCollection_AsciiString aCommand (theArgVec[1]);
8238   aCommand.LowerCase();
8239   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8240   if (anActiveView.IsNull())
8241   {
8242     std::cout << "Error: no active view.\n";
8243     return 1;
8244   }
8245
8246   // print maximum number of planes for current viewer
8247   if (aCommand == "-maxplanes"
8248    || aCommand == "maxplanes")
8249   {
8250     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8251           << " plane slots provided by driver.\n";
8252     return 0;
8253   }
8254
8255   // create / delete plane instance
8256   if (aCommand == "-create"
8257    || aCommand == "create"
8258    || aCommand == "-delete"
8259    || aCommand == "delete"
8260    || aCommand == "-clone"
8261    || aCommand == "clone")
8262   {
8263     if (theArgsNb < 3)
8264     {
8265       std::cout << "Syntax error: plane name is required.\n";
8266       return 1;
8267     }
8268
8269     Standard_Boolean toCreate = aCommand == "-create"
8270                              || aCommand == "create";
8271     Standard_Boolean toClone  = aCommand == "-clone"
8272                              || aCommand == "clone";
8273     Standard_Boolean toDelete = aCommand == "-delete"
8274                              || aCommand == "delete";
8275     TCollection_AsciiString aPlane (theArgVec[2]);
8276
8277     if (toCreate)
8278     {
8279       if (aRegPlanes.IsBound (aPlane))
8280       {
8281         std::cout << "Warning: existing plane has been overridden.\n";
8282         toDelete = true;
8283       }
8284       else
8285       {
8286         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8287         return 0;
8288       }
8289     }
8290     else if (toClone) // toClone
8291     {
8292       if (!aRegPlanes.IsBound (aPlane))
8293       {
8294         std::cout << "Error: no such plane.\n";
8295         return 1;
8296       }
8297       else if (theArgsNb < 4)
8298       {
8299         std::cout << "Syntax error: enter name for new plane.\n";
8300         return 1;
8301       }
8302
8303       TCollection_AsciiString aClone (theArgVec[3]);
8304       if (aRegPlanes.IsBound (aClone))
8305       {
8306         std::cout << "Error: plane name is in use.\n";
8307         return 1;
8308       }
8309
8310       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8311
8312       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8313       return 0;
8314     }
8315
8316     if (toDelete)
8317     {
8318       if (aPlane == "ALL"
8319        || aPlane == "all"
8320        || aPlane == "*")
8321       {
8322         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8323         {
8324           aPlane = aPlaneIter.Key();
8325           removePlane (aRegPlanes, aPlane);
8326           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8327         }
8328       }
8329       else
8330       {
8331         removePlane (aRegPlanes, aPlane);
8332       }
8333     }
8334
8335     if (toCreate)
8336     {
8337       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8338     }
8339     return 0;
8340   }
8341
8342   // set / unset plane command
8343   if (aCommand == "set"
8344    || aCommand == "unset")
8345   {
8346     if (theArgsNb < 5)
8347     {
8348       std::cout << "Syntax error: need more arguments.\n";
8349       return 1;
8350     }
8351
8352     // redirect to new syntax
8353     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8354     anArgVec.SetValue (1, theArgVec[0]);
8355     anArgVec.SetValue (2, theArgVec[2]);
8356     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8357     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8358     {
8359       anArgVec.SetValue (anIt, theArgVec[anIt]);
8360     }
8361
8362     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8363   }
8364
8365   // change plane command
8366   TCollection_AsciiString aPlaneName;
8367   Handle(Graphic3d_ClipPlane) aClipPlane;
8368   Standard_Integer anArgIter = 0;
8369   if (aCommand == "-change"
8370    || aCommand == "change")
8371   {
8372     // old syntax support
8373     if (theArgsNb < 3)
8374     {
8375       std::cout << "Syntax error: need more arguments.\n";
8376       return 1;
8377     }
8378
8379     anArgIter  = 3;
8380     aPlaneName = theArgVec[2];
8381     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8382     {
8383       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8384       return 1;
8385     }
8386   }
8387   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8388   {
8389     anArgIter  = 2;
8390     aPlaneName = theArgVec[1];
8391   }
8392   else
8393   {
8394     anArgIter  = 2;
8395     aPlaneName = theArgVec[1];
8396     aClipPlane = new Graphic3d_ClipPlane();
8397     aRegPlanes.Bind (aPlaneName, aClipPlane);
8398     theDi << "Created new plane " << aPlaneName << ".\n";
8399   }
8400
8401   if (theArgsNb - anArgIter < 1)
8402   {
8403     std::cout << "Syntax error: need more arguments.\n";
8404     return 1;
8405   }
8406
8407   for (; anArgIter < theArgsNb; ++anArgIter)
8408   {
8409     const char**     aChangeArgs   = theArgVec + anArgIter;
8410     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8411     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8412     aChangeArg.LowerCase();
8413
8414     Standard_Boolean toEnable = Standard_True;
8415     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8416     {
8417       aClipPlane->SetOn (toEnable);
8418     }
8419     else if (aChangeArg == "-equation"
8420           || aChangeArg == "equation")
8421     {
8422       if (aNbChangeArgs < 5)
8423       {
8424         std::cout << "Syntax error: need more arguments.\n";
8425         return 1;
8426       }
8427
8428       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
8429       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
8430       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
8431       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
8432       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8433       anArgIter += 4;
8434     }
8435     else if (aChangeArg == "-capping"
8436           || aChangeArg == "capping")
8437     {
8438       if (aNbChangeArgs < 2)
8439       {
8440         std::cout << "Syntax error: need more arguments.\n";
8441         return 1;
8442       }
8443
8444       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8445       {
8446         aClipPlane->SetCapping (toEnable);
8447         anArgIter += 1;
8448       }
8449       else
8450       {
8451         // just skip otherwise (old syntax)
8452       }
8453     }
8454     else if (aChangeArg == "-useobjectmaterial"
8455           || aChangeArg == "-useobjectmat"
8456           || aChangeArg == "-useobjmat"
8457           || aChangeArg == "-useobjmaterial")
8458     {
8459       if (aNbChangeArgs < 2)
8460       {
8461         std::cout << "Syntax error: need more arguments.\n";
8462         return 1;
8463       }
8464
8465       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8466       {
8467         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8468         anArgIter += 1;
8469       }
8470     }
8471     else if (aChangeArg == "-useobjecttexture"
8472           || aChangeArg == "-useobjecttex"
8473           || aChangeArg == "-useobjtexture"
8474           || aChangeArg == "-useobjtex")
8475     {
8476       if (aNbChangeArgs < 2)
8477       {
8478         std::cout << "Syntax error: need more arguments.\n";
8479         return 1;
8480       }
8481
8482       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8483       {
8484         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8485         anArgIter += 1;
8486       }
8487     }
8488     else if (aChangeArg == "-useobjectshader"
8489           || aChangeArg == "-useobjshader")
8490     {
8491       if (aNbChangeArgs < 2)
8492       {
8493         std::cout << "Syntax error: need more arguments.\n";
8494         return 1;
8495       }
8496
8497       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8498       {
8499         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8500         anArgIter += 1;
8501       }
8502     }
8503     else if (aChangeArg == "-color"
8504           || aChangeArg == "color")
8505     {
8506       Quantity_Color aColor;
8507       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8508                                                            aChangeArgs + 1,
8509                                                            aColor);
8510       if (aNbParsed == 0)
8511       {
8512         std::cout << "Syntax error: need more arguments.\n";
8513         return 1;
8514       }
8515
8516       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8517       aMat.SetAmbientColor (aColor);
8518       aMat.SetDiffuseColor (aColor);
8519       aClipPlane->SetCappingMaterial (aMat);
8520       anArgIter += aNbParsed;
8521     }
8522     else if (aChangeArg == "-texname"
8523           || aChangeArg == "texname")
8524     {
8525       if (aNbChangeArgs < 2)
8526       {
8527         std::cout << "Syntax error: need more arguments.\n";
8528         return 1;
8529       }
8530
8531       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8532       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8533       if (!aTexture->IsDone())
8534       {
8535         aClipPlane->SetCappingTexture (NULL);
8536       }
8537       else
8538       {
8539         aTexture->EnableModulate();
8540         aTexture->EnableRepeat();
8541         aClipPlane->SetCappingTexture (aTexture);
8542       }
8543       anArgIter += 1;
8544     }
8545     else if (aChangeArg == "-texscale"
8546           || aChangeArg == "texscale")
8547     {
8548       if (aClipPlane->CappingTexture().IsNull())
8549       {
8550         std::cout << "Error: no texture is set.\n";
8551         return 1;
8552       }
8553
8554       if (aNbChangeArgs < 3)
8555       {
8556         std::cout << "Syntax error: need more arguments.\n";
8557         return 1;
8558       }
8559
8560       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8561       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8562       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8563       anArgIter += 2;
8564     }
8565     else if (aChangeArg == "-texorigin"
8566           || aChangeArg == "texorigin") // texture origin
8567     {
8568       if (aClipPlane->CappingTexture().IsNull())
8569       {
8570         std::cout << "Error: no texture is set.\n";
8571         return 1;
8572       }
8573
8574       if (aNbChangeArgs < 3)
8575       {
8576         std::cout << "Syntax error: need more arguments.\n";
8577         return 1;
8578       }
8579
8580       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8581       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8582
8583       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8584       anArgIter += 2;
8585     }
8586     else if (aChangeArg == "-texrotate"
8587           || aChangeArg == "texrotate") // texture rotation
8588     {
8589       if (aClipPlane->CappingTexture().IsNull())
8590       {
8591         std::cout << "Error: no texture is set.\n";
8592         return 1;
8593       }
8594
8595       if (aNbChangeArgs < 2)
8596       {
8597         std::cout << "Syntax error: need more arguments.\n";
8598         return 1;
8599       }
8600
8601       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8602       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8603       anArgIter += 1;
8604     }
8605     else if (aChangeArg == "-hatch"
8606           || aChangeArg == "hatch")
8607     {
8608       if (aNbChangeArgs < 2)
8609       {
8610         std::cout << "Syntax error: need more arguments.\n";
8611         return 1;
8612       }
8613
8614       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8615       aHatchStr.LowerCase();
8616       if (aHatchStr == "on")
8617       {
8618         aClipPlane->SetCappingHatchOn();
8619       }
8620       else if (aHatchStr == "off")
8621       {
8622         aClipPlane->SetCappingHatchOff();
8623       }
8624       else
8625       {
8626         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8627       }
8628       anArgIter += 1;
8629     }
8630     else if (aChangeArg == "-delete"
8631           || aChangeArg == "delete")
8632     {
8633       removePlane (aRegPlanes, aPlaneName);
8634       return 0;
8635     }
8636     else if (aChangeArg == "-set"
8637           || aChangeArg == "-unset")
8638     {
8639       // set / unset plane command
8640       Standard_Boolean toSet = aChangeArg == "-set";
8641       Standard_Integer anIt = 1;
8642       for (; anIt < aNbChangeArgs; ++anIt)
8643       {
8644         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8645         if (anEntityName.IsEmpty()
8646          || anEntityName.Value (1) == '-')
8647         {
8648           break;
8649         }
8650         else if (ViewerTest_myViews.IsBound1 (anEntityName))
8651         {
8652           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8653           if (toSet)
8654           {
8655             aView->AddClipPlane (aClipPlane);
8656           }
8657           else
8658           {
8659             aView->RemoveClipPlane (aClipPlane);
8660           }
8661           continue;
8662         }
8663         else if (GetMapOfAIS().IsBound2 (anEntityName))
8664         {
8665           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
8666           if (toSet)
8667           {
8668             aIObj->AddClipPlane (aClipPlane);
8669           }
8670           else
8671           {
8672             aIObj->RemoveClipPlane (aClipPlane);
8673           }
8674         }
8675         else
8676         {
8677           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
8678           return 1;
8679         }
8680       }
8681
8682       if (anIt == 1)
8683       {
8684         // apply to active view
8685         if (toSet)
8686         {
8687           anActiveView->AddClipPlane (aClipPlane);
8688         }
8689         else
8690         {
8691           anActiveView->RemoveClipPlane (aClipPlane);
8692         }
8693       }
8694       else
8695       {
8696         anArgIter = anArgIter + anIt - 1;
8697       }
8698     }
8699     else
8700     {
8701       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8702       return 1;
8703     }
8704   }
8705
8706   ViewerTest::RedrawAllViews();
8707   return 0;
8708 }
8709
8710 //===============================================================================================
8711 //function : VZRange
8712 //purpose  :
8713 //===============================================================================================
8714 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8715 {
8716   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8717
8718   if (aCurrentView.IsNull())
8719   {
8720     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8721     return 1;
8722   }
8723
8724   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
8725
8726   if (theArgsNb < 2)
8727   {
8728     theDi << "ZNear: " << aCamera->ZNear() << "\n";
8729     theDi << "ZFar: " << aCamera->ZFar() << "\n";
8730     return 0;
8731   }
8732
8733   if (theArgsNb == 3)
8734   {
8735     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8736     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
8737
8738     if (aNewZNear >= aNewZFar)
8739     {
8740       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
8741       return 1;
8742     }
8743
8744     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8745     {
8746       std::cout << theArgVec[0] << ": invalid arguments: ";
8747       std::cout << "znear, zfar should be positive for perspective camera.\n";
8748       return 1;
8749     }
8750
8751     aCamera->SetZRange (aNewZNear, aNewZFar);
8752   }
8753   else
8754   {
8755     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8756     return 1;
8757   }
8758
8759   aCurrentView->Redraw();
8760
8761   return 0;
8762 }
8763
8764 //===============================================================================================
8765 //function : VAutoZFit
8766 //purpose  :
8767 //===============================================================================================
8768 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8769 {
8770   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8771
8772   if (aCurrentView.IsNull())
8773   {
8774     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8775     return 1;
8776   }
8777
8778   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
8779
8780   if (theArgsNb > 3)
8781   {
8782     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8783     return 1;
8784   }
8785
8786   if (theArgsNb < 2)
8787   {
8788     theDi << "Auto z-fit mode: \n"
8789           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
8790           << "Scale: " << aScale << "\n";
8791     return 0;
8792   }
8793
8794   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
8795
8796   if (theArgsNb >= 3)
8797   {
8798     aScale = Draw::Atoi (theArgVec[2]);
8799   }
8800
8801   aCurrentView->SetAutoZFitMode (isOn, aScale);
8802   aCurrentView->AutoZFit();
8803   aCurrentView->Redraw();
8804
8805   return 0;
8806 }
8807
8808 //! Auxiliary function to print projection type
8809 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
8810 {
8811   switch (theProjType)
8812   {
8813     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
8814     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
8815     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
8816     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
8817     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
8818   }
8819   return "UNKNOWN";
8820 }
8821
8822 //===============================================================================================
8823 //function : VCamera
8824 //purpose  :
8825 //===============================================================================================
8826 static int VCamera (Draw_Interpretor& theDI,
8827                     Standard_Integer  theArgsNb,
8828                     const char**      theArgVec)
8829 {
8830   Handle(V3d_View) aView = ViewerTest::CurrentView();
8831   if (aView.IsNull())
8832   {
8833     std::cout << "Error: no active view.\n";
8834     return 1;
8835   }
8836
8837   Handle(Graphic3d_Camera) aCamera = aView->Camera();
8838   if (theArgsNb < 2)
8839   {
8840     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
8841     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
8842     theDI << "Distance:   " << aCamera->Distance() << "\n";
8843     theDI << "IOD:        " << aCamera->IOD() << "\n";
8844     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
8845     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
8846     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
8847     return 0;
8848   }
8849
8850   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8851   {
8852     Standard_CString        anArg = theArgVec[anArgIter];
8853     TCollection_AsciiString anArgCase (anArg);
8854     anArgCase.LowerCase();
8855     if (anArgCase == "-proj"
8856      || anArgCase == "-projection"
8857      || anArgCase == "-projtype"
8858      || anArgCase == "-projectiontype")
8859     {
8860       theDI << projTypeName (aCamera->ProjectionType()) << " ";
8861     }
8862     else if (anArgCase == "-ortho"
8863           || anArgCase == "-orthographic")
8864     {
8865       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8866     }
8867     else if (anArgCase == "-persp"
8868           || anArgCase == "-perspective"
8869           || anArgCase == "-perspmono"
8870           || anArgCase == "-perspectivemono"
8871           || anArgCase == "-mono")
8872     {
8873       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8874     }
8875     else if (anArgCase == "-stereo"
8876           || anArgCase == "-stereoscopic"
8877           || anArgCase == "-perspstereo"
8878           || anArgCase == "-perspectivestereo")
8879     {
8880       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8881     }
8882     else if (anArgCase == "-left"
8883           || anArgCase == "-lefteye"
8884           || anArgCase == "-monoleft"
8885           || anArgCase == "-monolefteye"
8886           || anArgCase == "-perpsleft"
8887           || anArgCase == "-perpslefteye")
8888     {
8889       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8890     }
8891     else if (anArgCase == "-right"
8892           || anArgCase == "-righteye"
8893           || anArgCase == "-monoright"
8894           || anArgCase == "-monorighteye"
8895           || anArgCase == "-perpsright")
8896     {
8897       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8898     }
8899     else if (anArgCase == "-dist"
8900           || anArgCase == "-distance")
8901     {
8902       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8903       if (anArgValue != NULL
8904       && *anArgValue != '-')
8905       {
8906         ++anArgIter;
8907         aCamera->SetDistance (Draw::Atof (anArgValue));
8908         continue;
8909       }
8910       theDI << aCamera->Distance() << " ";
8911     }
8912     else if (anArgCase == "-iod")
8913     {
8914       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8915       if (anArgValue != NULL
8916       && *anArgValue != '-')
8917       {
8918         ++anArgIter;
8919         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8920         continue;
8921       }
8922       theDI << aCamera->IOD() << " ";
8923     }
8924     else if (anArgCase == "-iodtype")
8925     {
8926       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8927       TCollection_AsciiString anValueCase (anArgValue);
8928       anValueCase.LowerCase();
8929       if (anValueCase == "abs"
8930        || anValueCase == "absolute")
8931       {
8932         ++anArgIter;
8933         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8934         continue;
8935       }
8936       else if (anValueCase == "rel"
8937             || anValueCase == "relative")
8938       {
8939         ++anArgIter;
8940         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8941         continue;
8942       }
8943       else if (*anArgValue != '-')
8944       {
8945         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8946         return 1;
8947       }
8948       switch (aCamera->GetIODType())
8949       {
8950         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8951         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8952       }
8953     }
8954     else if (anArgCase == "-zfocus")
8955     {
8956       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8957       if (anArgValue != NULL
8958       && *anArgValue != '-')
8959       {
8960         ++anArgIter;
8961         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8962         continue;
8963       }
8964       theDI << aCamera->ZFocus() << " ";
8965     }
8966     else if (anArgCase == "-zfocustype")
8967     {
8968       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8969       TCollection_AsciiString anValueCase (anArgValue);
8970       anValueCase.LowerCase();
8971       if (anValueCase == "abs"
8972        || anValueCase == "absolute")
8973       {
8974         ++anArgIter;
8975         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8976         continue;
8977       }
8978       else if (anValueCase == "rel"
8979             || anValueCase == "relative")
8980       {
8981         ++anArgIter;
8982         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8983         continue;
8984       }
8985       else if (*anArgValue != '-')
8986       {
8987         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8988         return 1;
8989       }
8990       switch (aCamera->ZFocusType())
8991       {
8992         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8993         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8994       }
8995     }
8996     else if (anArgCase == "-fov"
8997           || anArgCase == "-fovy")
8998     {
8999       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9000       if (anArgValue != NULL
9001       && *anArgValue != '-')
9002       {
9003         ++anArgIter;
9004         aCamera->SetFOVy (Draw::Atof (anArgValue));
9005         continue;
9006       }
9007       theDI << aCamera->FOVy() << " ";
9008     }
9009     else
9010     {
9011       std::cout << "Error: unknown argument '" << anArg << "'\n";
9012       return 1;
9013     }
9014   }
9015
9016   aView->AutoZFit();
9017   aView->Redraw();
9018
9019   return 0;
9020 }
9021
9022 //! Parse stereo output mode
9023 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
9024                                          Graphic3d_StereoMode& theMode)
9025 {
9026   TCollection_AsciiString aFlag (theArg);
9027   aFlag.LowerCase();
9028   if (aFlag == "quadbuffer")
9029   {
9030     theMode = Graphic3d_StereoMode_QuadBuffer;
9031   }
9032   else if (aFlag == "anaglyph")
9033   {
9034     theMode = Graphic3d_StereoMode_Anaglyph;
9035   }
9036   else if (aFlag == "row"
9037         || aFlag == "rowinterlaced")
9038   {
9039     theMode = Graphic3d_StereoMode_RowInterlaced;
9040   }
9041   else if (aFlag == "col"
9042         || aFlag == "colinterlaced"
9043         || aFlag == "columninterlaced")
9044   {
9045     theMode = Graphic3d_StereoMode_ColumnInterlaced;
9046   }
9047   else if (aFlag == "chess"
9048         || aFlag == "chessboard")
9049   {
9050     theMode = Graphic3d_StereoMode_ChessBoard;
9051   }
9052   else if (aFlag == "sbs"
9053         || aFlag == "sidebyside")
9054   {
9055     theMode = Graphic3d_StereoMode_SideBySide;
9056   }
9057   else if (aFlag == "ou"
9058         || aFlag == "overunder")
9059   {
9060     theMode = Graphic3d_StereoMode_OverUnder;
9061   }
9062   else if (aFlag == "pageflip"
9063         || aFlag == "softpageflip")
9064   {
9065     theMode = Graphic3d_StereoMode_SoftPageFlip;
9066   }
9067   else
9068   {
9069     return Standard_False;
9070   }
9071   return Standard_True;
9072 }
9073
9074 //! Parse anaglyph filter
9075 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
9076                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
9077 {
9078   TCollection_AsciiString aFlag (theArg);
9079   aFlag.LowerCase();
9080   if (aFlag == "redcyansimple")
9081   {
9082     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9083   }
9084   else if (aFlag == "redcyan"
9085         || aFlag == "redcyanoptimized")
9086   {
9087     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
9088   }
9089   else if (aFlag == "yellowbluesimple")
9090   {
9091     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
9092   }
9093   else if (aFlag == "yellowblue"
9094         || aFlag == "yellowblueoptimized")
9095   {
9096     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
9097   }
9098   else if (aFlag == "greenmagenta"
9099         || aFlag == "greenmagentasimple")
9100   {
9101     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
9102   }
9103   else
9104   {
9105     return Standard_False;
9106   }
9107   return Standard_True;
9108 }
9109
9110 //==============================================================================
9111 //function : VStereo
9112 //purpose  :
9113 //==============================================================================
9114
9115 static int VStereo (Draw_Interpretor& theDI,
9116                     Standard_Integer  theArgNb,
9117                     const char**      theArgVec)
9118 {
9119   Handle(V3d_View) aView = ViewerTest::CurrentView();
9120   if (theArgNb < 2)
9121   {
9122     if (aView.IsNull())
9123     {
9124       std::cout << "Error: no active viewer!\n";
9125       return 0;
9126     }
9127
9128     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
9129     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
9130     if (isActive)
9131     {
9132       TCollection_AsciiString aMode;
9133       switch (aView->RenderingParams().StereoMode)
9134       {
9135         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
9136         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
9137         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
9138         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
9139         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
9140         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
9141         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
9142         case Graphic3d_StereoMode_Anaglyph  :
9143           aMode = "anaglyph";
9144           switch (aView->RenderingParams().AnaglyphFilter)
9145           {
9146             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
9147             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
9148             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
9149             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
9150             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
9151             default: break;
9152           }
9153         default: break;
9154       }
9155       theDI << "Mode " << aMode << "\n";
9156     }
9157     return 0;
9158   }
9159
9160   Handle(Graphic3d_Camera) aCamera;
9161   Graphic3d_RenderingParams*   aParams   = NULL;
9162   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
9163   if (!aView.IsNull())
9164   {
9165     aParams   = &aView->ChangeRenderingParams();
9166     aMode     = aParams->StereoMode;
9167     aCamera   = aView->Camera();
9168   }
9169
9170   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9171   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9172   {
9173     Standard_CString        anArg = theArgVec[anArgIter];
9174     TCollection_AsciiString aFlag (anArg);
9175     aFlag.LowerCase();
9176     if (anUpdateTool.parseRedrawMode (aFlag))
9177     {
9178       continue;
9179     }
9180     else if (aFlag == "0"
9181           || aFlag == "off")
9182     {
9183       if (++anArgIter < theArgNb)
9184       {
9185         std::cout << "Error: wrong number of arguments!\n";
9186         return 1;
9187       }
9188
9189       if (!aCamera.IsNull()
9190        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
9191       {
9192         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9193       }
9194       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
9195       return 0;
9196     }
9197     else if (aFlag == "1"
9198           || aFlag == "on")
9199     {
9200       if (++anArgIter < theArgNb)
9201       {
9202         std::cout << "Error: wrong number of arguments!\n";
9203         return 1;
9204       }
9205
9206       if (!aCamera.IsNull())
9207       {
9208         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9209       }
9210       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9211       return 0;
9212     }
9213     else if (aFlag == "-reverse"
9214           || aFlag == "-reversed"
9215           || aFlag == "-swap")
9216     {
9217       Standard_Boolean toEnable = Standard_True;
9218       if (++anArgIter < theArgNb
9219       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9220       {
9221         --anArgIter;
9222       }
9223       aParams->ToReverseStereo = toEnable;
9224     }
9225     else if (aFlag == "-noreverse"
9226           || aFlag == "-noswap")
9227     {
9228       Standard_Boolean toDisable = Standard_True;
9229       if (++anArgIter < theArgNb
9230       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9231       {
9232         --anArgIter;
9233       }
9234       aParams->ToReverseStereo = !toDisable;
9235     }
9236     else if (aFlag == "-mode"
9237           || aFlag == "-stereomode")
9238     {
9239       if (++anArgIter >= theArgNb
9240       || !parseStereoMode (theArgVec[anArgIter], aMode))
9241       {
9242         std::cout << "Error: syntax error at '" << anArg << "'\n";
9243         return 1;
9244       }
9245
9246       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9247       {
9248         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9249       }
9250     }
9251     else if (aFlag == "-anaglyph"
9252           || aFlag == "-anaglyphfilter")
9253     {
9254       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9255       if (++anArgIter >= theArgNb
9256       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9257       {
9258         std::cout << "Error: syntax error at '" << anArg << "'\n";
9259         return 1;
9260       }
9261
9262       aMode = Graphic3d_StereoMode_Anaglyph;
9263       aParams->AnaglyphFilter = aFilter;
9264     }
9265     else if (parseStereoMode (anArg, aMode)) // short syntax
9266     {
9267       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9268       {
9269         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9270       }
9271     }
9272     else
9273     {
9274       std::cout << "Error: syntax error at '" << anArg << "'\n";
9275       return 1;
9276     }
9277   }
9278
9279   if (!aView.IsNull())
9280   {
9281     aParams->StereoMode = aMode;
9282     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9283   }
9284   return 0;
9285 }
9286
9287 //===============================================================================================
9288 //function : VDefaults
9289 //purpose  :
9290 //===============================================================================================
9291 static int VDefaults (Draw_Interpretor& theDi,
9292                       Standard_Integer  theArgsNb,
9293                       const char**      theArgVec)
9294 {
9295   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9296   if (aCtx.IsNull())
9297   {
9298     std::cerr << "No active viewer!\n";
9299     return 1;
9300   }
9301
9302   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9303   if (theArgsNb < 2)
9304   {
9305     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9306     {
9307       theDi << "DeflType:           relative\n"
9308             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9309     }
9310     else
9311     {
9312       theDi << "DeflType:           absolute\n"
9313             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9314     }
9315     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9316     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9317     return 0;
9318   }
9319
9320   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9321   {
9322     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9323     anArg.UpperCase();
9324     if (anArg == "-ABSDEFL"
9325      || anArg == "-ABSOLUTEDEFLECTION"
9326      || anArg == "-DEFL"
9327      || anArg == "-DEFLECTION")
9328     {
9329       if (++anArgIter >= theArgsNb)
9330       {
9331         std::cout << "Error: wrong syntax at " << anArg << "\n";
9332         return 1;
9333       }
9334       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9335       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9336     }
9337     else if (anArg == "-RELDEFL"
9338           || anArg == "-RELATIVEDEFLECTION"
9339           || anArg == "-DEVCOEFF"
9340           || anArg == "-DEVIATIONCOEFF"
9341           || anArg == "-DEVIATIONCOEFFICIENT")
9342     {
9343       if (++anArgIter >= theArgsNb)
9344       {
9345         std::cout << "Error: wrong syntax at " << anArg << "\n";
9346         return 1;
9347       }
9348       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9349       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9350     }
9351     else if (anArg == "-ANGDEFL"
9352           || anArg == "-ANGULARDEFL"
9353           || anArg == "-ANGULARDEFLECTION")
9354     {
9355       if (++anArgIter >= theArgsNb)
9356       {
9357         std::cout << "Error: wrong syntax at " << anArg << "\n";
9358         return 1;
9359       }
9360       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9361       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9362     }
9363     else if (anArg == "-AUTOTR"
9364           || anArg == "-AUTOTRIANG"
9365           || anArg == "-AUTOTRIANGULATION")
9366     {
9367       if (++anArgIter >= theArgsNb)
9368       {
9369         std::cout << "Error: wrong syntax at " << anArg << "\n";
9370         return 1;
9371       }
9372       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9373       aValue.LowerCase();
9374       if (aValue == "on"
9375        || aValue == "1")
9376       {
9377         aDefParams->SetAutoTriangulation (Standard_True);
9378       }
9379       else if (aValue == "off"
9380             || aValue == "0")
9381       {
9382         aDefParams->SetAutoTriangulation (Standard_False);
9383       }
9384     }
9385     else
9386     {
9387       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9388     }
9389   }
9390
9391   return 0;
9392 }
9393
9394 //! Auxiliary method
9395 inline void addLight (const Handle(V3d_Light)& theLightNew,
9396                       const Graphic3d_ZLayerId theLayer,
9397                       const Standard_Boolean   theIsGlobal)
9398 {
9399   if (theLightNew.IsNull())
9400   {
9401     return;
9402   }
9403
9404   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9405   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
9406   {
9407     aViewer->AddLight (theLightNew);
9408     if (theIsGlobal)
9409     {
9410       aViewer->SetLightOn (theLightNew);
9411     }
9412     else
9413     {
9414       ViewerTest::CurrentView()->SetLightOn (theLightNew);
9415     }
9416   }
9417   else
9418   {
9419     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
9420     if (aSettings.Lights().IsNull())
9421     {
9422       aSettings.SetLights (new Graphic3d_LightSet());
9423     }
9424     aSettings.Lights()->Add (theLightNew);
9425     aViewer->SetZLayerSettings (theLayer, aSettings);
9426   }
9427 }
9428
9429 //! Auxiliary method
9430 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9431 {
9432   TCollection_AsciiString anArgNextCase (theArgNext);
9433   anArgNextCase.UpperCase();
9434   if (anArgNextCase.Length() > 5
9435    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9436   {
9437     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9438   }
9439   else
9440   {
9441     return theArgNext.IntegerValue();
9442   }
9443 }
9444
9445 //===============================================================================================
9446 //function : VLight
9447 //purpose  :
9448 //===============================================================================================
9449 static int VLight (Draw_Interpretor& theDi,
9450                    Standard_Integer  theArgsNb,
9451                    const char**      theArgVec)
9452 {
9453   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9454   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9455   if (aView.IsNull()
9456    || aViewer.IsNull())
9457   {
9458     std::cerr << "No active viewer!\n";
9459     return 1;
9460   }
9461
9462   Standard_Real anXYZ[3]   = {};
9463   Standard_Real anAtten[2] = {};
9464   if (theArgsNb < 2)
9465   {
9466     // print lights info
9467     Standard_Integer aLightId = 0;
9468     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9469     {
9470       Handle(V3d_Light) aLight = aLightIter.Value();
9471       const Quantity_Color aColor = aLight->Color();
9472       theDi << "Light #" << aLightId
9473             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
9474             << " [" << aLight->GetId() << "]" << "\n";
9475       switch (aLight->Type())
9476       {
9477         case V3d_AMBIENT:
9478         {
9479           theDi << "  Type:       Ambient\n";
9480           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9481           break;
9482         }
9483         case V3d_DIRECTIONAL:
9484         {
9485           theDi << "  Type:       Directional\n";
9486           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9487           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9488           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9489           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9490           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9491           break;
9492         }
9493         case V3d_POSITIONAL:
9494         {
9495           theDi << "  Type:       Positional\n";
9496           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9497           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9498           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9499           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9500           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9501           aLight->Attenuation (anAtten[0], anAtten[1]);
9502           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9503           break;
9504         }
9505         case V3d_SPOT:
9506         {
9507           theDi << "  Type:       Spot\n";
9508           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9509           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9510           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9511           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9512           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9513           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9514           aLight->Attenuation (anAtten[0], anAtten[1]);
9515           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9516           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
9517           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
9518           break;
9519         }
9520         default:
9521         {
9522           theDi << "  Type:       UNKNOWN\n";
9523           break;
9524         }
9525       }
9526       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
9527     }
9528   }
9529
9530   Handle(V3d_Light) aLightNew;
9531   Handle(V3d_Light) aLightOld;
9532   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
9533   Standard_Boolean  isGlobal = Standard_True;
9534   Standard_Boolean  toCreate = Standard_False;
9535   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9536   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9537   {
9538     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9539
9540     TCollection_AsciiString aName, aValue;
9541     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9542     TCollection_AsciiString anArgCase (anArg);
9543     anArgCase.UpperCase();
9544     if (anUpdateTool.parseRedrawMode (anArg))
9545     {
9546       continue;
9547     }
9548
9549     if (anArgCase.IsEqual ("NEW")
9550      || anArgCase.IsEqual ("ADD")
9551      || anArgCase.IsEqual ("CREATE")
9552      || anArgCase.IsEqual ("-NEW")
9553      || anArgCase.IsEqual ("-ADD")
9554      || anArgCase.IsEqual ("-CREATE"))
9555     {
9556       toCreate = Standard_True;
9557     }
9558     else if (anArgCase.IsEqual ("-LAYER")
9559           || anArgCase.IsEqual ("-ZLAYER"))
9560     {
9561       if (++anArgIt >= theArgsNb)
9562       {
9563         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9564         return 1;
9565       }
9566
9567       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
9568       aValStr.LowerCase();
9569       if (aValStr == "default"
9570        || aValStr == "def")
9571       {
9572         aLayer = Graphic3d_ZLayerId_Default;
9573       }
9574       else if (aValStr == "top")
9575       {
9576         aLayer = Graphic3d_ZLayerId_Top;
9577       }
9578       else if (aValStr == "topmost")
9579       {
9580         aLayer = Graphic3d_ZLayerId_Topmost;
9581       }
9582       else if (aValStr == "toposd"
9583             || aValStr == "osd")
9584       {
9585         aLayer = Graphic3d_ZLayerId_TopOSD;
9586       }
9587       else if (aValStr == "botosd"
9588             || aValStr == "bottom")
9589       {
9590         aLayer = Graphic3d_ZLayerId_BotOSD;
9591       }
9592       else if (aValStr.IsIntegerValue())
9593       {
9594         aLayer = Draw::Atoi (theArgVec[anArgIt]);
9595       }
9596       else
9597       {
9598         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
9599         return 1;
9600       }
9601     }
9602     else if (anArgCase.IsEqual ("GLOB")
9603           || anArgCase.IsEqual ("GLOBAL")
9604           || anArgCase.IsEqual ("-GLOB")
9605           || anArgCase.IsEqual ("-GLOBAL"))
9606     {
9607       isGlobal = Standard_True;
9608     }
9609     else if (anArgCase.IsEqual ("LOC")
9610           || anArgCase.IsEqual ("LOCAL")
9611           || anArgCase.IsEqual ("-LOC")
9612           || anArgCase.IsEqual ("-LOCAL"))
9613     {
9614       isGlobal = Standard_False;
9615     }
9616     else if (anArgCase.IsEqual ("DEF")
9617           || anArgCase.IsEqual ("DEFAULTS")
9618           || anArgCase.IsEqual ("-DEF")
9619           || anArgCase.IsEqual ("-DEFAULTS"))
9620     {
9621       toCreate = Standard_False;
9622       aViewer->SetDefaultLights();
9623     }
9624     else if (anArgCase.IsEqual ("CLR")
9625           || anArgCase.IsEqual ("CLEAR")
9626           || anArgCase.IsEqual ("-CLR")
9627           || anArgCase.IsEqual ("-CLEAR"))
9628     {
9629       toCreate = Standard_False;
9630
9631       TColStd_SequenceOfInteger aLayers;
9632       aViewer->GetAllZLayers (aLayers);
9633       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9634       {
9635         if (aLayeriter.Value() == aLayer
9636          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9637         {
9638           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9639           aSettings.SetLights (Handle(Graphic3d_LightSet)());
9640           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9641           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9642           {
9643             break;
9644           }
9645         }
9646       }
9647
9648       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9649       {
9650         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
9651         {
9652           Handle(V3d_Light) aLight = aLightIter.Value();
9653           aViewer->DelLight (aLight);
9654           aLightIter = aView->ActiveLightIterator();
9655         }
9656       }
9657     }
9658     else if (anArgCase.IsEqual ("AMB")
9659           || anArgCase.IsEqual ("AMBIENT")
9660           || anArgCase.IsEqual ("AMBLIGHT"))
9661     {
9662       if (!toCreate)
9663       {
9664         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9665         return 1;
9666       }
9667
9668       addLight (aLightNew, aLayer, isGlobal);
9669       toCreate  = Standard_False;
9670       aLightNew = new V3d_AmbientLight();
9671     }
9672     else if (anArgCase.IsEqual ("DIRECTIONAL")
9673           || anArgCase.IsEqual ("DIRLIGHT"))
9674     {
9675       if (!toCreate)
9676       {
9677         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9678         return 1;
9679       }
9680
9681       addLight (aLightNew, aLayer, isGlobal);
9682       toCreate  = Standard_False;
9683       aLightNew = new V3d_DirectionalLight();
9684     }
9685     else if (anArgCase.IsEqual ("SPOT")
9686           || anArgCase.IsEqual ("SPOTLIGHT"))
9687     {
9688       if (!toCreate)
9689       {
9690         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9691         return 1;
9692       }
9693
9694       addLight (aLightNew, aLayer, isGlobal);
9695       toCreate  = Standard_False;
9696       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
9697     }
9698     else if (anArgCase.IsEqual ("POSLIGHT")
9699           || anArgCase.IsEqual ("POSITIONAL"))
9700     {
9701       if (!toCreate)
9702       {
9703         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9704         return 1;
9705       }
9706
9707       addLight (aLightNew, aLayer, isGlobal);
9708       toCreate  = Standard_False;
9709       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
9710     }
9711     else if (anArgCase.IsEqual ("CHANGE")
9712           || anArgCase.IsEqual ("-CHANGE"))
9713     {
9714       if (++anArgIt >= theArgsNb)
9715       {
9716         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9717         return 1;
9718       }
9719
9720       addLight (aLightNew, aLayer, isGlobal);
9721       aLightNew.Nullify();
9722       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
9723       Standard_Integer aLightIt = 0;
9724       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9725       {
9726         if (aLightIt == aLightId)
9727         {
9728           aLightOld = aLightIter.Value();
9729           break;
9730         }
9731       }
9732
9733       if (aLightOld.IsNull())
9734       {
9735         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
9736         return 1;
9737       }
9738     }
9739     else if (anArgCase.IsEqual ("DEL")
9740           || anArgCase.IsEqual ("DELETE")
9741           || anArgCase.IsEqual ("-DEL")
9742           || anArgCase.IsEqual ("-DELETE"))
9743     {
9744       Handle(V3d_Light) aLightDel;
9745       if (++anArgIt >= theArgsNb)
9746       {
9747         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9748         return 1;
9749       }
9750
9751       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9752       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
9753       Standard_Integer aLightIt = 0;
9754       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9755       {
9756         aLightDel = aLightIter.Value();
9757         if (aLightIt == aLightDelId)
9758         {
9759           break;
9760         }
9761       }
9762       if (aLightDel.IsNull())
9763       {
9764         continue;
9765       }
9766
9767       TColStd_SequenceOfInteger aLayers;
9768       aViewer->GetAllZLayers (aLayers);
9769       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9770       {
9771         if (aLayeriter.Value() == aLayer
9772          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9773         {
9774           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9775           if (!aSettings.Lights().IsNull())
9776           {
9777             aSettings.Lights()->Remove (aLightDel);
9778             if (aSettings.Lights()->IsEmpty())
9779             {
9780               aSettings.SetLights (Handle(Graphic3d_LightSet)());
9781             }
9782           }
9783           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9784           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9785           {
9786             break;
9787           }
9788         }
9789       }
9790
9791       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9792       {
9793         aViewer->DelLight (aLightDel);
9794       }
9795     }
9796     else if (anArgCase.IsEqual ("COLOR")
9797           || anArgCase.IsEqual ("COLOUR")
9798           || anArgCase.IsEqual ("-COLOR")
9799           || anArgCase.IsEqual ("-COLOUR"))
9800     {
9801       if (++anArgIt >= theArgsNb
9802        || aLightCurr.IsNull())
9803       {
9804         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9805         return 1;
9806       }
9807
9808       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9809       anArgNext.UpperCase();
9810       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
9811       aLightCurr->SetColor (aColor);
9812     }
9813     else if (anArgCase.IsEqual ("POS")
9814           || anArgCase.IsEqual ("POSITION")
9815           || anArgCase.IsEqual ("-POS")
9816           || anArgCase.IsEqual ("-POSITION"))
9817     {
9818       if ((anArgIt + 3) >= theArgsNb
9819        || aLightCurr.IsNull()
9820        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9821         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9822       {
9823         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9824         return 1;
9825       }
9826
9827       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9828       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9829       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9830       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9831     }
9832     else if (anArgCase.IsEqual ("DIR")
9833           || anArgCase.IsEqual ("DIRECTION")
9834           || anArgCase.IsEqual ("-DIR")
9835           || anArgCase.IsEqual ("-DIRECTION"))
9836     {
9837       if ((anArgIt + 3) >= theArgsNb
9838        || aLightCurr.IsNull()
9839        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
9840         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9841       {
9842         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9843         return 1;
9844       }
9845
9846       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9847       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9848       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9849       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9850     }
9851     else if (anArgCase.IsEqual ("SM")
9852           || anArgCase.IsEqual ("SMOOTHNESS")
9853           || anArgCase.IsEqual ("-SM")
9854           || anArgCase.IsEqual ("-SMOOTHNESS"))
9855     {
9856       if (++anArgIt >= theArgsNb
9857        || aLightCurr.IsNull())
9858       {
9859         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9860         return 1;
9861       }
9862
9863       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9864       if (Abs (aSmoothness) <= ShortRealEpsilon())
9865       {
9866         aLightCurr->SetIntensity (1.f);
9867       }
9868       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
9869       {
9870         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
9871       }
9872       else
9873       {
9874         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
9875         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
9876       }
9877
9878       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
9879       {
9880         aLightCurr->SetSmoothRadius (aSmoothness);
9881       }
9882       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
9883       {
9884         aLightCurr->SetSmoothAngle (aSmoothness);
9885       }
9886     }
9887     else if (anArgCase.IsEqual ("INT")
9888           || anArgCase.IsEqual ("INTENSITY")
9889           || anArgCase.IsEqual ("-INT")
9890           || anArgCase.IsEqual ("-INTENSITY"))
9891     {
9892       if (++anArgIt >= theArgsNb
9893        || aLightCurr.IsNull())
9894       {
9895         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9896         return 1;
9897       }
9898
9899       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9900       aLightCurr->SetIntensity (aIntensity);
9901     }
9902     else if (anArgCase.IsEqual ("ANG")
9903           || anArgCase.IsEqual ("ANGLE")
9904           || anArgCase.IsEqual ("-ANG")
9905           || anArgCase.IsEqual ("-ANGLE"))
9906     {
9907       if (++anArgIt >= theArgsNb
9908        || aLightCurr.IsNull()
9909        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
9910       {
9911         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9912         return 1;
9913       }
9914
9915       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9916       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
9917     }
9918     else if (anArgCase.IsEqual ("CONSTATTEN")
9919           || anArgCase.IsEqual ("CONSTATTENUATION")
9920           || anArgCase.IsEqual ("-CONSTATTEN")
9921           || anArgCase.IsEqual ("-CONSTATTENUATION"))
9922     {
9923       if (++anArgIt >= theArgsNb
9924        || aLightCurr.IsNull()
9925        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9926         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9927       {
9928         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9929         return 1;
9930       }
9931
9932       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
9933       anAtten[0] = Atof (theArgVec[anArgIt]);
9934       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
9935     }
9936     else if (anArgCase.IsEqual ("LINATTEN")
9937           || anArgCase.IsEqual ("LINEARATTEN")
9938           || anArgCase.IsEqual ("LINEARATTENUATION")
9939           || anArgCase.IsEqual ("-LINATTEN")
9940           || anArgCase.IsEqual ("-LINEARATTEN")
9941           || anArgCase.IsEqual ("-LINEARATTENUATION"))
9942     {
9943       if (++anArgIt >= theArgsNb
9944        || aLightCurr.IsNull()
9945        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9946         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9947       {
9948         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9949         return 1;
9950       }
9951
9952       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
9953       anAtten[1] = Atof (theArgVec[anArgIt]);
9954       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
9955     }
9956     else if (anArgCase.IsEqual ("EXP")
9957           || anArgCase.IsEqual ("EXPONENT")
9958           || anArgCase.IsEqual ("SPOTEXP")
9959           || anArgCase.IsEqual ("SPOTEXPONENT")
9960           || anArgCase.IsEqual ("-EXP")
9961           || anArgCase.IsEqual ("-EXPONENT")
9962           || anArgCase.IsEqual ("-SPOTEXP")
9963           || anArgCase.IsEqual ("-SPOTEXPONENT"))
9964     {
9965       if (++anArgIt >= theArgsNb
9966        || aLightCurr.IsNull()
9967        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
9968       {
9969         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9970         return 1;
9971       }
9972
9973       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
9974     }
9975     else if (anArgCase.IsEqual ("HEAD")
9976           || anArgCase.IsEqual ("HEADLIGHT")
9977           || anArgCase.IsEqual ("-HEAD")
9978           || anArgCase.IsEqual ("-HEADLIGHT"))
9979     {
9980       if (aLightCurr.IsNull()
9981        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
9982       {
9983         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9984         return 1;
9985       }
9986
9987       Standard_Boolean isHeadLight = Standard_True;
9988       if (anArgIt + 1 < theArgsNb
9989        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
9990       {
9991         ++anArgIt;
9992       }
9993       aLightCurr->SetHeadlight (isHeadLight);
9994     }
9995     else
9996     {
9997       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9998     }
9999   }
10000
10001   addLight (aLightNew, aLayer, isGlobal);
10002   return 0;
10003 }
10004
10005 //! Read Graphic3d_RenderingParams::PerfCounters flag.
10006 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10007                                             Standard_Boolean& theToReset,
10008                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10009                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10010 {
10011   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10012   TCollection_AsciiString aVal = theValue;
10013   Standard_Boolean toReverse = Standard_False;
10014   if (aVal == "none")
10015   {
10016     theToReset = Standard_True;
10017     return Standard_True;
10018   }
10019   else if (aVal.StartsWith ("-"))
10020   {
10021     toReverse = Standard_True;
10022     aVal = aVal.SubString (2, aVal.Length());
10023   }
10024   else if (aVal.StartsWith ("no"))
10025   {
10026     toReverse = Standard_True;
10027     aVal = aVal.SubString (3, aVal.Length());
10028   }
10029   else if (aVal.StartsWith ("+"))
10030   {
10031     aVal = aVal.SubString (2, aVal.Length());
10032   }
10033   else
10034   {
10035     theToReset = Standard_True;
10036   }
10037
10038   if (     aVal == "fps"
10039         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
10040   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
10041   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
10042   else if (aVal == "structs"
10043         || aVal == "structures"
10044         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
10045   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
10046   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
10047   else if (aVal == "tris"
10048         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
10049   else if (aVal == "pnts"
10050         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
10051   else if (aVal == "mem"
10052         || aVal == "gpumem"
10053         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
10054   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
10055   else if (aVal == "extended"
10056         || aVal == "verbose"
10057         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
10058   else
10059   {
10060     return Standard_False;
10061   }
10062
10063   if (toReverse)
10064   {
10065     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
10066   }
10067   else
10068   {
10069     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
10070   }
10071   return Standard_True;
10072 }
10073
10074 //! Read Graphic3d_RenderingParams::PerfCounters flags.
10075 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
10076                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
10077 {
10078   TCollection_AsciiString aValue = theValue;
10079   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
10080   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
10081   Standard_Boolean toReset = Standard_False;
10082   for (;;)
10083   {
10084     Standard_Integer aSplitPos = aValue.Search ("|");
10085     if (aSplitPos <= 0)
10086     {
10087       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
10088       {
10089         return Standard_False;
10090       }
10091       if (toReset)
10092       {
10093         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
10094       }
10095       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
10096       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
10097       return Standard_True;
10098     }
10099
10100     if (aSplitPos > 1)
10101     {
10102       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
10103       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
10104       {
10105         return Standard_False;
10106       }
10107     }
10108     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
10109   }
10110 }
10111
10112 //=======================================================================
10113 //function : VRenderParams
10114 //purpose  : Enables/disables rendering features
10115 //=======================================================================
10116
10117 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
10118                                        Standard_Integer  theArgNb,
10119                                        const char**      theArgVec)
10120 {
10121   Handle(V3d_View) aView = ViewerTest::CurrentView();
10122   if (aView.IsNull())
10123   {
10124     std::cerr << "Error: no active viewer!\n";
10125     return 1;
10126   }
10127
10128   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
10129   TCollection_AsciiString aCmdName (theArgVec[0]);
10130   aCmdName.LowerCase();
10131   if (aCmdName == "vraytrace")
10132   {
10133     if (theArgNb == 1)
10134     {
10135       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
10136       return 0;
10137     }
10138     else if (theArgNb == 2)
10139     {
10140       TCollection_AsciiString aValue (theArgVec[1]);
10141       aValue.LowerCase();
10142       if (aValue == "on"
10143        || aValue == "1")
10144       {
10145         aParams.Method = Graphic3d_RM_RAYTRACING;
10146         aView->Redraw();
10147         return 0;
10148       }
10149       else if (aValue == "off"
10150             || aValue == "0")
10151       {
10152         aParams.Method = Graphic3d_RM_RASTERIZATION;
10153         aView->Redraw();
10154         return 0;
10155       }
10156       else
10157       {
10158         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
10159         return 1;
10160       }
10161     }
10162     else
10163     {
10164       std::cout << "Error: wrong number of arguments\n";
10165       return 1;
10166     }
10167   }
10168
10169   if (theArgNb < 2)
10170   {
10171     theDI << "renderMode:  ";
10172     switch (aParams.Method)
10173     {
10174       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10175       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
10176     }
10177     theDI << "\n";
10178     theDI << "transparency:  ";
10179     switch (aParams.TransparencyMethod)
10180     {
10181       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
10182       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
10183                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
10184     }
10185     theDI << "\n";
10186     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
10187     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
10188     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
10189     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
10190     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
10191     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
10192     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
10193     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
10194     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
10195     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
10196     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
10197     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
10198     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
10199     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
10200     theDI << "shadingModel: ";
10201     switch (aView->ShadingModel())
10202     {
10203       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
10204       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
10205       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
10206       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
10207       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
10208     }
10209     {
10210       theDI << "perfCounters:";
10211       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
10212       {
10213         theDI << " fps";
10214       }
10215       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
10216       {
10217         theDI << " cpu";
10218       }
10219       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
10220       {
10221         theDI << " structs";
10222       }
10223       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
10224       {
10225         theDI << " groups";
10226       }
10227       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
10228       {
10229         theDI << " arrays";
10230       }
10231       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
10232       {
10233         theDI << " tris";
10234       }
10235       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
10236       {
10237         theDI << " pnts";
10238       }
10239       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
10240       {
10241         theDI << " gpumem";
10242       }
10243       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
10244       {
10245         theDI << " none";
10246       }
10247       theDI << "\n";
10248     }
10249     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
10250     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
10251     theDI << "\n";
10252     return 0;
10253   }
10254
10255   Standard_Boolean toPrint = Standard_False;
10256   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10257   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10258   {
10259     Standard_CString        anArg (theArgVec[anArgIter]);
10260     TCollection_AsciiString aFlag (anArg);
10261     aFlag.LowerCase();
10262     if (anUpdateTool.parseRedrawMode (aFlag))
10263     {
10264       continue;
10265     }
10266     else if (aFlag == "-echo"
10267           || aFlag == "-print")
10268     {
10269       toPrint = Standard_True;
10270       anUpdateTool.Invalidate();
10271     }
10272     else if (aFlag == "-mode"
10273           || aFlag == "-rendermode"
10274           || aFlag == "-render_mode")
10275     {
10276       if (toPrint)
10277       {
10278         switch (aParams.Method)
10279         {
10280           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10281           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
10282         }
10283         continue;
10284       }
10285       else
10286       {
10287         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10288         return 1;
10289       }
10290     }
10291     else if (aFlag == "-ray"
10292           || aFlag == "-raytrace")
10293     {
10294       if (toPrint)
10295       {
10296         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
10297         continue;
10298       }
10299
10300       aParams.Method = Graphic3d_RM_RAYTRACING;
10301     }
10302     else if (aFlag == "-rast"
10303           || aFlag == "-raster"
10304           || aFlag == "-rasterization")
10305     {
10306       if (toPrint)
10307       {
10308         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
10309         continue;
10310       }
10311
10312       aParams.Method = Graphic3d_RM_RASTERIZATION;
10313     }
10314     else if (aFlag == "-msaa")
10315     {
10316       if (toPrint)
10317       {
10318         theDI << aParams.NbMsaaSamples << " ";
10319         continue;
10320       }
10321       else if (++anArgIter >= theArgNb)
10322       {
10323         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10324         return 1;
10325       }
10326
10327       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
10328       if (aNbSamples < 0)
10329       {
10330         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
10331         return 1;
10332       }
10333       else
10334       {
10335         aParams.NbMsaaSamples = aNbSamples;
10336       }
10337     }
10338     else if (aFlag == "-oit")
10339     {
10340       if (toPrint)
10341       {
10342         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
10343         {
10344           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
10345         }
10346         else
10347         {
10348           theDI << "off" << " ";
10349         }
10350         continue;
10351       }
10352       else if (++anArgIter >= theArgNb)
10353       {
10354         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10355         return 1;
10356       }
10357
10358       TCollection_AsciiString aParam = theArgVec[anArgIter];
10359       aParam.LowerCase();
10360       if (aParam.IsRealValue())
10361       {
10362         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10363         if (aWeight < 0.f || aWeight > 1.f)
10364         {
10365           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
10366           return 1;
10367         }
10368
10369         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
10370         aParams.OitDepthFactor     = aWeight;
10371       }
10372       else if (aParam == "off")
10373       {
10374         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
10375       }
10376       else
10377       {
10378         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10379         return 1;
10380       }
10381     }
10382     else if (aFlag == "-depthprepass")
10383     {
10384       if (toPrint)
10385       {
10386         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
10387         continue;
10388       }
10389       aParams.ToEnableDepthPrepass = Standard_True;
10390       if (anArgIter + 1 < theArgNb
10391        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
10392       {
10393         ++anArgIter;
10394       }
10395     }
10396     else if (aFlag == "-samplealphatocoverage"
10397           || aFlag == "-alphatocoverage")
10398     {
10399       if (toPrint)
10400       {
10401         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
10402         continue;
10403       }
10404       aParams.ToEnableAlphaToCoverage = Standard_True;
10405       if (anArgIter + 1 < theArgNb
10406        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
10407       {
10408         ++anArgIter;
10409       }
10410     }
10411     else if (aFlag == "-rendscale"
10412           || aFlag == "-renderscale"
10413           || aFlag == "-renderresolutionscale")
10414     {
10415       if (toPrint)
10416       {
10417         theDI << aParams.RenderResolutionScale << " ";
10418         continue;
10419       }
10420       else if (++anArgIter >= theArgNb)
10421       {
10422         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10423         return 1;
10424       }
10425
10426       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
10427       if (aScale < 0.01)
10428       {
10429         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
10430         return 1;
10431       }
10432       else
10433       {
10434         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
10435       }
10436     }
10437     else if (aFlag == "-raydepth"
10438           || aFlag == "-ray_depth")
10439     {
10440       if (toPrint)
10441       {
10442         theDI << aParams.RaytracingDepth << " ";
10443         continue;
10444       }
10445       else if (++anArgIter >= theArgNb)
10446       {
10447         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10448         return 1;
10449       }
10450
10451       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
10452
10453       // We allow RaytracingDepth be more than 10 in case of GI enabled
10454       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
10455       {
10456         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
10457         return 1;
10458       }
10459       else
10460       {
10461         aParams.RaytracingDepth = aDepth;
10462       }
10463     }
10464     else if (aFlag == "-shad"
10465           || aFlag == "-shadows")
10466     {
10467       if (toPrint)
10468       {
10469         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
10470         continue;
10471       }
10472
10473       Standard_Boolean toEnable = Standard_True;
10474       if (++anArgIter < theArgNb
10475       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10476       {
10477         --anArgIter;
10478       }
10479       aParams.IsShadowEnabled = toEnable;
10480     }
10481     else if (aFlag == "-refl"
10482           || aFlag == "-reflections")
10483     {
10484       if (toPrint)
10485       {
10486         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10487         continue;
10488       }
10489
10490       Standard_Boolean toEnable = Standard_True;
10491       if (++anArgIter < theArgNb
10492       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10493       {
10494         --anArgIter;
10495       }
10496       aParams.IsReflectionEnabled = toEnable;
10497     }
10498     else if (aFlag == "-fsaa")
10499     {
10500       if (toPrint)
10501       {
10502         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10503         continue;
10504       }
10505
10506       Standard_Boolean toEnable = Standard_True;
10507       if (++anArgIter < theArgNb
10508       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10509       {
10510         --anArgIter;
10511       }
10512       aParams.IsAntialiasingEnabled = toEnable;
10513     }
10514     else if (aFlag == "-gleam")
10515     {
10516       if (toPrint)
10517       {
10518         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10519         continue;
10520       }
10521
10522       Standard_Boolean toEnable = Standard_True;
10523       if (++anArgIter < theArgNb
10524       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10525       {
10526         --anArgIter;
10527       }
10528       aParams.IsTransparentShadowEnabled = toEnable;
10529     }
10530     else if (aFlag == "-gi")
10531     {
10532       if (toPrint)
10533       {
10534         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10535         continue;
10536       }
10537
10538       Standard_Boolean toEnable = Standard_True;
10539       if (++anArgIter < theArgNb
10540       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10541       {
10542         --anArgIter;
10543       }
10544       aParams.IsGlobalIlluminationEnabled = toEnable;
10545       if (!toEnable)
10546       {
10547         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10548       }
10549     }
10550     else if (aFlag == "-blockedrng"
10551           || aFlag == "-brng")
10552     {
10553       if (toPrint)
10554       {
10555         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10556         continue;
10557       }
10558
10559       Standard_Boolean toEnable = Standard_True;
10560       if (++anArgIter < theArgNb
10561         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10562       {
10563         --anArgIter;
10564       }
10565       aParams.CoherentPathTracingMode = toEnable;
10566     }
10567     else if (aFlag == "-maxrad")
10568     {
10569       if (toPrint)
10570       {
10571         theDI << aParams.RadianceClampingValue << " ";
10572         continue;
10573       }
10574       else if (++anArgIter >= theArgNb)
10575       {
10576         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10577         return 1;
10578       }
10579
10580       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10581       if (!aMaxRadStr.IsRealValue())
10582       {
10583         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10584         return 1;
10585       }
10586
10587       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10588       if (aMaxRadiance <= 0.0)
10589       {
10590         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10591         return 1;
10592       }
10593       else
10594       {
10595         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
10596       }
10597     }
10598     else if (aFlag == "-iss")
10599     {
10600       if (toPrint)
10601       {
10602         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
10603         continue;
10604       }
10605
10606       Standard_Boolean toEnable = Standard_True;
10607       if (++anArgIter < theArgNb
10608         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10609       {
10610         --anArgIter;
10611       }
10612       aParams.AdaptiveScreenSampling = toEnable;
10613     }
10614     else if (aFlag == "-issd")
10615     {
10616       if (toPrint)
10617       {
10618         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
10619         continue;
10620       }
10621
10622       Standard_Boolean toEnable = Standard_True;
10623       if (++anArgIter < theArgNb
10624         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10625       {
10626         --anArgIter;
10627       }
10628       aParams.ShowSamplingTiles = toEnable;
10629     }
10630     else if (aFlag == "-nbtiles")
10631     {
10632       if (toPrint)
10633       {
10634         theDI << aParams.NbRayTracingTiles << " ";
10635         continue;
10636       }
10637       else if (++anArgIter >= theArgNb)
10638       {
10639         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10640         return 1;
10641       }
10642
10643       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
10644
10645       if (aNbTiles < 64)
10646       {
10647         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
10648         std::cerr << "Specify value in range [64, 1024].\n";
10649         return 1;
10650       }
10651       else
10652       {
10653         aParams.NbRayTracingTiles = aNbTiles;
10654       }
10655     }
10656     else if (aFlag == "-env")
10657     {
10658       if (toPrint)
10659       {
10660         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
10661         continue;
10662       }
10663
10664       Standard_Boolean toEnable = Standard_True;
10665       if (++anArgIter < theArgNb
10666         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10667       {
10668         --anArgIter;
10669       }
10670       aParams.UseEnvironmentMapBackground = toEnable;
10671     }
10672     else if (aFlag == "-twoside")
10673     {
10674       if (toPrint)
10675       {
10676         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
10677         continue;
10678       }
10679
10680       Standard_Boolean toEnable = Standard_True;
10681       if (++anArgIter < theArgNb
10682         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10683       {
10684         --anArgIter;
10685       }
10686       aParams.TwoSidedBsdfModels = toEnable;
10687     }
10688     else if (aFlag == "-shademodel"
10689           || aFlag == "-shadingmodel"
10690           || aFlag == "-shading")
10691     {
10692       if (toPrint)
10693       {
10694         switch (aView->ShadingModel())
10695         {
10696           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
10697           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
10698           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
10699           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
10700           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
10701         }
10702         continue;
10703       }
10704
10705       if (++anArgIter >= theArgNb)
10706       {
10707         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10708       }
10709
10710       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
10711       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
10712        && aModel != Graphic3d_TOSM_DEFAULT)
10713       {
10714         aView->SetShadingModel (aModel);
10715       }
10716       else
10717       {
10718         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
10719         return 1;
10720       }
10721     }
10722     else if (aFlag == "-resolution")
10723     {
10724       if (++anArgIter >= theArgNb)
10725       {
10726         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10727         return 1;
10728       }
10729
10730       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
10731       if (aResolution.IsIntegerValue())
10732       {
10733         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
10734       }
10735       else
10736       {
10737         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10738         return 1;
10739       }
10740     }
10741     else if (aFlag == "-rebuildglsl"
10742           || aFlag == "-rebuild")
10743     {
10744       if (toPrint)
10745       {
10746         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
10747         continue;
10748       }
10749
10750       Standard_Boolean toEnable = Standard_True;
10751       if (++anArgIter < theArgNb
10752           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10753       {
10754         --anArgIter;
10755       }
10756       aParams.RebuildRayTracingShaders = toEnable;
10757     }
10758     else if (aFlag == "-focal")
10759     {
10760       if (++anArgIter >= theArgNb)
10761       {
10762         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10763         return 1;
10764       }
10765
10766       TCollection_AsciiString aParam (theArgVec[anArgIter]);
10767       if (aParam.IsRealValue())
10768       {
10769         float aFocalDist = static_cast<float> (aParam.RealValue());
10770         if (aFocalDist < 0)
10771         {
10772           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10773           return 1;
10774         }
10775         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
10776       }
10777       else
10778       {
10779         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10780         return 1;
10781       }
10782     }
10783     else if (aFlag == "-aperture")
10784     {
10785       if (++anArgIter >= theArgNb)
10786       {
10787         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10788         return 1;
10789       }
10790
10791       TCollection_AsciiString aParam(theArgVec[anArgIter]);
10792       if (aParam.IsRealValue())
10793       {
10794         float aApertureSize = static_cast<float> (aParam.RealValue());
10795         if (aApertureSize < 0)
10796         {
10797           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10798           return 1;
10799         }
10800         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
10801       }
10802       else
10803       {
10804         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10805         return 1;
10806       }
10807     }
10808     else if (aFlag == "-exposure")
10809     {
10810       if (++anArgIter >= theArgNb)
10811       {
10812         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10813         return 1;
10814       }
10815
10816       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
10817       if (anExposure.IsRealValue())
10818       {
10819         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
10820       }
10821       else
10822       {
10823         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10824         return 1;
10825       }
10826     }
10827     else if (aFlag == "-whitepoint")
10828     {
10829       if (++anArgIter >= theArgNb)
10830       {
10831         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10832         return 1;
10833       }
10834
10835       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
10836       if (aWhitePoint.IsRealValue())
10837       {
10838         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
10839       }
10840       else
10841       {
10842         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10843         return 1;
10844       }
10845     }
10846     else if (aFlag == "-tonemapping")
10847     {
10848       if (++anArgIter >= theArgNb)
10849       {
10850         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10851         return 1;
10852       }
10853
10854       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10855       aMode.LowerCase();
10856
10857       if (aMode == "disabled")
10858       {
10859         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
10860       }
10861       else if (aMode == "filmic")
10862       {
10863         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
10864       }
10865       else
10866       {
10867         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10868         return 1;
10869       }
10870     }
10871     else if (aFlag == "-performancestats"
10872           || aFlag == "-performancecounters"
10873           || aFlag == "-perfstats"
10874           || aFlag == "-perfcounters"
10875           || aFlag == "-stats")
10876     {
10877       if (++anArgIter >= theArgNb)
10878       {
10879         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10880         return 1;
10881       }
10882
10883       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
10884       aFlagsStr.LowerCase();
10885       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
10886       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
10887       {
10888         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10889         return 1;
10890       }
10891       aView->ChangeRenderingParams().CollectedStats = aFlags;
10892       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
10893     }
10894     else if (aFlag == "-perfupdateinterval"
10895           || aFlag == "-statsupdateinterval")
10896     {
10897       if (++anArgIter >= theArgNb)
10898       {
10899         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10900         return 1;
10901       }
10902       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
10903     }
10904     else
10905     {
10906       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
10907       return 1;
10908     }
10909   }
10910
10911   return 0;
10912 }
10913
10914 //=======================================================================
10915 //function : VProgressiveMode
10916 //purpose  :
10917 //=======================================================================
10918 #if defined(_WIN32)
10919 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
10920                                           Standard_Integer  /*theNbArgs*/,
10921                                           const char**      /*theArgs*/)
10922 {
10923   Handle(V3d_View) aView = ViewerTest::CurrentView();
10924   if (aView.IsNull())
10925   {
10926     std::cerr << "Error: no active viewer!\n";
10927     return 1;
10928   }
10929
10930   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
10931
10932   for (;;)
10933   {
10934     aView->Redraw();
10935
10936     Standard_Boolean toExit = Standard_False;
10937
10938     MSG aMsg;
10939     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
10940     {
10941       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
10942       {
10943         toExit = Standard_True;
10944       }
10945
10946       TranslateMessage (&aMsg);
10947       DispatchMessageW (&aMsg);
10948     }
10949
10950     if (toExit)
10951     {
10952       break;
10953     }
10954   }
10955
10956   return 0;
10957 }
10958 #endif
10959
10960 //=======================================================================
10961 //function : VFrustumCulling
10962 //purpose  : enables/disables view volume's culling.
10963 //=======================================================================
10964 static int VFrustumCulling (Draw_Interpretor& theDI,
10965                             Standard_Integer  theArgNb,
10966                             const char**      theArgVec)
10967 {
10968   Handle(V3d_View) aView = ViewerTest::CurrentView();
10969   if (aView.IsNull())
10970   {
10971     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
10972     return 1;
10973   }
10974
10975   if (theArgNb < 2)
10976   {
10977     theDI << (aView->IsCullingEnabled() ? "on" : "off");
10978     return 0;
10979   }
10980   else if (theArgNb != 2)
10981   {
10982     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
10983     return 1;
10984   }
10985
10986   TCollection_AsciiString aModeStr (theArgVec[1]);
10987   aModeStr.LowerCase();
10988   Standard_Boolean toEnable = 0;
10989   if (aModeStr == "on")
10990   {
10991     toEnable = 1;
10992   }
10993   else if (aModeStr == "off")
10994   {
10995     toEnable = 0;
10996   }
10997   else
10998   {
10999     toEnable = Draw::Atoi (theArgVec[1]) != 0;
11000   }
11001
11002   aView->SetFrustumCulling (toEnable);
11003   aView->Redraw();
11004   return 0;
11005 }
11006
11007 //=======================================================================
11008 //function : VHighlightSelected
11009 //purpose  : 
11010 //=======================================================================
11011 static int VHighlightSelected (Draw_Interpretor& theDI,
11012                                Standard_Integer  theArgNb,
11013                                const char**      theArgVec)
11014 {
11015   if (ViewerTest::GetAISContext().IsNull())
11016   {
11017     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
11018     return 1;
11019   }
11020
11021   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
11022
11023   if (theArgNb < 2)
11024   {
11025     theDI << (aContext->ToHilightSelected() ? "on" : "off");
11026     return 0;
11027   }
11028
11029   if (theArgNb != 2)
11030   {
11031     std::cout  << theArgVec[0] << " error : wrong number of parameters."
11032           << "Type 'help" << theArgVec[0] << "' for more information.";
11033     return 1;
11034   }
11035
11036   // Parse parameter
11037   TCollection_AsciiString aMode (theArgVec[1]);
11038   aMode.LowerCase();
11039   Standard_Boolean toEnable = Standard_False;
11040   if (aMode.IsEqual ("on"))
11041   {
11042     toEnable = Standard_True;
11043   }
11044   else if (aMode.IsEqual ("off"))
11045   {
11046     toEnable = Standard_False;
11047   }
11048   else
11049   {
11050     toEnable = Draw::Atoi (theArgVec[1]) != 0;
11051   }
11052
11053   if (toEnable != aContext->ToHilightSelected())
11054   {
11055     aContext->SetToHilightSelected (toEnable);
11056
11057     // Move cursor to null position and  back to process updating of detection
11058     // and highlighting of selected object immediatly.
11059     Standard_Integer aPixX = 0;
11060     Standard_Integer aPixY = 0;
11061     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
11062
11063     anEventManager->GetCurrentPosition (aPixX, aPixY);
11064     anEventManager->MoveTo (0, 0);
11065     anEventManager->MoveTo (aPixX, aPixY);
11066   }
11067
11068   return 0;
11069 }
11070
11071 //=======================================================================
11072 //function : VXRotate
11073 //purpose  :
11074 //=======================================================================
11075 static Standard_Integer VXRotate (Draw_Interpretor& di,
11076                                    Standard_Integer argc,
11077                                    const char ** argv)
11078 {
11079   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
11080   if (aContext.IsNull())
11081   {
11082     di << argv[0] << "ERROR : use 'vinit' command before \n";
11083     return 1;
11084   }
11085   
11086   if (argc != 3)
11087   {
11088     di << "ERROR : Usage : " << argv[0] << " name angle\n";
11089     return 1;
11090   }
11091
11092   TCollection_AsciiString aName (argv[1]);
11093   Standard_Real anAngle = Draw::Atof (argv[2]);
11094
11095   // find object
11096   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
11097   Handle(AIS_InteractiveObject) anIObj;
11098   if (!aMap.IsBound2 (aName) )
11099   {
11100     di << "Use 'vdisplay' before\n";
11101     return 1;
11102   }
11103   else
11104   {
11105     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
11106
11107     gp_Trsf aTransform;
11108     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
11109     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
11110
11111     aContext->SetLocation (anIObj, aTransform);
11112     aContext->UpdateCurrentViewer();
11113   }
11114
11115   return 0;
11116 }
11117
11118 //===============================================================================================
11119 //class   : ViewerTest_AISManipulator
11120 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
11121 //===============================================================================================
11122 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11123
11124 class ViewerTest_AISManipulator : public AIS_Manipulator
11125 {
11126 public:
11127
11128   ViewerTest_AISManipulator() : AIS_Manipulator()
11129   {
11130     GetMapOfAISManipulators().Add (this);
11131   }
11132
11133   virtual ~ViewerTest_AISManipulator()
11134   {
11135     GetMapOfAISManipulators().Remove (this);
11136   }
11137
11138   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11139 };
11140
11141 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11142 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11143
11144 //===============================================================================================
11145 //function : VManipulator
11146 //purpose  :
11147 //===============================================================================================
11148 static int VManipulator (Draw_Interpretor& theDi,
11149                          Standard_Integer  theArgsNb,
11150                          const char**      theArgVec)
11151 {
11152   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
11153   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
11154   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
11155   if (aView.IsNull()
11156    || aViewer.IsNull())
11157   {
11158     std::cerr << "No active viewer!\n";
11159     return 1;
11160   }
11161
11162   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
11163   Standard_Integer anArgIter = 1;
11164   for (; anArgIter < theArgsNb; ++anArgIter)
11165   {
11166     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
11167   }
11168
11169   ViewerTest_CmdParser aCmd;
11170   aCmd.AddDescription ("Manages manipulator for interactive objects:");
11171   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
11172   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
11173   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
11174   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
11175   aCmd.AddOption ("detach",         "...       - detach manipulator");
11176
11177   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
11178   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
11179   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
11180
11181   aCmd.AddOption ("move",   "... x y z - move object");
11182   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
11183   aCmd.AddOption ("scale",  "... factor - scale object");
11184
11185   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
11186   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
11187   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
11188   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
11189   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
11190   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
11191   aCmd.AddOption ("size",              "... size - set size of manipulator");
11192   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
11193
11194   aCmd.Parse (theArgsNb, theArgVec);
11195
11196   if (aCmd.HasOption ("help"))
11197   {
11198     theDi.PrintHelp (theArgVec[0]);
11199     return 0;
11200   }
11201
11202   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
11203
11204   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
11205
11206   if (aName.IsEmpty())
11207   {
11208     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
11209     return 1;
11210   }
11211
11212   // ----------------------------------
11213   // detach existing manipulator object
11214   // ----------------------------------
11215
11216   if (aCmd.HasOption ("detach"))
11217   {
11218     if (!aMapAIS.IsBound2 (aName))
11219     {
11220       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
11221       return 1;
11222     }
11223
11224     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11225     if (aManipulator.IsNull())
11226     {
11227       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11228       return 1;
11229     }
11230
11231     aManipulator->Detach();
11232     aMapAIS.UnBind2 (aName);
11233     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
11234
11235     return 0;
11236   }
11237
11238   // -----------------------------------------------
11239   // find or create manipulator if it does not exist
11240   // -----------------------------------------------
11241
11242   Handle(AIS_Manipulator) aManipulator;
11243   if (!aMapAIS.IsBound2 (aName))
11244   {
11245     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
11246
11247     aManipulator = new ViewerTest_AISManipulator();
11248     aMapAIS.Bind (aManipulator, aName);
11249   }
11250   else
11251   {
11252     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11253     if (aManipulator.IsNull())
11254     {
11255       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11256       return 1;
11257     }
11258   }
11259
11260   // -----------------------------------------
11261   // change properties of manipulator instance
11262   // -----------------------------------------
11263
11264   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
11265   {
11266     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
11267   }
11268   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
11269   {
11270     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
11271   }
11272   if (aCmd.HasOption ("followRotation", 1, Standard_True))
11273   {
11274     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
11275   }
11276   if (aCmd.HasOption ("gap", 1, Standard_True))
11277   {
11278     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
11279   }
11280   if (aCmd.HasOption ("part", 3, Standard_True))
11281   {
11282     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
11283     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
11284     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
11285     if (aMode < 1 || aMode > 3)
11286     {
11287       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
11288       return 1;
11289     }
11290
11291     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
11292   }
11293   if (aCmd.HasOption ("pos", 3, Standard_True))
11294   {
11295     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
11296     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
11297     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
11298
11299     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
11300   }
11301   if (aCmd.HasOption ("size", 1, Standard_True))
11302   {
11303     aManipulator->SetSize (aCmd.ArgFloat ("size"));
11304   }
11305   if (aCmd.HasOption ("zoomable", 1, Standard_True))
11306   {
11307     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
11308
11309     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
11310     {
11311       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
11312       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
11313     }
11314   }
11315
11316   // ---------------------------------------------------
11317   // attach, detach or access manipulator from an object
11318   // ---------------------------------------------------
11319
11320   if (aCmd.HasOption ("attach"))
11321   {
11322     // Find an object and attach manipulator to it
11323     if (!aCmd.HasOption ("attach", 1, Standard_True))
11324     {
11325       return 1;
11326     }
11327
11328     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
11329     if (!aMapAIS.IsBound2 (anObjName))
11330     {
11331       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
11332       return 1;
11333     }
11334
11335     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
11336     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
11337     for (; anIt.More(); anIt.Next())
11338     {
11339       if (anIt.Value()->IsAttached()
11340        && anIt.Value()->Object() == anObject)
11341       {
11342         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
11343         return 1;
11344       }
11345     }
11346
11347     AIS_Manipulator::OptionsForAttach anOptions;
11348     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
11349     {
11350       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
11351     }
11352     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
11353     {
11354       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
11355     }
11356     if (aCmd.HasOption ("enableModes", 1, Standard_True))
11357     {
11358       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
11359     }
11360
11361     aManipulator->Attach (anObject, anOptions);
11362   }
11363
11364   // --------------------------------------
11365   // apply transformation using manipulator
11366   // --------------------------------------
11367
11368   if (aCmd.HasOption ("startTransform", 2, Standard_True))
11369   {
11370     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
11371   }
11372   if (aCmd.HasOption ("transform", 2, Standard_True))
11373   {
11374     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
11375   }
11376   if (aCmd.HasOption ("stopTransform"))
11377   {
11378     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
11379
11380     aManipulator->StopTransform (toApply);
11381   }
11382
11383   gp_Trsf aT;
11384   if (aCmd.HasOption ("move", 3, Standard_True))
11385   {
11386     aT.SetTranslationPart (aCmd.ArgVec ("move"));
11387   }
11388   if (aCmd.HasOption ("rotate", 7, Standard_True))
11389   {
11390     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
11391   }
11392   if (aCmd.HasOption ("scale", 1))
11393   {
11394     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
11395   }
11396
11397   if (aT.Form() != gp_Identity)
11398   {
11399     aManipulator->Transform (aT);
11400   }
11401
11402   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
11403
11404   return 0;
11405 }
11406
11407 //===============================================================================================
11408 //function : VSelectionProperties
11409 //purpose  :
11410 //===============================================================================================
11411 static int VSelectionProperties (Draw_Interpretor& theDi,
11412                                  Standard_Integer  theArgsNb,
11413                                  const char**      theArgVec)
11414 {
11415   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
11416   if (aCtx.IsNull())
11417   {
11418     std::cerr << "No active viewer!\n";
11419     return 1;
11420   }
11421
11422   Standard_Boolean toPrint  = theArgsNb == 1;
11423   Standard_Boolean toRedraw = Standard_False;
11424   Standard_Integer anArgIter = 1;
11425   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
11426   if (anArgIter < theArgsNb)
11427   {
11428     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
11429     anArgFirst.LowerCase();
11430     ++anArgIter;
11431     if (anArgFirst == "dynhighlight"
11432      || anArgFirst == "dynhilight"
11433      || anArgFirst == "dynamichighlight"
11434      || anArgFirst == "dynamichilight")
11435     {
11436       aType = Prs3d_TypeOfHighlight_Dynamic;
11437     }
11438     else if (anArgFirst == "localdynhighlight"
11439           || anArgFirst == "localdynhilight"
11440           || anArgFirst == "localdynamichighlight"
11441           || anArgFirst == "localdynamichilight")
11442     {
11443       aType = Prs3d_TypeOfHighlight_LocalDynamic;
11444     }
11445     else if (anArgFirst == "selhighlight"
11446           || anArgFirst == "selhilight"
11447           || anArgFirst == "selectedhighlight"
11448           || anArgFirst == "selectedhilight")
11449     {
11450       aType = Prs3d_TypeOfHighlight_Selected;
11451     }
11452     else if (anArgFirst == "localselhighlight"
11453           || anArgFirst == "localselhilight"
11454           || anArgFirst == "localselectedhighlight"
11455           || anArgFirst == "localselectedhilight")
11456     {
11457       aType = Prs3d_TypeOfHighlight_LocalSelected;
11458     }
11459     else
11460     {
11461       --anArgIter;
11462     }
11463   }
11464   for (; anArgIter < theArgsNb; ++anArgIter)
11465   {
11466     TCollection_AsciiString anArg (theArgVec[anArgIter]);
11467     anArg.LowerCase();
11468     if (anArg == "-help")
11469     {
11470       theDi.PrintHelp (theArgVec[0]);
11471       return 0;
11472     }
11473     else if (anArg == "-print")
11474     {
11475       toPrint = Standard_True;
11476     }
11477     else if (anArg == "-autoactivate")
11478     {
11479       Standard_Boolean toEnable = Standard_True;
11480       if (anArgIter + 1 < theArgsNb
11481        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11482       {
11483         ++anArgIter;
11484       }
11485       aCtx->SetAutoActivateSelection (toEnable);
11486     }
11487     else if (anArg == "-pickstrategy"
11488           || anArg == "-pickingstrategy")
11489     {
11490       if (++anArgIter >= theArgsNb)
11491       {
11492         std::cout << "Syntax error: type of highlighting is undefined\n";
11493         return 1;
11494       }
11495
11496       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11497       TCollection_AsciiString aVal (theArgVec[anArgIter]);
11498       aVal.LowerCase();
11499       if (aVal == "first"
11500        || aVal == "firstaccepted"
11501        || aVal == "firstacceptable")
11502       {
11503         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11504       }
11505       else if (aVal == "topmost"
11506             || aVal == "onlyTopmost")
11507       {
11508         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
11509       }
11510       else
11511       {
11512         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
11513         return 1;
11514       }
11515
11516       aCtx->SetPickingStrategy (aStrategy);
11517     }
11518     else if (anArg == "-pixtol"
11519           && anArgIter + 1 < theArgsNb)
11520     {
11521       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
11522     }
11523     else if ((anArg == "-mode"
11524            || anArg == "-dispmode")
11525           && anArgIter + 1 < theArgsNb)
11526     {
11527       if (aType == Prs3d_TypeOfHighlight_None)
11528       {
11529         std::cout << "Syntax error: type of highlighting is undefined\n";
11530         return 1;
11531       }
11532
11533       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
11534       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11535       aStyle->SetDisplayMode (aDispMode);
11536       toRedraw = Standard_True;
11537     }
11538     else if (anArg == "-layer"
11539           && anArgIter + 1 < theArgsNb)
11540     {
11541       if (aType == Prs3d_TypeOfHighlight_None)
11542       {
11543         std::cout << "Syntax error: type of highlighting is undefined\n";
11544         return 1;
11545       }
11546
11547       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
11548       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
11549       {
11550         TColStd_SequenceOfInteger aLayers;
11551         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
11552         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
11553         {
11554           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
11555           return 1;
11556         }
11557       }
11558
11559       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11560       aStyle->SetZLayer (aNewLayer);
11561       toRedraw = Standard_True;
11562     }
11563     else if (anArg == "-hicolor"
11564           || anArg == "-selcolor"
11565           || anArg == "-color")
11566     {
11567       if (anArg.StartsWith ("-hi"))
11568       {
11569         aType = Prs3d_TypeOfHighlight_Dynamic;
11570       }
11571       else if (anArg.StartsWith ("-sel"))
11572       {
11573         aType = Prs3d_TypeOfHighlight_Selected;
11574       }
11575       else if (aType == Prs3d_TypeOfHighlight_None)
11576       {
11577         std::cout << "Syntax error: type of highlighting is undefined\n";
11578         return 1;
11579       }
11580
11581       Quantity_Color aColor;
11582       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
11583                                                            theArgVec + anArgIter + 1,
11584                                                            aColor);
11585       if (aNbParsed == 0)
11586       {
11587         std::cout << "Syntax error: need more arguments.\n";
11588         return 1;
11589       }
11590       anArgIter += aNbParsed;
11591
11592       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11593       aStyle->SetColor (aColor);
11594       toRedraw = Standard_True;
11595     }
11596     else if ((anArg == "-transp"
11597            || anArg == "-transparency"
11598            || anArg == "-hitransp"
11599            || anArg == "-seltransp"
11600            || anArg == "-hitransplocal"
11601            || anArg == "-seltransplocal")
11602           && anArgIter + 1 < theArgsNb)
11603     {
11604       if (anArg.StartsWith ("-hi"))
11605       {
11606         aType = Prs3d_TypeOfHighlight_Dynamic;
11607       }
11608       else if (anArg.StartsWith ("-sel"))
11609       {
11610         aType = Prs3d_TypeOfHighlight_Selected;
11611       }
11612       else if (aType == Prs3d_TypeOfHighlight_None)
11613       {
11614         std::cout << "Syntax error: type of highlighting is undefined\n";
11615         return 1;
11616       }
11617
11618       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
11619       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11620       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
11621       toRedraw = Standard_True;
11622     }
11623     else if ((anArg == "-mat"
11624            || anArg == "-material")
11625           && anArgIter + 1 < theArgsNb)
11626     {
11627       if (aType == Prs3d_TypeOfHighlight_None)
11628       {
11629         std::cout << "Syntax error: type of highlighting is undefined\n";
11630         return 1;
11631       }
11632
11633       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11634       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
11635       if (aMatName != Graphic3d_NOM_DEFAULT)
11636       {
11637         ++anArgIter;
11638         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
11639         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
11640         Graphic3d_MaterialAspect aMat (aMatName);
11641         aMat.SetColor (aStyle->Color());
11642         aMat.SetTransparency (aStyle->Transparency());
11643         anAspect->SetFrontMaterial (aMat);
11644         anAspect->SetInteriorColor (aStyle->Color());
11645         aStyle->SetBasicFillAreaAspect (anAspect);
11646       }
11647       else
11648       {
11649         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
11650       }
11651       toRedraw = Standard_True;
11652     }
11653     else
11654     {
11655       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
11656     }
11657   }
11658
11659   if (toPrint)
11660   {
11661     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
11662     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
11663     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
11664     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
11665     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
11666     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
11667     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
11668     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
11669     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
11670     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
11671     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
11672     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
11673   }
11674
11675   if (aCtx->NbSelected() != 0 && toRedraw)
11676   {
11677     aCtx->HilightSelected (Standard_True);
11678   }
11679
11680   return 0;
11681 }
11682
11683 //===============================================================================================
11684 //function : VDumpSelectionImage
11685 //purpose  :
11686 //===============================================================================================
11687 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
11688                                 Standard_Integer  theArgsNb,
11689                                 const char**      theArgVec)
11690 {
11691   if (theArgsNb < 2)
11692   {
11693     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
11694     return 1;
11695   }
11696
11697   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
11698   if (aContext.IsNull())
11699   {
11700     std::cout << "Error: no active view.\n";
11701     return 1;
11702   }
11703
11704   TCollection_AsciiString aFile;
11705   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11706   Image_Format anImgFormat = Image_Format_BGR;
11707   Standard_Integer aPickedIndex = 1;
11708   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
11709   {
11710     TCollection_AsciiString aParam (theArgVec[anArgIter]);
11711     aParam.LowerCase();
11712     if (aParam == "-type")
11713     {
11714       if (++anArgIter >= theArgsNb)
11715       {
11716         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
11717         return 1;
11718       }
11719
11720       TCollection_AsciiString aValue (theArgVec[anArgIter]);
11721       aValue.LowerCase();
11722       if (aValue == "depth"
11723        || aValue == "normdepth"
11724        || aValue == "normalizeddepth")
11725       {
11726         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11727         anImgFormat = Image_Format_GrayF;
11728       }
11729       if (aValue == "depthinverted"
11730        || aValue == "normdepthinverted"
11731        || aValue == "normalizeddepthinverted"
11732        || aValue == "inverted")
11733       {
11734         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
11735         anImgFormat = Image_Format_GrayF;
11736       }
11737       else if (aValue == "unnormdepth"
11738             || aValue == "unnormalizeddepth")
11739       {
11740         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
11741         anImgFormat = Image_Format_GrayF;
11742       }
11743       else if (aValue == "objectcolor"
11744             || aValue == "object"
11745             || aValue == "color")
11746       {
11747         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
11748       }
11749       else if (aValue == "entitycolor"
11750             || aValue == "entity")
11751       {
11752         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
11753       }
11754       else if (aValue == "ownercolor"
11755             || aValue == "owner")
11756       {
11757         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
11758       }
11759       else if (aValue == "selectionmodecolor"
11760             || aValue == "selectionmode"
11761             || aValue == "selmodecolor"
11762             || aValue == "selmode")
11763       {
11764         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
11765       }
11766     }
11767     else if (aParam == "-picked"
11768           || aParam == "-pickeddepth"
11769           || aParam == "-pickedindex")
11770     {
11771       if (++anArgIter >= theArgsNb)
11772       {
11773         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
11774         return 1;
11775       }
11776
11777       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
11778     }
11779     else if (aFile.IsEmpty())
11780     {
11781       aFile = theArgVec[anArgIter];
11782     }
11783     else
11784     {
11785       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
11786       return 1;
11787     }
11788   }
11789   if (aFile.IsEmpty())
11790   {
11791     std::cout << "Syntax error: image file name is missing.\n";
11792     return 1;
11793   }
11794
11795   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
11796   Standard_Integer aWidth = 0, aHeight = 0;
11797   aView->Window()->Size (aWidth, aHeight);
11798
11799   Image_AlienPixMap aPixMap;
11800   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
11801   {
11802     std::cout << "Error: can't allocate image.\n";
11803     return 1;
11804   }
11805   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
11806   {
11807     std::cout << "Error: can't generate selection image.\n";
11808     return 1;
11809   }
11810   if (!aPixMap.Save (aFile))
11811   {
11812     std::cout << "Error: can't save selection image.\n";
11813     return 0;
11814   }
11815   return 0;
11816 }
11817
11818 //=======================================================================
11819 //function : ViewerCommands
11820 //purpose  :
11821 //=======================================================================
11822
11823 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
11824 {
11825
11826   const char *group = "ZeViewer";
11827   theCommands.Add("vinit",
11828           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
11829     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
11830   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11831     "\n\t\t:     [-display displayName]"
11832   #endif
11833     "\n\t\t: Creates new View window with specified name viewName."
11834     "\n\t\t: By default the new view is created in the viewer and in"
11835     "\n\t\t: graphic driver shared with active view."
11836     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
11837     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
11838     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
11839 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11840     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
11841     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
11842 #endif
11843     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
11844     "\n\t\t:  -width, -height width and heigth of window respectively."
11845     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
11846     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
11847     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
11848     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
11849     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
11850     __FILE__,VInit,group);
11851   theCommands.Add("vclose" ,
11852     "[view_id [keep_context=0|1]]\n"
11853     "or vclose ALL - to remove all created views\n"
11854     " - removes view(viewer window) defined by its view_id.\n"
11855     " - keep_context: by default 0; if 1 and the last view is deleted"
11856     " the current context is not removed.",
11857     __FILE__,VClose,group);
11858   theCommands.Add("vactivate" ,
11859     "view_id"
11860     " - activates view(viewer window) defined by its view_id",
11861     __FILE__,VActivate,group);
11862   theCommands.Add("vviewlist",
11863     "vviewlist [format={tree, long}]"
11864     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
11865     " - format: format of result output, if tree the output is a tree view;"
11866     "otherwise it's a list of full view names. By default format = tree",
11867     __FILE__,VViewList,group);
11868   theCommands.Add("vhelp" ,
11869     "vhelp            : display help on the viewer commands",
11870     __FILE__,VHelp,group);
11871   theCommands.Add("vtop" ,
11872     "vtop or <T>      : Top view. Orientation +X+Y" ,
11873     __FILE__,VTop,group);
11874   theCommands.Add("vbottom" ,
11875     "vbottom          : Bottom view. Orientation +X-Y" ,
11876     __FILE__,VBottom,group);
11877   theCommands.Add("vleft" ,
11878     "vleft            : Left view. Orientation -Y+Z" ,
11879     __FILE__,VLeft,group);
11880   theCommands.Add("vright" ,
11881     "vright           : Right view. Orientation +Y+Z" ,
11882     __FILE__,VRight,group);
11883   theCommands.Add("vaxo" ,
11884     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
11885     __FILE__,VAxo,group);
11886   theCommands.Add("vfront" ,
11887     "vfront           : Front view. Orientation +X+Z" ,
11888     __FILE__,VFront,group);
11889   theCommands.Add("vback" ,
11890     "vback            : Back view. Orientation -X+Z" ,
11891     __FILE__,VBack,group);
11892   theCommands.Add("vpick" ,
11893     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
11894     VPick,group);
11895   theCommands.Add("vfit",
11896     "vfit or <F> [-selected] [-noupdate]"
11897     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
11898     __FILE__,VFit,group);
11899   theCommands.Add ("vfitarea",
11900     "vfitarea x1 y1 x2 y2"
11901     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
11902     "\n\t\t: Fit view to show area located between two points"
11903     "\n\t\t: given in world 2D or 3D corrdinates.",
11904     __FILE__, VFitArea, group);
11905   theCommands.Add ("vzfit", "vzfit [scale]\n"
11906     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
11907     "   \"scale\" - specifies factor to scale computed z range.\n",
11908     __FILE__, VZFit, group);
11909   theCommands.Add("vrepaint",
11910             "vrepaint [-immediate]"
11911     "\n\t\t: force redraw",
11912     __FILE__,VRepaint,group);
11913   theCommands.Add("vclear",
11914     "vclear          : vclear"
11915     "\n\t\t: remove all the object from the viewer",
11916     __FILE__,VClear,group);
11917   theCommands.Add("vsetbg",
11918     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
11919     __FILE__,VSetBg,group);
11920   theCommands.Add("vsetbgmode",
11921     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
11922     __FILE__,VSetBgMode,group);
11923   theCommands.Add("vsetgradientbg",
11924     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
11925     __FILE__,VSetGradientBg,group);
11926   theCommands.Add("vsetgrbgmode",
11927     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
11928     __FILE__,VSetGradientBgMode,group);
11929   theCommands.Add("vsetcolorbg",
11930     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
11931     __FILE__,VSetColorBg,group);
11932   theCommands.Add("vsetdefaultbg",
11933     "vsetdefaultbg r g b\n"
11934     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
11935     "\n\t\t: Set default viewer background fill color (flat/gradient).",
11936     __FILE__,VSetDefaultBg,group);
11937   theCommands.Add("vscale",
11938     "vscale          : vscale X Y Z",
11939     __FILE__,VScale,group);
11940   theCommands.Add("vzbufftrihedron",
11941             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
11942     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
11943     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
11944     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
11945     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
11946     "\n\t\t: Displays a trihedron",
11947     __FILE__,VZBuffTrihedron,group);
11948   theCommands.Add("vrotate",
11949     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
11950     "\n                : Option -mouseStart starts rotation according to the mouse position"
11951     "\n                : Option -mouseMove continues rotation with angle computed"
11952     "\n                : from last and new mouse position."
11953     "\n                : vrotate AX AY AZ [X Y Z]",
11954     __FILE__,VRotate,group);
11955   theCommands.Add("vzoom",
11956     "vzoom           : vzoom coef",
11957     __FILE__,VZoom,group);
11958   theCommands.Add("vpan",
11959     "vpan            : vpan dx dy",
11960     __FILE__,VPan,group);
11961   theCommands.Add("vexport",
11962     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
11963     " : exports the view to a vector file of a given format"
11964     " : notice that EMF format requires patched gl2ps",
11965     __FILE__,VExport,group);
11966   theCommands.Add("vcolorscale",
11967     "vcolorscale name [-noupdate|-update] [-demo]"
11968     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
11969     "\n\t\t:       [-font HeightFont=20]"
11970     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
11971     "\n\t\t:       [-smoothTransition {on|off}=off]"
11972     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
11973     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
11974     "\n\t\t:       [-textpos {left|right|center|none}=right]"
11975     "\n\t\t:       [-labelAtBorder {on|off}=on]"
11976     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
11977     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
11978     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
11979     "\n\t\t:       [-xy Left=0 Bottom=0]"
11980     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
11981     "\n\t\t:  -colors   - set colors for all intervals"
11982     "\n\t\t:  -color    - set color for specific interval"
11983     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
11984     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
11985     "\n\t\t:              at border means the value inbetween neighbor intervals,"
11986     "\n\t\t:              at center means the center value within current interval"
11987     "\n\t\t:  -labels   - set labels for all intervals"
11988     "\n\t\t:  -freeLabels - same as -labels but does not require"
11989     "\n\t\t:              matching the number of intervals"
11990     "\n\t\t:  -label    - set label for specific interval"
11991     "\n\t\t:  -title    - set title"
11992     "\n\t\t:  -reversed - setup smooth color transition between intervals"
11993     "\n\t\t:  -smoothTransition - swap colorscale direction"
11994     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
11995     __FILE__, VColorScale, group);
11996   theCommands.Add("vgraduatedtrihedron",
11997     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
11998     "\t[-namefont Name] [-valuesfont Name]\n"
11999     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
12000     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
12001     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
12002     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
12003     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
12004     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
12005     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
12006     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
12007     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
12008     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
12009     " - Displays or erases graduated trihedron"
12010     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
12011     " - namefont - font of axes names. Default: Arial\n"
12012     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
12013     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
12014     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
12015     " - valuesfont - font of axes values. Default: Arial\n"
12016     " - xcolor, ycolor, zcolor - color of axis and values\n"
12017     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
12018     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
12019     __FILE__,VGraduatedTrihedron,group);
12020   theCommands.Add("vtile" ,
12021             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
12022     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
12023     "\n\t\t:  -totalSize the size of virtual bigger viewport"
12024     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
12025     "\n\t\t:  -lowerLeft tile offset as lower left corner"
12026     "\n\t\t:  -upperLeft tile offset as upper left corner",
12027     __FILE__, VTile, group);
12028   theCommands.Add("vzlayer",
12029               "vzlayer [layerId]"
12030       "\n\t\t:         [-add|-delete|-get|-settings]"
12031       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
12032       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
12033       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
12034       "\n\t\t: ZLayer list management:"
12035       "\n\t\t:   -add      add new z layer to viewer and print its id"
12036       "\n\t\t:   -delete   delete z layer"
12037       "\n\t\t:   -get      print sequence of z layers"
12038       "\n\t\t:   -settings print status of z layer settings"
12039       "\n\t\t:   -disable  disables given setting"
12040       "\n\t\t:   -enable   enables  given setting",
12041     __FILE__,VZLayer,group);
12042   theCommands.Add("vlayerline",
12043     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
12044     __FILE__,VLayerLine,group);
12045   theCommands.Add ("vgrid",
12046     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
12047     " : Mode - rectangular or circular"
12048     " : Type - lines or points",
12049     __FILE__, VGrid, group);
12050   theCommands.Add ("vpriviledgedplane",
12051     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
12052     "\n\t\t:   Ox, Oy, Oz - plane origin"
12053     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
12054     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
12055     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
12056     __FILE__, VPriviledgedPlane, group);
12057   theCommands.Add ("vconvert",
12058     "vconvert v [Mode={window|view}]"
12059     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
12060     "\n\t\t: vconvert x y z [Mode={window|grid}]"
12061     "\n\t\t:   window - convert to window coordinates, pixels"
12062     "\n\t\t:   view   - convert to view projection plane"
12063     "\n\t\t:   grid   - convert to model coordinates, given on grid"
12064     "\n\t\t:   ray    - convert projection ray to model coordiantes"
12065     "\n\t\t: - vconvert v window : convert view to window;"
12066     "\n\t\t: - vconvert v view   : convert window to view;"
12067     "\n\t\t: - vconvert x y window : convert view to window;"
12068     "\n\t\t: - vconvert x y view : convert window to view;"
12069     "\n\t\t: - vconvert x y : convert window to model;"
12070     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
12071     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
12072     "\n\t\t: - vconvert x y z window : convert model to window;"
12073     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
12074     "\n\t\t: Converts the given coordinates to window/view/model space.",
12075     __FILE__, VConvert, group);
12076   theCommands.Add ("vfps",
12077     "vfps [framesNb=100] : estimate average frame rate for active view",
12078     __FILE__, VFps, group);
12079   theCommands.Add ("vgldebug",
12080             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
12081     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
12082     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
12083     "\n\t\t: Debug context can be requested only on Windows"
12084     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
12085     "\n\t\t:  -sync     - request synchronized debug GL context"
12086     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
12087     "\n\t\t:              which are suppressed by default,"
12088     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
12089     "\n\t\t:              which are suppressed by default",
12090     __FILE__, VGlDebug, group);
12091   theCommands.Add ("vvbo",
12092     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
12093     __FILE__, VVbo, group);
12094   theCommands.Add ("vstereo",
12095             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
12096     "\n\t\t:         [-anaglyph Filter]"
12097     "\n\t\t: Control stereo output mode. Available modes for -mode:"
12098     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
12099     "\n\t\t:                     requires driver support."
12100     "\n\t\t:                     Should be called BEFORE vinit!"
12101     "\n\t\t:  anaglyph         - Anaglyph glasses"
12102     "\n\t\t:  rowInterlaced    - row-interlaced display"
12103     "\n\t\t:  columnInterlaced - column-interlaced display"
12104     "\n\t\t:  chessBoard       - chess-board output"
12105     "\n\t\t:  sideBySide       - horizontal pair"
12106     "\n\t\t:  overUnder        - vertical   pair"
12107     "\n\t\t: Available Anaglyph filters for -anaglyph:"
12108     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
12109     "\n\t\t:  greenMagentaSimple",
12110     __FILE__, VStereo, group);
12111   theCommands.Add ("vcaps",
12112             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
12113     "\n\t\t:       [-compatibleProfile {0|1}]"
12114     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
12115     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
12116     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
12117     "\n\t\t: Modify particular graphic driver options:"
12118     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
12119     "\n\t\t:             built-in GLSL programs"
12120     "\n\t\t:            (requires compatible profile)"
12121     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
12122     "\n\t\t:             arrays to GPU memory)"
12123     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
12124     "\n\t\t:  vsync    - switch VSync on or off"
12125     "\n\t\t:  winBuffer - allow using window buffer for rendering"
12126     "\n\t\t: Context creation options:"
12127     "\n\t\t:  softMode          - software OpenGL implementation"
12128     "\n\t\t:  compatibleProfile - backward-compatible profile"
12129     "\n\t\t:  quadbuffer        - QuadBuffer"
12130     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
12131     "\n\t\t: rendering paths producing the same visual result when"
12132     "\n\t\t: possible."
12133     "\n\t\t: Command is intended for testing old hardware compatibility.",
12134     __FILE__, VCaps, group);
12135   theCommands.Add ("vmemgpu",
12136     "vmemgpu [f]: print system-dependent GPU memory information if available;"
12137     " with f option returns free memory in bytes",
12138     __FILE__, VMemGpu, group);
12139   theCommands.Add ("vreadpixel",
12140     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
12141     " : Read pixel value for active view",
12142     __FILE__, VReadPixel, group);
12143   theCommands.Add("diffimage",
12144             "diffimage imageFile1 imageFile2 [diffImageFile]"
12145     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
12146     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
12147     "\n\t\t: Compare two images by content and generate difference image."
12148     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
12149     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
12150     __FILE__, VDiffImage, group);
12151   theCommands.Add ("vselect",
12152     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
12153     "- emulates different types of selection:\n"
12154     "- 1) single click selection\n"
12155     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
12156     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
12157     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
12158     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
12159     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
12160     " (partial inclusion - overlap - is not allowed by default)\n"
12161     "- 5) any of these selections with shift button pressed",
12162     __FILE__, VSelect, group);
12163   theCommands.Add ("vmoveto",
12164     "vmoveto x y"
12165     "- emulates cursor movement to pixel postion (x,y)",
12166     __FILE__, VMoveTo, group);
12167   theCommands.Add ("vviewparams",
12168               "vviewparams [-args] [-scale [s]]"
12169       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
12170       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
12171       "\n\t\t: Manage current view parameters or prints all"
12172       "\n\t\t: current values when called without argument."
12173       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
12174       "\n\t\t:   -eye  [x y z] prints or sets eye location"
12175       "\n\t\t:   -at   [x y z] prints or sets center of look"
12176       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
12177       "\n\t\t:   -proj [x y z] prints or sets direction of look"
12178       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
12179       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
12180       "\n\t\t:                 or changes the size of its maximum dimension"
12181       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
12182     __FILE__, VViewParams, group);
12183
12184   theCommands.Add("v2dmode",
12185     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
12186     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
12187     "\n\t\t:   mode   - switches On/Off rotation mode"
12188     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
12189     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
12190     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
12191     "\n\t\t: View camera position might be changed only by commands.",
12192     __FILE__, V2DMode, group);
12193
12194   theCommands.Add("vanimation", "Alias for vanim",
12195     __FILE__, VAnimation, group);
12196
12197   theCommands.Add("vanim",
12198             "List existing animations:"
12199     "\n\t\t:  vanim"
12200     "\n\t\t: Animation playback:"
12201     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
12202     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
12203     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
12204     "\n\t\t:   -freeLook skip camera animations"
12205     "\n\t\t:   -lockLoop disable any interactions"
12206     "\n\t\t:"
12207     "\n\t\t: Animation definition:"
12208     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
12209     "\n\t\t:        [start TimeSec] [duration TimeSec]"
12210     "\n\t\t:"
12211     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
12212     "\n\t\t: specifies nested animations."
12213     "\n\t\t: There is no syntax to explicitly add new animation,"
12214     "\n\t\t: and all non-existing animations within the name will be"
12215     "\n\t\t: implicitly created on first use (including parents)."
12216     "\n\t\t:"
12217     "\n\t\t: Each animation might define the SINGLE action (see below),"
12218     "\n\t\t: like camera transition, object transformation or custom callback."
12219     "\n\t\t: Child animations can be used for defining concurrent actions."
12220     "\n\t\t:"
12221     "\n\t\t: Camera animation:"
12222     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
12223     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
12224     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
12225     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
12226     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
12227     "\n\t\t:   -atX    camera Center positions pair"
12228     "\n\t\t:   -upX    camera Up directions pair"
12229     "\n\t\t:   -scaleX camera Scale factors pair"
12230     "\n\t\t: Object animation:"
12231     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
12232     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
12233     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
12234     "\n\t\t:   -locX   object Location points pair (translation)"
12235     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
12236     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
12237     "\n\t\t: Custom callback:"
12238     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
12239     "\n\t\t:   %Pts        overall animation presentation timestamp"
12240     "\n\t\t:   %LocalPts   local animation timestamp"
12241     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
12242     "\n\t\t:"
12243     "\n\t\t: Video recording:"
12244     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
12245     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
12246     "\n\t\t:             [-crf Value] [-preset Preset]"
12247     "\n\t\t:   -fps     video framerate"
12248     "\n\t\t:   -format  file format, container (matroska, etc.)"
12249     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
12250     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
12251     "\n\t\t:   -crf     constant rate factor (specific to codec)"
12252     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
12253     __FILE__, VAnimation, group);
12254
12255   theCommands.Add("vchangeselected",
12256     "vchangeselected shape"
12257     "- adds to shape to selection or remove one from it",
12258                 __FILE__, VChangeSelected, group);
12259   theCommands.Add ("vnbselected",
12260     "vnbselected"
12261     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
12262   theCommands.Add ("vcamera",
12263               "vcamera [-ortho] [-projtype]"
12264       "\n\t\t:         [-persp]"
12265       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
12266       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
12267       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
12268       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
12269       "\n\t\t: Manage camera parameters."
12270       "\n\t\t: Prints current value when option called without argument."
12271       "\n\t\t: Orthographic camera:"
12272       "\n\t\t:   -ortho      activate orthographic projection"
12273       "\n\t\t: Perspective camera:"
12274       "\n\t\t:   -persp      activate perspective  projection (mono)"
12275       "\n\t\t:   -fovy       field of view in y axis, in degrees"
12276       "\n\t\t:   -distance   distance of eye from camera center"
12277       "\n\t\t: Stereoscopic camera:"
12278       "\n\t\t:   -stereo     perspective  projection (stereo)"
12279       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
12280       "\n\t\t:   -rightEye   perspective  projection (right eye)"
12281       "\n\t\t:   -iod        intraocular distance value"
12282       "\n\t\t:   -iodType    distance type, absolute or relative"
12283       "\n\t\t:   -zfocus     stereographic focus value"
12284       "\n\t\t:   -zfocusType focus type, absolute or relative",
12285     __FILE__, VCamera, group);
12286   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
12287     "- vautozfit [on={1|0}] [scale]\n"
12288     "    Prints or changes parameters of automatic z-fit mode:\n"
12289     "   \"on\" - turns automatic z-fit on or off\n"
12290     "   \"scale\" - specifies factor to scale computed z range.\n",
12291     __FILE__, VAutoZFit, group);
12292   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
12293     "   vzrange                - without parameters shows current values\n"
12294     "   vzrange [znear] [zfar] - applies provided values to view",
12295     __FILE__,VZRange, group);
12296   theCommands.Add ("vpurgedisplay",
12297     "vpurgedisplay"
12298     "- removes structures which don't belong to objects displayed in neutral point",
12299     __FILE__, VPurgeDisplay, group);
12300   theCommands.Add("vsetviewsize",
12301     "vsetviewsize size",
12302     __FILE__,VSetViewSize,group);
12303   theCommands.Add("vmoveview",
12304     "vmoveview Dx Dy Dz [Start = 1|0]",
12305     __FILE__,VMoveView,group);
12306   theCommands.Add("vtranslateview",
12307     "vtranslateview Dx Dy Dz [Start = 1|0)]",
12308     __FILE__,VTranslateView,group);
12309   theCommands.Add("vturnview",
12310     "vturnview Ax Ay Az [Start = 1|0]",
12311     __FILE__,VTurnView,group);
12312   theCommands.Add("vtextureenv",
12313     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
12314     "or user-defined file and optionally applying texture mapping parameters\n"
12315     "                  Usage:\n"
12316     "                  vtextureenv off - disables environment mapping\n"
12317     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
12318     "                              std_texture = (0..7)\n"
12319     "                              rep         = {clamp|repeat}\n"
12320     "                              mod         = {decal|modulate}\n"
12321     "                              flt         = {nearest|bilinear|trilinear}\n"
12322     "                              ss, st      - scale factors for s and t texture coordinates\n"
12323     "                              ts, tt      - translation for s and t texture coordinates\n"
12324     "                              rot         - texture rotation angle in degrees",
12325     __FILE__, VTextureEnv, group);
12326   theCommands.Add("vhlr",
12327             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
12328       "\n\t\t: Hidden Line Removal algorithm."
12329       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
12330       "\n\t\t:   -algoType   type of HLR algorithm.\n",
12331     __FILE__,VHLR,group);
12332   theCommands.Add("vhlrtype",
12333               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
12334       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
12335       "\n\t\t:   'algo' - exact HLR algorithm is applied"
12336       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
12337       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
12338     __FILE__,VHLRType,group);
12339   theCommands.Add("vclipplane",
12340               "vclipplane planeName [{0|1}]"
12341       "\n\t\t:   [-equation A B C D]"
12342       "\n\t\t:   [-set|-unset [objects|views]]"
12343       "\n\t\t:   [-maxPlanes]"
12344       "\n\t\t:   [-capping {0|1}]"
12345       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
12346       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
12347       "\n\t\t:       [-texRotate Angle]"
12348       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
12349       "\n\t\t:       [-useObjShader {0|1}]"
12350       "\n\t\t: Clipping planes management:"
12351       "\n\t\t:   -maxPlanes   print plane limit for view"
12352       "\n\t\t:   -delete      delete plane with given name"
12353       "\n\t\t:   {off|on|0|1} turn clipping on/off"
12354       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
12355       "\n\t\t:                applied to active View when list is omitted"
12356       "\n\t\t:   -equation A B C D change plane equation"
12357       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
12358       "\n\t\t: Capping options:"
12359       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
12360       "\n\t\t:   -color R G B          set capping color"
12361       "\n\t\t:   -texName Texture      set capping texture"
12362       "\n\t\t:   -texScale SX SY       set capping tex scale"
12363       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
12364       "\n\t\t:   -texRotate Angle      set capping tex rotation"
12365       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
12366       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
12367       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
12368       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
12369       __FILE__, VClipPlane, group);
12370   theCommands.Add("vdefaults",
12371                "vdefaults [-absDefl value]"
12372        "\n\t\t:           [-devCoeff value]"
12373        "\n\t\t:           [-angDefl value]"
12374        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
12375     , __FILE__, VDefaults, group);
12376   theCommands.Add("vlight",
12377     "tool to manage light sources, without arguments shows list of lights."
12378     "\n    Main commands: "
12379     "\n      '-clear' to clear lights"
12380     "\n      '-{def}aults' to load deafault lights"
12381     "\n      '-add' <type> to add any light source"
12382     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
12383     "\n      'change' <lightId> to edit light source with specified lightId"
12384     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
12385     "\n        -layer Id"
12386     "\n        -{pos}ition X Y Z"
12387     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
12388     "\n        -color colorName"
12389     "\n        -{head}light 0|1"
12390     "\n        -{sm}oothness value"
12391     "\n        -{int}ensity value"
12392     "\n        -{constAtten}uation value"
12393     "\n        -{linearAtten}uation value"
12394     "\n        -angle angleDeg"
12395     "\n        -{spotexp}onent value"
12396     "\n        -local|-global"
12397     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
12398     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
12399     __FILE__, VLight, group);
12400   theCommands.Add("vraytrace",
12401             "vraytrace [0|1]"
12402     "\n\t\t: Turns on/off ray-tracing renderer."
12403     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
12404     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
12405     __FILE__, VRenderParams, group);
12406   theCommands.Add("vrenderparams",
12407     "\n    Manages rendering parameters: "
12408     "\n      '-raster'                   Disables GPU ray-tracing"
12409     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
12410     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
12411     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
12412     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
12413     "\n      '-rendScale    value        Rendering resolution scale factor"
12414     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
12415     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
12416     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
12417     "\n      '-reflections  on|off'      Enables/disables specular reflections"
12418     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
12419     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
12420     "\n      '-gi           on|off'      Enables/disables global illumination effects"
12421     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
12422     "\n      '-env          on|off'      Enables/disables environment map background"
12423     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
12424     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
12425     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
12426     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
12427     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
12428     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
12429     "\n      '-shadingModel model'       Controls shading model from enumeration"
12430     "\n                                  color, flat, gouraud, phong"
12431     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
12432     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
12433     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
12434     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
12435     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
12436     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
12437     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points|gpuMem|basic|extended|nofps'"
12438     "\n                                  Show/hide performance counters (flags can be combined)"
12439     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
12440     "\n    Unlike vcaps, these parameters dramatically change visual properties."
12441     "\n    Command is intended to control presentation quality depending on"
12442     "\n    hardware capabilities and performance.",
12443     __FILE__, VRenderParams, group);
12444   theCommands.Add("vfrustumculling",
12445     "vfrustumculling [toEnable]: enables/disables objects clipping",
12446     __FILE__,VFrustumCulling,group);
12447   theCommands.Add("vhighlightselected",
12448     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
12449     "Without arguments it shows if highlighting of selected objects is enabled now.",
12450     __FILE__,VHighlightSelected,group);
12451   theCommands.Add ("vplace",
12452             "vplace dx dy"
12453     "\n\t\t: Places the point (in pixels) at the center of the window",
12454     __FILE__, VPlace, group);
12455   theCommands.Add("vxrotate",
12456     "vxrotate",
12457     __FILE__,VXRotate,group);
12458
12459     theCommands.Add("vmanipulator",
12460       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
12461       "\n    tool to create and manage AIS manipulators."
12462       "\n    Options: "
12463       "\n      '-attach AISObject'                 attach manipulator to AISObject"
12464       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
12465       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
12466       "\n      '-enableModes    {0|1}'             enable modes when attaching"
12467       "\n      '-detach'                           detach manipulator"
12468       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
12469       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
12470       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
12471       "\n      '-move x y z'                     - move attached object"
12472       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
12473       "\n      '-scale factor'                   - scale attached object"
12474       "\n      '-autoActivate      {0|1}'        - set activation on detection"
12475       "\n      '-followTranslation {0|1}'        - set following translation transform"
12476       "\n      '-followRotation    {0|1}'        - set following rotation transform"
12477       "\n      '-gap value'                      - set gap between sub-parts"
12478       "\n      '-part axis mode    {0|1}'        - set visual part"
12479       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
12480       "\n      '-size value'                     - set size of manipulator"
12481       "\n      '-zoomable {0|1}'                 - set zoom persistence",
12482     __FILE__, VManipulator, group);
12483
12484   theCommands.Add("vselprops",
12485     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
12486     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
12487     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
12488     "\n    -pickStrategy {first|topmost} : defines picking strategy"
12489     "\n                            'first'   to pick first acceptable (default)"
12490     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
12491     "\n    -pixTol    value        : sets up pixel tolerance"
12492     "\n    -dispMode  dispMode     : sets display mode for highlighting"
12493     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
12494     "\n    -color     {name|r g b} : sets highlight color"
12495     "\n    -transp    value        : sets transparency coefficient for highlight"
12496     "\n    -material  material     : sets highlight material"
12497     "\n    -print                  : prints current state of all mentioned parameters",
12498     __FILE__, VSelectionProperties, group);
12499
12500   theCommands.Add ("vseldump",
12501                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
12502                    "\n\t\t: Generate an image based on detection results:"
12503                    "\n\t\t:   depth       normalized depth values"
12504                    "\n\t\t:   unnormDepth unnormalized depth values"
12505                    "\n\t\t:   object      color of detected object"
12506                    "\n\t\t:   owner       color of detected owner"
12507                    "\n\t\t:   selMode     color of selection mode"
12508                    "\n\t\t:   entity      color of etected entity",
12509                    __FILE__, VDumpSelectionImage, group);
12510
12511 #if defined(_WIN32)
12512   theCommands.Add("vprogressive",
12513     "vprogressive",
12514     __FILE__, VProgressiveMode, group);
12515 #endif
12516 }