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