0030619: Draw Harness, ViewerTest - add continuous rendering option to vrepaint command
[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_CameraFrustum.hxx>
23 #include <AIS_ColorScale.hxx>
24 #include <AIS_Manipulator.hxx>
25 #include <AIS_RubberBand.hxx>
26 #include <AIS_Shape.hxx>
27 #include <AIS_InteractiveObject.hxx>
28 #include <AIS_ListOfInteractive.hxx>
29 #include <AIS_ListIteratorOfListOfInteractive.hxx>
30 #include <Aspect_Grid.hxx>
31 #include <DBRep.hxx>
32 #include <Draw_ProgressIndicator.hxx>
33 #include <Graphic3d_ArrayOfPolylines.hxx>
34 #include <Graphic3d_AspectMarker3d.hxx>
35 #include <Graphic3d_NameOfTextureEnv.hxx>
36 #include <Graphic3d_GraduatedTrihedron.hxx>
37 #include <Graphic3d_TextureEnv.hxx>
38 #include <Graphic3d_TextureParams.hxx>
39 #include <Graphic3d_TypeOfTextureFilter.hxx>
40 #include <Graphic3d_AspectFillArea3d.hxx>
41 #include <ViewerTest.hxx>
42 #include <ViewerTest_AutoUpdater.hxx>
43 #include <ViewerTest_EventManager.hxx>
44 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
45 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
46 #include <ViewerTest_CmdParser.hxx>
47 #include <V3d_AmbientLight.hxx>
48 #include <V3d_DirectionalLight.hxx>
49 #include <V3d_PositionalLight.hxx>
50 #include <V3d_SpotLight.hxx>
51 #include <Message_ProgressSentry.hxx>
52 #include <NCollection_DoubleMap.hxx>
53 #include <NCollection_List.hxx>
54 #include <NCollection_Vector.hxx>
55 #include <AIS_InteractiveContext.hxx>
56 #include <Draw_Interpretor.hxx>
57 #include <Draw.hxx>
58 #include <Draw_Appli.hxx>
59 #include <Image_AlienPixMap.hxx>
60 #include <Image_VideoRecorder.hxx>
61 #include <OpenGl_GraphicDriver.hxx>
62 #include <OSD.hxx>
63 #include <OSD_Timer.hxx>
64 #include <TColStd_HSequenceOfAsciiString.hxx>
65 #include <TColStd_SequenceOfInteger.hxx>
66 #include <TColStd_HSequenceOfReal.hxx>
67 #include <TColgp_Array1OfPnt2d.hxx>
68 #include <TColStd_MapOfAsciiString.hxx>
69 #include <Aspect_TypeOfLine.hxx>
70 #include <Image_Diff.hxx>
71 #include <Aspect_DisplayConnection.hxx>
72 #include <gp_Pnt.hxx>
73 #include <gp_Dir.hxx>
74 #include <gp_Pln.hxx>
75 #include <PrsMgr_PresentableObject.hxx>
76 #include <Graphic3d_ClipPlane.hxx>
77 #include <NCollection_DataMap.hxx>
78 #include <Graphic3d_Texture2Dmanual.hxx>
79 #include <Prs3d_ShadingAspect.hxx>
80 #include <Prs3d_Drawer.hxx>
81 #include <Prs3d_LineAspect.hxx>
82 #include <Prs3d_Root.hxx>
83 #include <Prs3d_Text.hxx>
84 #include <Select3D_SensitivePrimitiveArray.hxx>
85
86 #ifdef _WIN32
87 #undef DrawText
88 #endif
89
90 #include <cstdlib>
91
92 #if defined(_WIN32)
93   #include <WNT_WClass.hxx>
94   #include <WNT_Window.hxx>
95 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
96   #include <Cocoa_Window.hxx>
97 #else
98   #include <Xw_Window.hxx>
99   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
100   #include <X11/Xutil.h>
101   #include <tk.h>
102 #endif
103
104 // Auxiliary definitions
105 static const char THE_KEY_DELETE = 127;
106 static const char THE_KEY_ESCAPE = 27;
107
108 //==============================================================================
109 //  VIEWER GLOBAL VARIABLES
110 //==============================================================================
111
112 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
113 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
114
115 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
116 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
117
118 extern int VErase (Draw_Interpretor& theDI,
119                    Standard_Integer  theArgNb,
120                    const char**      theArgVec);
121
122 #if defined(_WIN32)
123 static Handle(WNT_Window)& VT_GetWindow() {
124   static Handle(WNT_Window) WNTWin;
125   return WNTWin;
126 }
127 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
128 static Handle(Cocoa_Window)& VT_GetWindow()
129 {
130   static Handle(Cocoa_Window) aWindow;
131   return aWindow;
132 }
133 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
134 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
135 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
136
137 #else
138 static Handle(Xw_Window)& VT_GetWindow(){
139   static Handle(Xw_Window) XWWin;
140   return XWWin;
141 }
142
143 static void VProcessEvents(ClientData,int);
144 #endif
145
146 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
147 {
148   static Handle(Aspect_DisplayConnection) aDisplayConnection;
149   return aDisplayConnection;
150 }
151
152 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
153 {
154   GetDisplayConnection() = theDisplayConnection;
155 }
156
157 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
158 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
159 {
160   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
161 #if defined(_WIN32)
162   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
163   if (!aWindow.IsNull())
164     return aWindow->HWindow();
165 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
166   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
167   if (!aWindow.IsNull())
168   return aWindow->XWindow();
169 #endif
170   return aWindowHandle;
171 }
172 #endif
173
174 //! Setting additional flag to store 2D mode of the View to avoid scene rotation by mouse/key events
175 class ViewerTest_V3dView : public V3d_View
176 {
177   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_V3dView, V3d_View)
178 public:
179   //! Initializes the view.
180   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType = V3d_ORTHOGRAPHIC,
181                       bool theIs2dMode = false)
182   : V3d_View (theViewer, theType), myIs2dMode (theIs2dMode) {}
183
184   //! Initializes the view by copying.
185   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
186   : V3d_View (theViewer, theView), myIs2dMode (false)
187   {
188     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (theView))
189     {
190       myIs2dMode = aV3dView->IsViewIn2DMode();
191     }
192   }
193
194   //! Returns true if 2D mode is set for the view
195   bool IsViewIn2DMode() const { return myIs2dMode; }
196
197   //! Sets 2D mode for the view
198   void SetView2DMode (bool the2dMode) { myIs2dMode = the2dMode; }
199
200 public:
201
202   //! Returns true if active view in 2D mode.
203   static bool IsCurrentViewIn2DMode()
204   {
205     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
206     {
207       return aV3dView->IsViewIn2DMode();
208     }
209     return false;
210   }
211
212   //! Set if active view in 2D mode.
213   static void SetCurrentView2DMode (bool theIs2d)
214   {
215     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
216     {
217       aV3dView->SetView2DMode (theIs2d);
218     }
219   }
220
221 private:
222
223   Standard_Boolean myIs2dMode; //!< 2D mode flag
224
225 };
226
227 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
228 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
229 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
230 static OpenGl_Caps ViewerTest_myDefaultCaps;
231
232 static void OSWindowSetup();
233
234 static struct
235 {
236   Quantity_Color FlatColor;
237   Quantity_Color GradientColor1;
238   Quantity_Color GradientColor2;
239   Aspect_GradientFillMethod FillMethod;
240 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
241
242 //==============================================================================
243 //  EVENT GLOBAL VARIABLES
244 //==============================================================================
245
246 static int Start_Rot = 0;
247 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
248 int X_Motion = 0; // Current cursor position
249 int Y_Motion = 0;
250 int X_ButtonPress = 0; // Last ButtonPress position
251 int Y_ButtonPress = 0;
252 Standard_Boolean IsDragged = Standard_False;
253 Standard_Boolean DragFirst = Standard_False;
254 Standard_Boolean TheIsAnimating = Standard_False;
255 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
256 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
257
258
259 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
260 {
261   static Handle(AIS_RubberBand) aBand;
262   if (aBand.IsNull())
263   {
264     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
265     aBand->SetDisplayMode (0);
266   }
267   return aBand;
268 }
269
270 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
271
272 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
273 {
274   static ViewerTest_MapOfAISManipulators aMap;
275   return aMap;
276 }
277
278 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
279 {
280   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
281   for (; anIt.More(); anIt.Next())
282   {
283     if (anIt.Value()->HasActiveMode())
284     {
285       return anIt.Value();
286     }
287   }
288   return NULL;
289 }
290
291 //==============================================================================
292
293 #ifdef _WIN32
294 static LRESULT WINAPI ViewerWindowProc(
295                                        HWND hwnd,
296                                        UINT uMsg,
297                                        WPARAM wParam,
298                                        LPARAM lParam );
299 static LRESULT WINAPI AdvViewerWindowProc(
300   HWND hwnd,
301   UINT uMsg,
302   WPARAM wParam,
303   LPARAM lParam );
304 #endif
305
306
307 //==============================================================================
308 //function : WClass
309 //purpose  :
310 //==============================================================================
311
312 const Handle(Standard_Transient)& ViewerTest::WClass()
313 {
314   static Handle(Standard_Transient) theWClass;
315 #if defined(_WIN32)
316   if (theWClass.IsNull())
317   {
318     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
319                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
320                                 ::LoadCursor (NULL, IDC_ARROW));
321   }
322 #endif
323   return theWClass;
324 }
325
326 //==============================================================================
327 //function : CreateName
328 //purpose  : Create numerical name for new object in theMap
329 //==============================================================================
330 template <typename ObjectType>
331 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
332                                     const TCollection_AsciiString& theDefaultString)
333 {
334   if (theObjectMap.IsEmpty())
335     return theDefaultString + TCollection_AsciiString(1);
336
337   Standard_Integer aNextKey = 1;
338   Standard_Boolean isFound = Standard_False;
339   while (!isFound)
340   {
341     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
342     // Look for objects with default names
343     if (theObjectMap.IsBound1(aStringKey))
344     {
345       aNextKey++;
346     }
347     else
348       isFound = Standard_True;
349   }
350
351   return theDefaultString + TCollection_AsciiString(aNextKey);
352 }
353
354 //==============================================================================
355 //structure : ViewerTest_Names
356 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
357 //==============================================================================
358 struct ViewerTest_Names
359 {
360 private:
361   TCollection_AsciiString myDriverName;
362   TCollection_AsciiString myViewerName;
363   TCollection_AsciiString myViewName;
364
365 public:
366
367   const TCollection_AsciiString& GetDriverName () const
368   {
369     return myDriverName;
370   }
371   void SetDriverName (const TCollection_AsciiString& theDriverName)
372   {
373     myDriverName = theDriverName;
374   }
375   const TCollection_AsciiString& GetViewerName () const
376   {
377     return myViewerName;
378   }
379   void SetViewerName (const TCollection_AsciiString& theViewerName)
380   {
381     myViewerName = theViewerName;
382   }
383   const TCollection_AsciiString& GetViewName () const
384   {
385     return myViewName;
386   }
387   void SetViewName (const TCollection_AsciiString& theViewName)
388   {
389     myViewName = theViewName;
390   }
391
392   //===========================================================================
393   //function : Constructor for ViewerTest_Names
394   //purpose  : Get view, viewer, driver names from custom string
395   //===========================================================================
396
397   ViewerTest_Names (const TCollection_AsciiString& theInputString)
398   {
399     TCollection_AsciiString aName(theInputString);
400     if (theInputString.IsEmpty())
401     {
402       // Get current configuration
403       if (ViewerTest_myDrivers.IsEmpty())
404         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
405           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
406       else
407         myDriverName = ViewerTest_myDrivers.Find2
408         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
409
410       if(ViewerTest_myContexts.IsEmpty())
411       {
412         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
413           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
414       }
415       else
416       {
417         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
418       }
419
420       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
421     }
422     else
423     {
424       // There is at least view name
425       Standard_Integer aParserNumber = 0;
426       for (Standard_Integer i = 0; i < 3; ++i)
427       {
428         Standard_Integer aParserPos = aName.SearchFromEnd("/");
429         if(aParserPos != -1)
430         {
431           aParserNumber++;
432           aName.Split(aParserPos-1);
433         }
434         else
435           break;
436       }
437       if (aParserNumber == 0)
438       {
439         // Only view name
440         if (!ViewerTest::GetAISContext().IsNull())
441         {
442           myDriverName = ViewerTest_myDrivers.Find2
443           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
444           myViewerName = ViewerTest_myContexts.Find2
445           (ViewerTest::GetAISContext());
446         }
447         else
448         {
449           // There is no opened contexts here, need to create names for viewer and driver
450           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
451             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
452
453           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
454             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
455         }
456         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
457       }
458       else if (aParserNumber == 1)
459       {
460         // Here is viewerName/viewName
461         if (!ViewerTest::GetAISContext().IsNull())
462           myDriverName = ViewerTest_myDrivers.Find2
463           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
464         else
465         {
466           // There is no opened contexts here, need to create name for driver
467           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
468             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
469         }
470         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
471
472         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
473       }
474       else
475       {
476         //Here is driverName/viewerName/viewName
477         myDriverName = TCollection_AsciiString(aName);
478
479         TCollection_AsciiString aViewerName(theInputString);
480         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
481         myViewerName = TCollection_AsciiString(aViewerName);
482
483         myViewName = TCollection_AsciiString(theInputString);
484       }
485     }
486   }
487 };
488
489 //==============================================================================
490 //function : FindContextByView
491 //purpose  : Find AIS_InteractiveContext by View
492 //==============================================================================
493
494 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
495 {
496   Handle(AIS_InteractiveContext) anAISContext;
497
498   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
499        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
500   {
501     if (anIter.Value()->CurrentViewer() == theView->Viewer())
502        return anIter.Key2();
503   }
504   return anAISContext;
505 }
506
507
508 //==============================================================================
509 //function : SetWindowTitle
510 //purpose  : Set window title
511 //==============================================================================
512
513 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
514                      Standard_CString theTitle)
515 {
516 #if defined(_WIN32)
517   const TCollection_ExtendedString theTitleW (theTitle);
518   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
519 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
520   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
521 #else
522   if(GetDisplayConnection()->GetDisplay())
523   {
524     Window aWindow =
525       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
526     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
527   }
528 #endif
529 }
530
531 //==============================================================================
532 //function : IsWindowOverlapped
533 //purpose  : Check if theWindow overlapp another view
534 //==============================================================================
535
536 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
537                                      const Standard_Integer thePxTop,
538                                      const Standard_Integer thePxRight,
539                                      const Standard_Integer thePxBottom,
540                                      TCollection_AsciiString& theViewId)
541 {
542   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
543       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
544   {
545     Standard_Integer aTop = 0,
546       aLeft = 0,
547       aRight = 0,
548       aBottom = 0;
549     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
550     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
551         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
552         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
553         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
554     {
555       theViewId = anIter.Key1();
556       return Standard_True;
557     }
558   }
559   return Standard_False;
560 }
561
562 // Workaround: to create and delete non-orthographic views outside ViewerTest
563 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
564 {
565   ViewerTest_myViews.UnBind1 (theName);
566 }
567
568 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
569                                const Handle(V3d_View)& theView)
570 {
571   ViewerTest_myViews.Bind (theName, theView);
572 }
573
574 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
575 {
576   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
577 }
578
579 //! Auxiliary tool performing continuous redraws of specified window.
580 class ViewerTest_ContinuousRedrawer
581 {
582 public:
583   //! Return global instance.
584   static ViewerTest_ContinuousRedrawer& Instance()
585   {
586     static ViewerTest_ContinuousRedrawer aRedrawer;
587     return aRedrawer;
588   }
589 public:
590
591   //! Destructor.
592   ~ViewerTest_ContinuousRedrawer()
593   {
594     Stop();
595   }
596
597   //! Start thread.
598   void Start (const Handle(Aspect_Window)& theWindow,
599               Standard_Real theTargetFps)
600   {
601     if (myWindow != theWindow
602      || myTargetFps != theTargetFps)
603     {
604       Stop();
605       myWindow = theWindow;
606       myTargetFps = theTargetFps;
607     }
608     if (myThread.GetId() == 0)
609     {
610       myToStop = false;
611       myThread.Run (this);
612     }
613   }
614
615   //! Stop thread.
616   void Stop (const Handle(Aspect_Window)& theWindow = NULL)
617   {
618     if (!theWindow.IsNull()
619       && myWindow != theWindow)
620     {
621       return;
622     }
623
624     {
625       Standard_Mutex::Sentry aLock (myMutex);
626       myToStop = true;
627     }
628     myThread.Wait();
629     myToStop = false;
630     myWindow.Nullify();
631   }
632
633 private:
634
635   //! Thread loop.
636   void doThreadLoop()
637   {
638     Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
639     OSD_Timer aTimer;
640     aTimer.Start();
641     Standard_Real aTimeOld = 0.0;
642     const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
643     for (;;)
644     {
645       {
646         Standard_Mutex::Sentry aLock (myMutex);
647         if (myToStop)
648         {
649           return;
650         }
651       }
652       if (myTargetFps > 0.0)
653       {
654         const Standard_Real aTimeNew  = aTimer.ElapsedTime();
655         const Standard_Real aDuration = aTimeNew - aTimeOld;
656         if (aDuration >= aTargetDur)
657         {
658           myWindow->InvalidateContent (aDisp);
659           aTimeOld = aTimeNew;
660         }
661       }
662       else
663       {
664         myWindow->InvalidateContent (aDisp);
665       }
666
667       OSD::MilliSecSleep (1);
668     }
669   }
670
671   //! Thread creation callback.
672   static Standard_Address doThreadWrapper (Standard_Address theData)
673   {
674     ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
675     aThis->doThreadLoop();
676     return 0;
677   }
678
679   //! Empty constructor.
680   ViewerTest_ContinuousRedrawer()
681   : myThread (doThreadWrapper),
682     myTargetFps (0.0),
683     myToStop (false) {}
684
685 private:
686   Handle(Aspect_Window) myWindow;
687   OSD_Thread      myThread;
688   Standard_Mutex  myMutex;
689   Standard_Real   myTargetFps;
690   volatile bool   myToStop;
691 };
692
693 //==============================================================================
694 //function : ViewerInit
695 //purpose  : Create the window viewer and initialize all the global variable
696 //==============================================================================
697
698 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
699                                                 const Standard_Integer thePxTop,
700                                                 const Standard_Integer thePxWidth,
701                                                 const Standard_Integer thePxHeight,
702                                                 const TCollection_AsciiString& theViewName,
703                                                 const TCollection_AsciiString& theDisplayName,
704                                                 const Handle(V3d_View)& theViewToClone)
705 {
706   // Default position and dimension of the viewer window.
707   // Note that left top corner is set to be sufficiently small to have
708   // window fit in the small screens (actual for remote desktops, see #23003).
709   // The position corresponds to the window's client area, thus some
710   // gap is added for window frame to be visible.
711   Standard_Integer aPxLeft   = 20;
712   Standard_Integer aPxTop    = 40;
713   Standard_Integer aPxWidth  = 409;
714   Standard_Integer aPxHeight = 409;
715   Standard_Boolean toCreateViewer = Standard_False;
716   if (!theViewToClone.IsNull())
717   {
718     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
719   }
720
721   Handle(OpenGl_GraphicDriver) aGraphicDriver;
722   ViewerTest_Names aViewNames(theViewName);
723   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
724     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
725
726   if (thePxLeft != 0)
727     aPxLeft = thePxLeft;
728   if (thePxTop != 0)
729     aPxTop = thePxTop;
730   if (thePxWidth != 0)
731     aPxWidth = thePxWidth;
732   if (thePxHeight != 0)
733     aPxHeight = thePxHeight;
734
735   // Get graphic driver (create it or get from another view)
736   const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
737   if (isNewDriver)
738   {
739     // Get connection string
740   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
741     if (!theDisplayName.IsEmpty())
742     {
743       SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
744     }
745     else
746     {
747       ::Display* aDispX = NULL;
748       // create dedicated display connection instead of reusing Tk connection
749       // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
750       /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
751       Tcl_Interp* aTclInterp = aCommands.Interp();
752       Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
753       aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
754       SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
755     }
756   #else
757     (void)theDisplayName; // avoid warning on unused argument
758     SetDisplayConnection (new Aspect_DisplayConnection ());
759   #endif
760
761     if (Draw_VirtualWindows)
762     {
763       // don't waste the time waiting for VSync when window is not displayed on the screen
764       ViewerTest_myDefaultCaps.swapInterval = 0;
765       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
766       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
767     }
768     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
769     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
770
771     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
772     toCreateViewer = Standard_True;
773   }
774   else
775   {
776     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
777   }
778
779   //Dispose the window if input parameters are default
780   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
781   {
782     Standard_Integer aTop = 0,
783                      aLeft = 0,
784                      aRight = 0,
785                      aBottom = 0,
786                      aScreenWidth = 0,
787                      aScreenHeight = 0;
788
789     // Get screen resolution
790 #if defined(_WIN32) || defined(__WIN32__)
791     RECT aWindowSize;
792     GetClientRect(GetDesktopWindow(), &aWindowSize);
793     aScreenHeight = aWindowSize.bottom;
794     aScreenWidth = aWindowSize.right;
795 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
796     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
797 #else
798     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
799     aScreenWidth = WidthOfScreen(aScreen);
800     aScreenHeight = HeightOfScreen(aScreen);
801 #endif
802
803     TCollection_AsciiString anOverlappedViewId("");
804
805     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
806     {
807       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
808
809       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
810         && aRight + 2*aPxWidth + 40 > aScreenWidth)
811       {
812         if (aBottom + aPxHeight + 40 > aScreenHeight)
813         {
814           aPxLeft = 20;
815           aPxTop = 40;
816           break;
817         }
818         aPxLeft = 20;
819         aPxTop = aBottom + 40;
820       }
821       else
822         aPxLeft = aRight + 20;
823     }
824   }
825
826   // Get viewer name
827   TCollection_AsciiString aTitle("3D View - ");
828   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
829
830   // Change name of current active window
831   if (!ViewerTest::CurrentView().IsNull())
832   {
833     TCollection_AsciiString anActiveWindowTitle("3D View - ");
834     anActiveWindowTitle = anActiveWindowTitle
835       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
836     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
837   }
838
839   // Create viewer
840   Handle(V3d_Viewer) a3DViewer;
841   // If it's the single view, we first look for empty context
842   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
843   {
844     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
845       anIter(ViewerTest_myContexts);
846     if (anIter.More())
847       ViewerTest::SetAISContext (anIter.Value());
848     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
849   }
850   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
851   {
852     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
853     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
854   }
855   else if (a3DViewer.IsNull())
856   {
857     toCreateViewer = Standard_True;
858     a3DViewer = new V3d_Viewer(aGraphicDriver);
859     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
860     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
861                                            ViewerTest_DefaultBackground.GradientColor2,
862                                            ViewerTest_DefaultBackground.FillMethod);
863   }
864
865   // AIS context setup
866   if (ViewerTest::GetAISContext().IsNull() ||
867       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
868   {
869     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
870     ViewerTest::SetAISContext (aContext);
871     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
872   }
873   else
874   {
875     ViewerTest::ResetEventManager();
876   }
877
878   // Create window
879 #if defined(_WIN32)
880   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
881                                     Handle(WNT_WClass)::DownCast (WClass()),
882                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
883                                     aPxLeft, aPxTop,
884                                     aPxWidth, aPxHeight,
885                                     Quantity_NOC_BLACK);
886 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
887   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
888                                      aPxLeft, aPxTop,
889                                      aPxWidth, aPxHeight);
890   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
891 #else
892   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
893                                   aTitle.ToCString(),
894                                   aPxLeft, aPxTop,
895                                   aPxWidth, aPxHeight);
896 #endif
897   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
898
899   // View setup
900   Handle(V3d_View) aView;
901   if (!theViewToClone.IsNull())
902   {
903     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
904   }
905   else
906   {
907     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
908   }
909
910   aView->SetWindow (VT_GetWindow());
911   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
912
913   ViewerTest::CurrentView(aView);
914   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
915
916   // Setup for X11 or NT
917   OSWindowSetup();
918
919   // Set parameters for V3d_View and V3d_Viewer
920   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
921   aV3dView->SetComputedMode(Standard_False);
922
923   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
924   if (toCreateViewer)
925   {
926     a3DViewer->SetDefaultLights();
927     a3DViewer->SetLightOn();
928   }
929
930 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
931   if (isNewDriver)
932   {
933     ::Display* aDispX = GetDisplayConnection()->GetDisplay();
934     Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
935   }
936 #endif
937
938   VT_GetWindow()->Map();
939
940   // Set the handle of created view in the event manager
941   ViewerTest::ResetEventManager();
942
943   ViewerTest::CurrentView()->Redraw();
944
945   aView.Nullify();
946   a3DViewer.Nullify();
947
948   return aViewNames.GetViewName();
949 }
950
951 //==============================================================================
952 //function : RedrawAllViews
953 //purpose  : Redraw all created views
954 //==============================================================================
955 void ViewerTest::RedrawAllViews()
956 {
957   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
958   for (; aViewIt.More(); aViewIt.Next())
959   {
960     const Handle(V3d_View)& aView = aViewIt.Key2();
961     aView->Redraw();
962   }
963 }
964
965 //==============================================================================
966 //function : Vinit
967 //purpose  : Create the window viewer and initialize all the global variable
968 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
969 //==============================================================================
970
971 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
972 {
973   TCollection_AsciiString aViewName, aDisplayName;
974   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
975   Handle(V3d_View) aCopyFrom;
976   TCollection_AsciiString aName, aValue;
977   int is2dMode = -1;
978   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
979   {
980     const TCollection_AsciiString anArg = theArgVec[anArgIt];
981     TCollection_AsciiString anArgCase = anArg;
982     anArgCase.LowerCase();
983     if (anArgIt + 1 < theArgsNb
984      && anArgCase == "-name")
985     {
986       aViewName = theArgVec[++anArgIt];
987     }
988     else if (anArgIt + 1 < theArgsNb
989           && (anArgCase == "-left"
990            || anArgCase == "-l"))
991     {
992       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
993     }
994     else if (anArgIt + 1 < theArgsNb
995           && (anArgCase == "-top"
996            || anArgCase == "-t"))
997     {
998       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
999     }
1000     else if (anArgIt + 1 < theArgsNb
1001           && (anArgCase == "-width"
1002            || anArgCase == "-w"))
1003     {
1004       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
1005     }
1006     else if (anArgIt + 1 < theArgsNb
1007           && (anArgCase == "-height"
1008            || anArgCase == "-h"))
1009     {
1010       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
1011     }
1012     else if (anArgCase == "-exitonclose")
1013     {
1014       Draw_ToExitOnCloseView = true;
1015       if (anArgIt + 1 < theArgsNb
1016        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
1017       {
1018         ++anArgIt;
1019       }
1020     }
1021     else if (anArgCase == "-closeonescape"
1022           || anArgCase == "-closeonesc")
1023     {
1024       Draw_ToCloseViewOnEsc = true;
1025       if (anArgIt + 1 < theArgsNb
1026        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
1027       {
1028         ++anArgIt;
1029       }
1030     }
1031     else if (anArgCase == "-2d_mode"
1032           || anArgCase == "-2dmode"
1033           || anArgCase == "-2d")
1034     {
1035       bool toEnable = true;
1036       if (anArgIt + 1 < theArgsNb
1037        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
1038       {
1039         ++anArgIt;
1040       }
1041       is2dMode = toEnable ? 1 : 0;
1042     }
1043     else if (anArgIt + 1 < theArgsNb
1044           && (anArgCase == "-disp"
1045            || anArgCase == "-display"))
1046     {
1047       aDisplayName = theArgVec[++anArgIt];
1048     }
1049     else if (!ViewerTest::CurrentView().IsNull()
1050           &&  aCopyFrom.IsNull()
1051           && (anArgCase == "-copy"
1052            || anArgCase == "-clone"
1053            || anArgCase == "-cloneactive"
1054            || anArgCase == "-cloneactiveview"))
1055     {
1056       aCopyFrom = ViewerTest::CurrentView();
1057     }
1058     // old syntax
1059     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
1060     {
1061       aName.LowerCase();
1062       if (aName == "name")
1063       {
1064         aViewName = aValue;
1065       }
1066       else if (aName == "l"
1067             || aName == "left")
1068       {
1069         aPxLeft = aValue.IntegerValue();
1070       }
1071       else if (aName == "t"
1072             || aName == "top")
1073       {
1074         aPxTop = aValue.IntegerValue();
1075       }
1076       else if (aName == "disp"
1077             || aName == "display")
1078       {
1079         aDisplayName = aValue;
1080       }
1081       else if (aName == "w"
1082             || aName == "width")
1083       {
1084         aPxWidth = aValue.IntegerValue();
1085       }
1086       else if (aName == "h"
1087             || aName == "height")
1088       {
1089         aPxHeight = aValue.IntegerValue();
1090       }
1091       else
1092       {
1093         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
1094         return 1;
1095       }
1096     }
1097     else if (aViewName.IsEmpty())
1098     {
1099       aViewName = anArg;
1100     }
1101     else
1102     {
1103       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
1104       return 1;
1105     }
1106   }
1107
1108 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
1109   if (!aDisplayName.IsEmpty())
1110   {
1111     aDisplayName.Clear();
1112     std::cout << "Warning: display parameter will be ignored.\n";
1113   }
1114 #endif
1115
1116   ViewerTest_Names aViewNames (aViewName);
1117   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
1118   {
1119     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
1120     theDi.Eval (aCommand.ToCString());
1121     if (is2dMode != -1)
1122     {
1123       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1124     }
1125     return 0;
1126   }
1127
1128   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
1129                                                             aViewName, aDisplayName, aCopyFrom);
1130   if (is2dMode != -1)
1131   {
1132     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1133   }
1134   theDi << aViewId;
1135   return 0;
1136 }
1137
1138 //! Parse HLR algo type.
1139 static Standard_Boolean parseHlrAlgoType (const char* theName,
1140                                           Prs3d_TypeOfHLR& theType)
1141 {
1142   TCollection_AsciiString aName (theName);
1143   aName.LowerCase();
1144   if (aName == "polyalgo")
1145   {
1146     theType = Prs3d_TOH_PolyAlgo;
1147   }
1148   else if (aName == "algo")
1149   {
1150     theType = Prs3d_TOH_Algo;
1151   }
1152   else
1153   {
1154     return Standard_False;
1155   }
1156   return Standard_True;
1157 }
1158
1159 //==============================================================================
1160 //function : VHLR
1161 //purpose  : hidden lines removal algorithm
1162 //==============================================================================
1163
1164 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1165 {
1166   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1167   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1168   if (aView.IsNull())
1169   {
1170     std::cerr << "Error: No opened viewer!\n";
1171     return 1;
1172   }
1173
1174   Standard_Boolean hasHlrOnArg = Standard_False;
1175   Standard_Boolean hasShowHiddenArg = Standard_False;
1176   Standard_Boolean isHLROn = Standard_False;
1177   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
1178   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
1179   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1180   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1181   {
1182     TCollection_AsciiString anArg (argv[anArgIter]);
1183     anArg.LowerCase();
1184     if (anUpdateTool.parseRedrawMode (anArg))
1185     {
1186       continue;
1187     }
1188     else if (anArg == "-showhidden"
1189           && anArgIter + 1 < argc
1190           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
1191     {
1192       ++anArgIter;
1193       hasShowHiddenArg = Standard_True;
1194       continue;
1195     }
1196     else if ((anArg == "-type"
1197            || anArg == "-algo"
1198            || anArg == "-algotype")
1199           && anArgIter + 1 < argc
1200           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1201     {
1202       ++anArgIter;
1203       continue;
1204     }
1205     else if (!hasHlrOnArg
1206           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
1207     {
1208       hasHlrOnArg = Standard_True;
1209       continue;
1210     }
1211     // old syntax
1212     else if (!hasShowHiddenArg
1213           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
1214     {
1215       hasShowHiddenArg = Standard_True;
1216       continue;
1217     }
1218     else
1219     {
1220       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
1221       return 1;
1222     }
1223   }
1224   if (!hasHlrOnArg)
1225   {
1226     di << "HLR:        " << aView->ComputedMode() << "\n";
1227     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1228     di << "HlrAlgo:    ";
1229     switch (aCtx->DefaultDrawer()->TypeOfHLR())
1230     {
1231       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
1232       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1233       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
1234     }
1235     anUpdateTool.Invalidate();
1236     return 0;
1237   }
1238
1239   Standard_Boolean toRecompute = Standard_False;
1240   if (aTypeOfHLR != Prs3d_TOH_NotSet
1241    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
1242   {
1243     toRecompute = Standard_True;
1244     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1245   }
1246   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1247   {
1248     toRecompute = Standard_True;
1249     if (toShowHidden)
1250     {
1251       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
1252     }
1253     else
1254     {
1255       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
1256     }
1257   }
1258
1259   // redisplay shapes
1260   if (aView->ComputedMode() && isHLROn && toRecompute)
1261   {
1262     AIS_ListOfInteractive aListOfShapes;
1263     aCtx->DisplayedObjects (aListOfShapes);
1264     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
1265     {
1266       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
1267       {
1268         aCtx->Redisplay (aShape, Standard_False);
1269       }
1270     }
1271   }
1272
1273   aView->SetComputedMode (isHLROn);
1274   return 0;
1275 }
1276
1277 //==============================================================================
1278 //function : VHLRType
1279 //purpose  : change type of using HLR algorithm
1280 //==============================================================================
1281
1282 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1283 {
1284   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1285   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1286   if (aView.IsNull())
1287   {
1288     std::cerr << "Error: No opened viewer!\n";
1289     return 1;
1290   }
1291
1292   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1293   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1294   AIS_ListOfInteractive aListOfShapes;
1295   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1296   {
1297     TCollection_AsciiString anArg (argv[anArgIter]);
1298     anArg.LowerCase();
1299     if (anUpdateTool.parseRedrawMode (anArg))
1300     {
1301       continue;
1302     }
1303     else if ((anArg == "-type"
1304            || anArg == "-algo"
1305            || anArg == "-algotype")
1306           && anArgIter + 1 < argc
1307           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1308     {
1309       ++anArgIter;
1310       continue;
1311     }
1312     // old syntax
1313     else if (aTypeOfHLR == Prs3d_TOH_NotSet
1314           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1315     {
1316       continue;
1317     }
1318     else
1319     {
1320       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1321       TCollection_AsciiString aName (argv[anArgIter]);
1322       if (!aMap.IsBound2 (aName))
1323       {
1324         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
1325         return 1;
1326       }
1327
1328       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1329       if (aShape.IsNull())
1330       {
1331         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
1332         return 1;
1333       }
1334       aListOfShapes.Append (aShape);
1335       continue;
1336     }
1337   }
1338   if (aTypeOfHLR == Prs3d_TOH_NotSet)
1339   {
1340     std::cout << "Syntax error: wrong number of arguments!\n";
1341     return 1;
1342   }
1343
1344   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1345   if (isGlobal)
1346   {
1347     aCtx->DisplayedObjects (aListOfShapes);
1348     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1349   }
1350
1351   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1352   {
1353     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1354     if (aShape.IsNull())
1355     {
1356       continue;
1357     }
1358
1359     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1360                             && aView->ComputedMode();
1361     if (!isGlobal
1362      || aShape->TypeOfHLR() != aTypeOfHLR)
1363     {
1364       aShape->SetTypeOfHLR (aTypeOfHLR);
1365     }
1366     if (toUpdateShape)
1367     {
1368       aCtx->Redisplay (aShape, Standard_False);
1369     }
1370   }
1371   return 0;
1372 }
1373
1374 //==============================================================================
1375 //function : FindViewIdByWindowHandle
1376 //purpose  : Find theView Id in the map of views by window handle
1377 //==============================================================================
1378 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1379 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1380 {
1381   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1382        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1383   {
1384     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1385     if (aWindowHandle == theWindowHandle)
1386       return anIter.Key1();
1387   }
1388   return TCollection_AsciiString("");
1389 }
1390 #endif
1391
1392 //! Make the view active
1393 void ActivateView (const TCollection_AsciiString& theViewName,
1394                    Standard_Boolean theToUpdate = Standard_True)
1395 {
1396   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1397   if (aView.IsNull())
1398   {
1399     return;
1400   }
1401
1402   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1403   if (!anAISContext.IsNull())
1404   {
1405     if (!ViewerTest::CurrentView().IsNull())
1406     {
1407       TCollection_AsciiString aTitle("3D View - ");
1408       aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1409       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1410     }
1411
1412     ViewerTest::CurrentView (aView);
1413     ViewerTest::SetAISContext (anAISContext);
1414     TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
1415     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1416 #if defined(_WIN32)
1417     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1418 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1419     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1420 #else
1421     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1422 #endif
1423     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1424     if (theToUpdate)
1425     {
1426       ViewerTest::CurrentView()->Redraw();
1427     }
1428   }
1429 }
1430
1431 //==============================================================================
1432 //function : RemoveView
1433 //purpose  :
1434 //==============================================================================
1435 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1436                              const Standard_Boolean  theToRemoveContext)
1437 {
1438   if (!ViewerTest_myViews.IsBound2 (theView))
1439   {
1440     return;
1441   }
1442
1443   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1444   RemoveView (aViewName, theToRemoveContext);
1445 }
1446
1447 //==============================================================================
1448 //function : RemoveView
1449 //purpose  : Close and remove view from display, clear maps if neccessary
1450 //==============================================================================
1451 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1452 {
1453   if (!ViewerTest_myViews.IsBound1(theViewName))
1454   {
1455     cout << "Wrong view name\n";
1456     return;
1457   }
1458
1459   // Activate another view if it's active now
1460   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1461   {
1462     if (ViewerTest_myViews.Extent() > 1)
1463     {
1464       TCollection_AsciiString aNewViewName;
1465       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1466            anIter.More(); anIter.Next())
1467       {
1468         if (anIter.Key1() != theViewName)
1469         {
1470           aNewViewName = anIter.Key1();
1471           break;
1472         }
1473       }
1474       ActivateView (aNewViewName);
1475     }
1476     else
1477     {
1478       VT_GetWindow().Nullify();
1479       ViewerTest::CurrentView (Handle(V3d_View)());
1480       if (isContextRemoved)
1481       {
1482         Handle(AIS_InteractiveContext) anEmptyContext;
1483         ViewerTest::SetAISContext(anEmptyContext);
1484       }
1485     }
1486   }
1487
1488   // Delete view
1489   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1490   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1491   ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
1492   aRedrawer.Stop (aView->Window());
1493
1494   // Remove view resources
1495   ViewerTest_myViews.UnBind1(theViewName);
1496   aView->Window()->Unmap();
1497   aView->Remove();
1498
1499 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1500   XFlush (GetDisplayConnection()->GetDisplay());
1501 #endif
1502
1503   // Keep context opened only if the closed view is last to avoid
1504   // unused empty contexts
1505   if (!aCurrentContext.IsNull())
1506   {
1507     // Check if there are more difined views in the viewer
1508     aCurrentContext->CurrentViewer()->InitDefinedViews();
1509     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1510     {
1511       // Remove driver if there is no viewers that use it
1512       Standard_Boolean isRemoveDriver = Standard_True;
1513       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1514           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1515       {
1516         if (aCurrentContext != anIter.Key2() &&
1517           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1518         {
1519           isRemoveDriver = Standard_False;
1520           break;
1521         }
1522       }
1523
1524       aCurrentContext->RemoveAll (Standard_False);
1525       if(isRemoveDriver)
1526       {
1527         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1528       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1529         Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1530       #endif
1531       }
1532
1533       ViewerTest_myContexts.UnBind2(aCurrentContext);
1534     }
1535   }
1536   cout << "3D View - " << theViewName << " was deleted.\n";
1537   if (Draw_ToExitOnCloseView)
1538   {
1539     Draw_Interprete ("exit");
1540   }
1541 }
1542
1543 //==============================================================================
1544 //function : VClose
1545 //purpose  : Remove the view defined by its name
1546 //==============================================================================
1547
1548 static int VClose (Draw_Interpretor& /*theDi*/,
1549                    Standard_Integer  theArgsNb,
1550                    const char**      theArgVec)
1551 {
1552   NCollection_List<TCollection_AsciiString> aViewList;
1553   if (theArgsNb > 1)
1554   {
1555     TCollection_AsciiString anArg (theArgVec[1]);
1556     anArg.UpperCase();
1557     if (anArg.IsEqual ("ALL")
1558      || anArg.IsEqual ("*"))
1559     {
1560       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1561            anIter.More(); anIter.Next())
1562       {
1563         aViewList.Append (anIter.Key1());
1564       }
1565       if (aViewList.IsEmpty())
1566       {
1567         std::cout << "No view to close\n";
1568         return 0;
1569       }
1570     }
1571     else
1572     {
1573       ViewerTest_Names aViewName (theArgVec[1]);
1574       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1575       {
1576         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1577         return 1;
1578       }
1579       aViewList.Append (aViewName.GetViewName());
1580     }
1581   }
1582   else
1583   {
1584     // close active view
1585     if (ViewerTest::CurrentView().IsNull())
1586     {
1587       std::cerr << "No active view!\n";
1588       return 1;
1589     }
1590     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1591   }
1592
1593   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1594   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1595        anIter.More(); anIter.Next())
1596   {
1597     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1598   }
1599
1600   return 0;
1601 }
1602
1603 //==============================================================================
1604 //function : VActivate
1605 //purpose  : Activate the view defined by its ID
1606 //==============================================================================
1607
1608 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1609 {
1610   if (theArgsNb == 1)
1611   {
1612     theDi.Eval("vviewlist");
1613     return 0;
1614   }
1615
1616   TCollection_AsciiString aNameString;
1617   Standard_Boolean toUpdate = Standard_True;
1618   Standard_Boolean toActivate = Standard_True;
1619   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
1620   {
1621     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1622     anArg.LowerCase();
1623     if (toUpdate
1624      && anArg == "-noupdate")
1625     {
1626       toUpdate = Standard_False;
1627     }
1628     else if (toActivate
1629           && aNameString.IsEmpty()
1630           && anArg == "none")
1631     {
1632       TCollection_AsciiString aTitle("3D View - ");
1633       aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1634       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1635       VT_GetWindow().Nullify();
1636       ViewerTest::CurrentView (Handle(V3d_View)());
1637       ViewerTest::ResetEventManager();
1638       theDi << theArgVec[0] << ": all views are inactive\n";
1639       toActivate = Standard_False;
1640     }
1641     else if (toActivate
1642           && aNameString.IsEmpty())
1643     {
1644       aNameString = theArgVec[anArgIter];
1645     }
1646     else
1647     {
1648       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
1649       return 1;
1650     }
1651   }
1652
1653   if (!toActivate)
1654   {
1655     return 0;
1656   }
1657   else if (aNameString.IsEmpty())
1658   {
1659     std::cout << "Syntax error: wrong number of arguments\n";
1660     return 1;
1661   }
1662
1663   // Check if this view exists in the viewer with the driver
1664   ViewerTest_Names aViewNames (aNameString);
1665   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1666   {
1667     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
1668     return 1;
1669   }
1670
1671   // Check if it is active already
1672   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1673   {
1674     theDi << theArgVec[0] << ": the view is active already\n";
1675     return 0;
1676   }
1677
1678   ActivateView (aViewNames.GetViewName(), toUpdate);
1679   return 0;
1680 }
1681
1682 //==============================================================================
1683 //function : VViewList
1684 //purpose  : Print current list of views per viewer and graphic driver ID
1685 //           shared between viewers
1686 //==============================================================================
1687
1688 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1689 {
1690   if (theArgsNb > 2)
1691   {
1692     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1693           << "Usage: " << theArgVec[0] << " name";
1694     return 1;
1695   }
1696   if (ViewerTest_myContexts.Size() < 1)
1697     return 0;
1698
1699   Standard_Boolean isTreeView =
1700     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1701
1702   if (isTreeView)
1703   {
1704     theDi << theArgVec[0] <<":\n";
1705   }
1706
1707   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1708        aDriverIter.More(); aDriverIter.Next())
1709   {
1710     if (isTreeView)
1711       theDi << aDriverIter.Key1() << ":\n";
1712
1713     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1714       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1715     {
1716       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1717       {
1718         if (isTreeView)
1719         {
1720           TCollection_AsciiString aContextName(aContextIter.Key1());
1721           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1722         }
1723
1724         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1725              aViewIter.More(); aViewIter.Next())
1726         {
1727           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1728           {
1729             TCollection_AsciiString aViewName(aViewIter.Key1());
1730             if (isTreeView)
1731             {
1732               if (aViewIter.Value() == ViewerTest::CurrentView())
1733                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1734               else
1735                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1736             }
1737             else
1738             {
1739               theDi << aViewName << " ";
1740             }
1741           }
1742         }
1743       }
1744     }
1745   }
1746   return 0;
1747 }
1748
1749 //==============================================================================
1750 //function : VT_ProcessKeyPress
1751 //purpose  : Handle KeyPress event from a CString
1752 //==============================================================================
1753 void VT_ProcessKeyPress (const char* buf_ret)
1754 {
1755   //cout << "KeyPress" << endl;
1756   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1757   // Letter in alphabetic order
1758
1759   if (!strcasecmp (buf_ret, "A")
1760    && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1761   {
1762     // AXO
1763     aView->SetProj(V3d_XposYnegZpos);
1764   }
1765   else if (!strcasecmp (buf_ret, "D")
1766         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1767   {
1768     // Reset
1769     aView->Reset();
1770   }
1771   else if (!strcasecmp (buf_ret, "F"))
1772   {
1773     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1774     {
1775       ViewerTest::GetAISContext()->FitSelected (aView);
1776     }
1777     else
1778     {
1779       // FitAll
1780       aView->FitAll();
1781     }
1782   }
1783   else if (!strcasecmp (buf_ret, "H"))
1784   {
1785     // HLR
1786     std::cout << "HLR" << std::endl;
1787     aView->SetComputedMode (!aView->ComputedMode());
1788     aView->Redraw();
1789   }
1790   else if (!strcasecmp (buf_ret, "P"))
1791   {
1792     // Type of HLR
1793     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1794     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1795       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1796     else
1797       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1798     if (aContext->NbSelected()==0)
1799     {
1800       AIS_ListOfInteractive aListOfShapes;
1801       aContext->DisplayedObjects(aListOfShapes);
1802       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1803         anIter.More(); anIter.Next())
1804       {
1805         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1806         if (aShape.IsNull())
1807           continue;
1808         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1809           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1810         else
1811           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1812         aContext->Redisplay (aShape, Standard_False);
1813       }
1814     }
1815     else
1816     {
1817       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1818       {
1819         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1820         if (aShape.IsNull())
1821           continue;
1822         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1823           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1824         else
1825           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1826         aContext->Redisplay (aShape, Standard_False);
1827       }
1828     }
1829
1830     aContext->UpdateCurrentViewer();
1831
1832   }
1833   else if (!strcasecmp (buf_ret, "S"))
1834   {
1835     std::cout << "setup Shaded display mode" << std::endl;
1836
1837     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1838     if(Ctx->NbSelected()==0)
1839       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1840     else{
1841       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1842         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1843       Ctx->UpdateCurrentViewer();
1844     }
1845   }
1846   else if (!strcasecmp (buf_ret, "U"))
1847   {
1848     // Unset display mode
1849     std::cout << "reset display mode to defaults" << std::endl;
1850
1851     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1852     if(Ctx->NbSelected()==0)
1853       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1854     else{
1855       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1856         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1857       Ctx->UpdateCurrentViewer();
1858     }
1859
1860   }
1861   else if (!strcasecmp (buf_ret, "T")
1862         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1863   {
1864     // Top
1865     aView->SetProj(V3d_Zpos);
1866   }
1867   else if (!strcasecmp (buf_ret, "B")
1868         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1869   {
1870     // Bottom
1871     aView->SetProj(V3d_Zneg);
1872   }
1873   else if (!strcasecmp (buf_ret, "L")
1874         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1875   {
1876     // Left
1877     aView->SetProj(V3d_Xneg);
1878   }
1879   else if (!strcasecmp (buf_ret, "R")
1880         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1881   {
1882     // Right
1883     aView->SetProj(V3d_Xpos);
1884   }
1885   else if (!strcasecmp (buf_ret, "W"))
1886   {
1887     std::cout << "setup WireFrame display mode" << std::endl;
1888     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1889     if(Ctx->NbSelected()==0)
1890       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1891     else{
1892       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1893         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1894       Ctx->UpdateCurrentViewer();
1895     }
1896   }
1897   else if (!strcasecmp (buf_ret, ","))
1898   {
1899     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1900   }
1901   else if (!strcasecmp (buf_ret, "."))
1902   {
1903     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1904   }
1905   else if (!strcasecmp (buf_ret, "/"))
1906   {
1907     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1908     if (aCamera->IsStereo())
1909     {
1910       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1911       aView->Redraw();
1912     }
1913   }
1914   else if (!strcasecmp (buf_ret, "*"))
1915   {
1916     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1917     if (aCamera->IsStereo())
1918     {
1919       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1920       aView->Redraw();
1921     }
1922   }
1923   else if (*buf_ret == THE_KEY_DELETE)
1924   {
1925     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1926     if (!aCtx.IsNull()
1927      && aCtx->NbSelected() > 0)
1928     {
1929       Draw_Interprete ("verase");
1930     }
1931   }
1932   else if (*buf_ret == THE_KEY_ESCAPE)
1933   {
1934     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1935     if (!aCtx.IsNull()
1936      && Draw_ToCloseViewOnEsc)
1937     {
1938       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
1939     }
1940   }
1941   else
1942   {
1943     // Number
1944     const Standard_Integer aSelMode = Draw::Atoi(buf_ret);
1945     if (aSelMode >= 0 && aSelMode <= 7)
1946     {
1947       bool toEnable = true;
1948       if (const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext())
1949       {
1950         AIS_ListOfInteractive aPrsList;
1951         aCtx->DisplayedObjects (aPrsList);
1952         for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
1953         {
1954           TColStd_ListOfInteger aModes;
1955           aCtx->ActivatedModes (aPrsIter.Value(), aModes);
1956           for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
1957           {
1958             if (aModeIter.Value() == aSelMode)
1959             {
1960               toEnable = false;
1961             }
1962           }
1963         }
1964       }
1965       TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
1966       Draw_Interprete (aCmd.ToCString());
1967     }
1968   }
1969 }
1970
1971 //==============================================================================
1972 //function : VT_ProcessExpose
1973 //purpose  : Redraw the View on an Expose Event
1974 //==============================================================================
1975 void VT_ProcessExpose()
1976 {
1977   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1978   if (!aView3d.IsNull())
1979   {
1980     aView3d->Redraw();
1981   }
1982 }
1983
1984 //==============================================================================
1985 //function : VT_ProcessConfigure
1986 //purpose  : Resize the View on an Configure Event
1987 //==============================================================================
1988 void VT_ProcessConfigure()
1989 {
1990   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1991   if (aView3d.IsNull())
1992   {
1993     return;
1994   }
1995
1996   aView3d->MustBeResized();
1997   aView3d->Update();
1998   aView3d->Redraw();
1999 }
2000
2001 //==============================================================================
2002 //function : VT_ProcessButton1Press
2003 //purpose  : Picking
2004 //==============================================================================
2005 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
2006                                          const char**     theArgVec,
2007                                          Standard_Boolean theToPick,
2008                                          Standard_Boolean theIsShift)
2009 {
2010   if (TheIsAnimating)
2011   {
2012     TheIsAnimating = Standard_False;
2013     return Standard_False;
2014   }
2015
2016   if (theToPick)
2017   {
2018     Standard_Real X, Y, Z;
2019     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
2020
2021     Draw::Set (theArgVec[1], X);
2022     Draw::Set (theArgVec[2], Y);
2023     Draw::Set (theArgVec[3], Z);
2024   }
2025
2026   if (theIsShift)
2027   {
2028     ViewerTest::CurrentEventManager()->ShiftSelect();
2029   }
2030   else
2031   {
2032     ViewerTest::CurrentEventManager()->Select();
2033   }
2034
2035   return Standard_False;
2036 }
2037
2038 //==============================================================================
2039 //function : VT_ProcessButton1Release
2040 //purpose  : End selecting
2041 //==============================================================================
2042 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
2043 {
2044   if (IsDragged)
2045   {
2046     IsDragged = Standard_False;
2047     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
2048     if (theIsShift)
2049     {
2050       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
2051                        X_Motion, Y_Motion);
2052     }
2053     else
2054     {
2055       EM->Select (X_ButtonPress, Y_ButtonPress,
2056                   X_Motion, Y_Motion);
2057     }
2058   }
2059 }
2060
2061 //==============================================================================
2062 //function : VT_ProcessButton3Press
2063 //purpose  : Start Rotation
2064 //==============================================================================
2065 void VT_ProcessButton3Press()
2066 {
2067   if (ViewerTest_V3dView::IsCurrentViewIn2DMode())
2068   {
2069     return;
2070   }
2071
2072   Start_Rot = 1;
2073   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
2074   if (HasHlrOnBeforeRotation)
2075   {
2076     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
2077   }
2078   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
2079 }
2080
2081 //==============================================================================
2082 //function : VT_ProcessButton3Release
2083 //purpose  : End rotation
2084 //==============================================================================
2085 void VT_ProcessButton3Release()
2086 {
2087   if (Start_Rot)
2088   {
2089     Start_Rot = 0;
2090     if (HasHlrOnBeforeRotation)
2091     {
2092       HasHlrOnBeforeRotation = Standard_False;
2093       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
2094       ViewerTest::CurrentView()->Redraw();
2095     }
2096   }
2097 }
2098
2099 //==============================================================================
2100 //function : ProcessControlButton1Motion
2101 //purpose  : Zoom
2102 //==============================================================================
2103
2104 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
2105 static void ProcessControlButton1Motion()
2106 {
2107   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
2108
2109   X_ButtonPress = X_Motion;
2110   Y_ButtonPress = Y_Motion;
2111 }
2112 #endif
2113
2114 //==============================================================================
2115 //function : VT_ProcessControlButton2Motion
2116 //purpose  : Panning
2117 //==============================================================================
2118 void VT_ProcessControlButton2Motion()
2119 {
2120   Standard_Integer aDx = X_Motion - X_ButtonPress;
2121   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
2122
2123   aDy = -aDy; // Xwindow Y axis is from top to Bottom
2124
2125   ViewerTest::CurrentView()->Pan (aDx, aDy);
2126
2127   X_ButtonPress = X_Motion;
2128   Y_ButtonPress = Y_Motion;
2129 }
2130
2131 //==============================================================================
2132 //function : VT_ProcessControlButton3Motion
2133 //purpose  : Rotation
2134 //==============================================================================
2135 void VT_ProcessControlButton3Motion()
2136 {
2137   if (Start_Rot)
2138   {
2139     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
2140   }
2141 }
2142
2143 //==============================================================================
2144 //function : VT_ProcessMotion
2145 //purpose  :
2146 //==============================================================================
2147 void VT_ProcessMotion()
2148 {
2149   //pre-hilights detected objects at mouse position
2150
2151   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
2152   EM->MoveTo(X_Motion, Y_Motion);
2153 }
2154
2155
2156 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
2157 {
2158   Xpix = X_Motion;Ypix=Y_Motion;
2159 }
2160
2161 //==============================================================================
2162 //function : ViewProject: implements VAxo, VTop, VLeft, ...
2163 //purpose  : Switches to an axonometric, top, left and other views
2164 //==============================================================================
2165
2166 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
2167 {
2168   if ( ViewerTest::CurrentView().IsNull() )
2169   {
2170     di<<"Call vinit before this command, please\n";
2171     return 1;
2172   }
2173
2174   ViewerTest::CurrentView()->SetProj(ori);
2175   return 0;
2176 }
2177
2178 //==============================================================================
2179 //function : VAxo
2180 //purpose  : Switch to an Axonometric view
2181 //Draw arg : No args
2182 //==============================================================================
2183
2184 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
2185 {
2186   return ViewProject(di, V3d_XposYnegZpos);
2187 }
2188
2189 //==============================================================================
2190 //function : VTop
2191 //purpose  : Switch to a Top View
2192 //Draw arg : No args
2193 //==============================================================================
2194
2195 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
2196 {
2197   return ViewProject(di, V3d_Zpos);
2198 }
2199
2200 //==============================================================================
2201 //function : VBottom
2202 //purpose  : Switch to a Bottom View
2203 //Draw arg : No args
2204 //==============================================================================
2205
2206 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
2207 {
2208   return ViewProject(di, V3d_Zneg);
2209 }
2210
2211 //==============================================================================
2212 //function : VLeft
2213 //purpose  : Switch to a Left View
2214 //Draw arg : No args
2215 //==============================================================================
2216
2217 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
2218 {
2219   return ViewProject(di, V3d_Xneg);
2220 }
2221
2222 //==============================================================================
2223 //function : VRight
2224 //purpose  : Switch to a Right View
2225 //Draw arg : No args
2226 //==============================================================================
2227
2228 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
2229 {
2230   return ViewProject(di, V3d_Xpos);
2231 }
2232
2233 //==============================================================================
2234 //function : VFront
2235 //purpose  : Switch to a Front View
2236 //Draw arg : No args
2237 //==============================================================================
2238
2239 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
2240 {
2241   return ViewProject(di, V3d_Yneg);
2242 }
2243
2244 //==============================================================================
2245 //function : VBack
2246 //purpose  : Switch to a Back View
2247 //Draw arg : No args
2248 //==============================================================================
2249
2250 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
2251 {
2252   return ViewProject(di, V3d_Ypos);
2253 }
2254
2255 //==============================================================================
2256 //function : VHelp
2257 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
2258 //Draw arg : No args
2259 //==============================================================================
2260
2261 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
2262 {
2263
2264   di << "Q : Quit the application\n";
2265
2266   di << "=========================\n";
2267   di << "F : FitAll\n";
2268   di << "T : TopView\n";
2269   di << "B : BottomView\n";
2270   di << "R : RightView\n";
2271   di << "L : LeftView\n";
2272   di << "A : AxonometricView\n";
2273   di << "D : ResetView\n";
2274
2275   di << "=========================\n";
2276   di << "S : Shading\n";
2277   di << "W : Wireframe\n";
2278   di << "H : HidelLineRemoval\n";
2279   di << "U : Unset display mode\n";
2280   di << "Delete : Remove selection from viewer\n";
2281
2282   di << "=========================\n";
2283   di << "Selection mode \n";
2284   di << "0 : Shape\n";
2285   di << "1 : Vertex\n";
2286   di << "2 : Edge\n";
2287   di << "3 : Wire\n";
2288   di << "4 : Face\n";
2289   di << "5 : Shell\n";
2290   di << "6 : Solid\n";
2291   di << "7 : Compound\n";
2292
2293   di << "=========================\n";
2294   di << "Z : Switch Z clipping On/Off\n";
2295   di << ", : Hilight next detected\n";
2296   di << ". : Hilight previous detected\n";
2297
2298   return 0;
2299 }
2300
2301 #ifdef _WIN32
2302
2303 static Standard_Boolean Ppick = 0;
2304 static Standard_Integer Pargc = 0;
2305 static const char**           Pargv = NULL;
2306
2307
2308 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
2309                                           UINT Msg,
2310                                           WPARAM wParam,
2311                                           LPARAM lParam )
2312 {
2313   if (!ViewerTest_myViews.IsEmpty()) {
2314
2315     WPARAM fwKeys = wParam;
2316
2317     switch( Msg ) {
2318     case WM_CLOSE:
2319        {
2320          // Delete view from map of views
2321          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
2322          return 0;
2323        }
2324        break;
2325     case WM_ACTIVATE:
2326       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
2327         || ViewerTest::CurrentView().IsNull())
2328       {
2329         // Activate inactive window
2330         if(GetWindowHandle(VT_GetWindow()) != hwnd)
2331         {
2332           ActivateView (FindViewIdByWindowHandle(hwnd));
2333         }
2334       }
2335       break;
2336
2337     case WM_LBUTTONUP:
2338       if (IsDragged && !DragFirst)
2339       {
2340         if (!GetActiveAISManipulator().IsNull())
2341         {
2342           GetActiveAISManipulator()->StopTransform();
2343           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2344         }
2345
2346         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2347         {
2348           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2349           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2350         }
2351
2352         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
2353       }
2354       IsDragged = Standard_False;
2355       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2356
2357     case WM_RBUTTONUP:
2358       if (IsDragged && !DragFirst)
2359       {
2360         if (!GetActiveAISManipulator().IsNull())
2361         {
2362           GetActiveAISManipulator()->StopTransform (Standard_False);
2363           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2364         }
2365         IsDragged = Standard_False;
2366       }
2367       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
2368
2369     case WM_LBUTTONDOWN:
2370       if (!GetActiveAISManipulator().IsNull())
2371       {
2372         IsDragged = ( fwKeys == MK_LBUTTON );
2373       }
2374       else
2375       {
2376         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
2377       }
2378
2379       if (IsDragged)
2380       {
2381         DragFirst = Standard_True;
2382         X_ButtonPress = LOWORD(lParam);
2383         Y_ButtonPress = HIWORD(lParam);
2384       }
2385       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2386
2387     case WM_MOUSEMOVE:
2388       if (IsDragged)
2389       {
2390         X_Motion = LOWORD (lParam);
2391         Y_Motion = HIWORD (lParam);
2392         if (!GetActiveAISManipulator().IsNull())
2393         {
2394           if (DragFirst)
2395           {
2396             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
2397           }
2398           else
2399           {
2400             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
2401             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
2402           }
2403         }
2404         else
2405         {
2406           bool toRedraw = false;
2407           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2408           {
2409             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2410             toRedraw = true;
2411           }
2412
2413           RECT aRect;
2414           if (GetClientRect (hwnd, &aRect))
2415           {
2416             int aHeight = aRect.bottom - aRect.top;
2417             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2418             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2419             toRedraw = true;
2420           }
2421           if (toRedraw)
2422           {
2423             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2424           }
2425         }
2426
2427         DragFirst = Standard_False;
2428       }
2429       else
2430         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2431       break;
2432
2433     default:
2434       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2435     }
2436     return 0;
2437   }
2438   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2439 }
2440
2441
2442 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2443                                        UINT Msg,
2444                                        WPARAM wParam,
2445                                        LPARAM lParam )
2446 {
2447   static int Up = 1;
2448   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2449   if (aView.IsNull())
2450   {
2451     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2452   }
2453
2454     PAINTSTRUCT    ps;
2455
2456     switch( Msg ) {
2457     case WM_PAINT:
2458       BeginPaint(hwnd, &ps);
2459       EndPaint(hwnd, &ps);
2460       VT_ProcessExpose();
2461       break;
2462
2463     case WM_SIZE:
2464       VT_ProcessConfigure();
2465       break;
2466     case WM_MOVE:
2467     case WM_MOVING:
2468     case WM_SIZING:
2469       switch (aView->RenderingParams().StereoMode)
2470       {
2471         case Graphic3d_StereoMode_RowInterlaced:
2472         case Graphic3d_StereoMode_ColumnInterlaced:
2473         case Graphic3d_StereoMode_ChessBoard:
2474           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2475           break;
2476         default:
2477           break;
2478       }
2479       break;
2480
2481     case WM_KEYDOWN:
2482       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2483       {
2484         char c[2];
2485         c[0] = (char) wParam;
2486         c[1] = '\0';
2487         if (wParam == VK_DELETE)
2488         {
2489           c[0] = THE_KEY_DELETE;
2490         }
2491         else if (wParam == VK_ESCAPE)
2492         {
2493           c[0] = THE_KEY_ESCAPE;
2494         }
2495         // comma
2496         else if (wParam == VK_OEM_COMMA)
2497         {
2498           c[0] = ',';
2499         }
2500         // dot
2501         else if (wParam == VK_OEM_PERIOD)
2502         {
2503           c[0] = '.';
2504         }
2505         else if (wParam == VK_DIVIDE)
2506         {
2507           c[0] = '/';
2508         }
2509         // dot
2510         else if (wParam == VK_MULTIPLY)
2511         {
2512           c[0] = '*';
2513         }
2514         VT_ProcessKeyPress (c);
2515       }
2516       break;
2517
2518     case WM_LBUTTONUP:
2519     case WM_MBUTTONUP:
2520     case WM_RBUTTONUP:
2521       Up = 1;
2522       VT_ProcessButton3Release();
2523       break;
2524
2525     case WM_LBUTTONDOWN:
2526     case WM_MBUTTONDOWN:
2527     case WM_RBUTTONDOWN:
2528       {
2529         WPARAM fwKeys = wParam;
2530
2531         Up = 0;
2532
2533         X_ButtonPress = LOWORD(lParam);
2534         Y_ButtonPress = HIWORD(lParam);
2535
2536         if (Msg == WM_LBUTTONDOWN)
2537         {
2538           if ((fwKeys & MK_CONTROL) != 0)
2539           {
2540             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2541           }
2542           else
2543           {
2544             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2545           }
2546         }
2547         else if (Msg == WM_RBUTTONDOWN)
2548         {
2549           // Start rotation
2550           VT_ProcessButton3Press();
2551         }
2552       }
2553       break;
2554
2555     case WM_MOUSEWHEEL:
2556     {
2557       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2558       if (wParam & MK_CONTROL)
2559       {
2560         if (aView->Camera()->IsStereo())
2561         {
2562           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2563           if (aFocus > 0.2
2564            && aFocus < 2.0)
2565           {
2566             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2567             aView->Redraw();
2568           }
2569         }
2570       }
2571       else
2572       {
2573         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2574       }
2575       break;
2576     }
2577
2578     case WM_MOUSEMOVE:
2579       {
2580         //cout << "\t WM_MOUSEMOVE" << endl;
2581         WPARAM fwKeys = wParam;
2582         X_Motion = LOWORD(lParam);
2583         Y_Motion = HIWORD(lParam);
2584
2585         if ( Up &&
2586           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2587           {
2588             Up = 0;
2589             X_ButtonPress = LOWORD(lParam);
2590             Y_ButtonPress = HIWORD(lParam);
2591
2592             if ((fwKeys & MK_RBUTTON) != 0) {
2593               // Start rotation
2594               VT_ProcessButton3Press();
2595             }
2596           }
2597
2598           if ((fwKeys & MK_CONTROL) != 0)
2599           {
2600             if ((fwKeys & MK_LBUTTON) != 0)
2601             {
2602               ProcessControlButton1Motion();
2603             }
2604             else if ((fwKeys & MK_MBUTTON) != 0
2605                  || ((fwKeys & MK_LBUTTON) != 0
2606                   && (fwKeys & MK_RBUTTON) != 0))
2607             {
2608               VT_ProcessControlButton2Motion();
2609             }
2610             else if ((fwKeys & MK_RBUTTON) != 0)
2611             {
2612               VT_ProcessControlButton3Motion();
2613             }
2614           }
2615           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2616           {
2617             VT_ProcessMotion();
2618           }
2619       }
2620       break;
2621
2622     default:
2623       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2624     }
2625     return 0L;
2626 }
2627
2628 //==============================================================================
2629 //function : ViewerMainLoop
2630 //purpose  : Get a Event on the view and dispatch it
2631 //==============================================================================
2632
2633
2634 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2635 {
2636   Ppick = (argc > 0)? 1 : 0;
2637   Pargc = argc;
2638   Pargv = argv;
2639
2640   if ( Ppick ) {
2641     MSG msg;
2642     msg.wParam = 1;
2643
2644     cout << "Start picking" << endl;
2645
2646     while ( Ppick == 1 ) {
2647       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2648       if (GetMessageW (&msg, NULL, 0, 0))
2649       {
2650         TranslateMessage (&msg);
2651         DispatchMessageW (&msg);
2652       }
2653     }
2654
2655     cout << "Picking done" << endl;
2656   }
2657
2658   return Ppick;
2659 }
2660
2661 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2662
2663 int min( int a, int b )
2664 {
2665   if( a<b )
2666     return a;
2667   else
2668     return b;
2669 }
2670
2671 int max( int a, int b )
2672 {
2673   if( a>b )
2674     return a;
2675   else
2676     return b;
2677 }
2678
2679 int ViewerMainLoop (Standard_Integer argc, const char** argv)
2680 {
2681   static XEvent aReport;
2682   const Standard_Boolean toPick = argc > 0;
2683   Standard_Boolean toPickMore = toPick;
2684   Display* aDisplay = GetDisplayConnection()->GetDisplay();
2685   XNextEvent (aDisplay, &aReport);
2686
2687   // Handle event for the chosen display connection
2688   switch (aReport.type)
2689   {
2690     case ClientMessage:
2691     {
2692       if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2693       {
2694         // Close the window
2695         ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2696         return toPick ? 0 : 1;
2697       }
2698       break;
2699     }
2700     case FocusIn:
2701     {
2702       // Activate inactive view
2703       Window aWindow = GetWindowHandle(VT_GetWindow());
2704       if (aWindow != aReport.xfocus.window)
2705       {
2706         ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2707       }
2708       break;
2709     }
2710     case Expose:
2711     {
2712       Window anXWindow = GetWindowHandle (VT_GetWindow());
2713       if (anXWindow == aReport.xexpose.window)
2714       {
2715         VT_ProcessExpose();
2716       }
2717
2718       // remove all the ExposureMask and process them at once
2719       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
2720       {
2721         if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
2722         {
2723           break;
2724         }
2725       }
2726
2727       break;
2728     }
2729     case ConfigureNotify:
2730     {
2731       // remove all the StructureNotifyMask and process them at once
2732       Window anXWindow = GetWindowHandle (VT_GetWindow());
2733       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
2734       {
2735         if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
2736         {
2737           break;
2738         }
2739       }
2740
2741       if (anXWindow == aReport.xconfigure.window)
2742       {
2743         VT_ProcessConfigure();
2744       }
2745       break;
2746     }
2747     case KeyPress:
2748     {
2749       KeySym aKeySym;
2750       char aKeyBuf[11];
2751       XComposeStatus status_in_out;
2752       int aKeyLen = XLookupString ((XKeyEvent* )&aReport, (char* )aKeyBuf, 10, &aKeySym, &status_in_out);
2753       aKeyBuf[aKeyLen] = '\0';
2754       if (aKeyLen != 0)
2755       {
2756         VT_ProcessKeyPress (aKeyBuf);
2757       }
2758       break;
2759     }
2760     case ButtonPress:
2761     {
2762       X_ButtonPress = aReport.xbutton.x;
2763       Y_ButtonPress = aReport.xbutton.y;
2764       if (aReport.xbutton.button == Button1)
2765       {
2766         if (aReport.xbutton.state & ControlMask)
2767         {
2768           toPickMore = VT_ProcessButton1Press (argc, argv, toPick, (aReport.xbutton.state & ShiftMask) != 0);
2769         }
2770         else
2771         {
2772           IsDragged = Standard_True;
2773           DragFirst = Standard_True;
2774         }
2775       }
2776       else if (aReport.xbutton.button == Button3)
2777       {
2778         // Start rotation
2779         VT_ProcessButton3Press();
2780       }
2781       break;
2782     }
2783     case ButtonRelease:
2784     {
2785       if (!IsDragged)
2786       {
2787         VT_ProcessButton3Release();
2788         break;
2789       }
2790
2791       Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
2792       if (aContext.IsNull())
2793       {
2794         std::cout << "Error: No active view.\n";
2795         return 0;
2796       }
2797
2798       if (!DragFirst
2799         && aContext->IsDisplayed (GetRubberBand()))
2800       {
2801         aContext->Remove (GetRubberBand(), Standard_False);
2802         aContext->CurrentViewer()->RedrawImmediate();
2803       }
2804
2805       if (aReport.xbutton.button != Button1)
2806       {
2807         break;
2808       }
2809
2810       const Standard_Boolean isShiftPressed = (aReport.xbutton.state & ShiftMask) != 0;
2811       if (DragFirst)
2812       {
2813         if (isShiftPressed)
2814         {
2815           aContext->ShiftSelect (Standard_True);
2816         }
2817         else
2818         {
2819           aContext->Select (Standard_True);
2820         }
2821       }
2822       else
2823       {
2824         if (isShiftPressed)
2825         {
2826           aContext->ShiftSelect (Min (X_ButtonPress, X_Motion), Min (Y_ButtonPress, Y_Motion),
2827                                  Max (X_ButtonPress, X_Motion), Max (Y_ButtonPress, Y_Motion),
2828                                  ViewerTest::CurrentView(), Standard_True);
2829         }
2830         else
2831         {
2832           aContext->Select (Min (X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2833                             Max (X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2834                             ViewerTest::CurrentView(), Standard_True);
2835         }
2836       }
2837       IsDragged = Standard_False;
2838       break;
2839     }
2840     case MotionNotify:
2841     {
2842       Window anXWindow = GetWindowHandle (VT_GetWindow());
2843       if (anXWindow != aReport.xmotion.window)
2844       {
2845         break;
2846       }
2847
2848       // remove all the ButtonMotionMask and process them at once
2849       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
2850       {
2851         if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
2852         {
2853           break;
2854         }
2855       }
2856
2857       if (IsDragged)
2858       {
2859         if (!DragFirst
2860           && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2861         {
2862           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2863         }
2864
2865         X_Motion = aReport.xmotion.x;
2866         Y_Motion = aReport.xmotion.y;
2867         DragFirst = Standard_False;
2868
2869         Window aWindow = GetWindowHandle(VT_GetWindow());
2870         Window aRoot;
2871         int anX, anY;
2872         unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2873         XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2874         GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2875         ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2876         ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2877       }
2878       else
2879       {
2880         X_Motion = aReport.xmotion.x;
2881         Y_Motion = aReport.xmotion.y;
2882         if ((aReport.xmotion.state & ControlMask) != 0)
2883         {
2884           if ((aReport.xmotion.state & Button1Mask) != 0)
2885           {
2886             ProcessControlButton1Motion();
2887           }
2888           else if ((aReport.xmotion.state & Button2Mask) != 0)
2889           {
2890             VT_ProcessControlButton2Motion();
2891           }
2892           else if ((aReport.xmotion.state & Button3Mask) != 0)
2893           {
2894             VT_ProcessControlButton3Motion();
2895           }
2896         }
2897         else
2898         {
2899           VT_ProcessMotion();
2900         }
2901       }
2902       break;
2903     }
2904   }
2905   return (!toPick || toPickMore) ? 1 : 0;
2906 }
2907
2908 //==============================================================================
2909 //function : VProcessEvents
2910 //purpose  : manage the event in the Viewer window (see Tcl_CreateFileHandler())
2911 //==============================================================================
2912 static void VProcessEvents (ClientData theDispX, int)
2913 {
2914   Display* aDispX = (Display* )theDispX;
2915   Handle(Aspect_DisplayConnection) aDispConn;
2916   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2917        aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
2918   {
2919     const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
2920     if (aDispConnTmp->GetDisplay() == aDispX)
2921     {
2922       aDispConn = aDispConnTmp;
2923       break;
2924     }
2925   }
2926   if (aDispConn.IsNull())
2927   {
2928     std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
2929     return;
2930   }
2931
2932   // process new events in queue
2933   SetDisplayConnection (aDispConn);
2934   int aNbRemain = 0;
2935   for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
2936   {
2937     const int anEventResult = ViewerMainLoop (0, NULL);
2938     if (anEventResult == 0)
2939     {
2940       return;
2941     }
2942
2943     aNbRemain = XPending (aDispX);
2944     if (++anEventIter >= aNbEventsMax
2945      || aNbRemain <= 0)
2946     {
2947       break;
2948     }
2949   }
2950
2951   // Listening X events through Tcl_CreateFileHandler() callback is fragile,
2952   // it is possible that new events will arrive to queue before the end of this callback
2953   // so that either this callback should go into an infinite loop (blocking processing of other events)
2954   // or to keep unprocessed events till the next queue update (which can arrive not soon).
2955   // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
2956   if (aNbRemain != 0)
2957   {
2958     XEvent aDummyEvent;
2959     memset (&aDummyEvent, 0, sizeof(aDummyEvent));
2960     aDummyEvent.type = ClientMessage;
2961     aDummyEvent.xclient.format = 32;
2962     XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
2963     XFlush (aDispX);
2964   }
2965
2966   if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
2967   {
2968     SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
2969   }
2970 }
2971 #endif
2972
2973 //==============================================================================
2974 //function : OSWindowSetup
2975 //purpose  : Setup for the X11 window to be able to cath the event
2976 //==============================================================================
2977
2978
2979 static void OSWindowSetup()
2980 {
2981 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2982   // X11
2983
2984   Window  window   = VT_GetWindow()->XWindow();
2985   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2986   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2987   XSynchronize(aDisplay, 1);
2988
2989   // X11 : For keyboard on SUN
2990   XWMHints wmhints;
2991   wmhints.flags = InputHint;
2992   wmhints.input = 1;
2993
2994   XSetWMHints( aDisplay, window, &wmhints);
2995
2996   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2997     ButtonPressMask | ButtonReleaseMask |
2998     StructureNotifyMask |
2999     PointerMotionMask |
3000     Button1MotionMask | Button2MotionMask |
3001     Button3MotionMask | FocusChangeMask
3002     );
3003   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
3004   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
3005
3006   XSynchronize(aDisplay, 0);
3007
3008 #else
3009   // _WIN32
3010 #endif
3011
3012 }
3013
3014 //==============================================================================
3015 //function : VFit
3016 //purpose  :
3017 //==============================================================================
3018
3019 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
3020 {
3021   const Handle(V3d_View) aView = ViewerTest::CurrentView();
3022   if (aView.IsNull())
3023   {
3024     std::cout << "Error: no active viewer!\n";
3025     return 1;
3026   }
3027
3028   Standard_Boolean toFit = Standard_True;
3029   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
3030   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3031   {
3032     TCollection_AsciiString anArg (theArgv[anArgIter]);
3033     anArg.LowerCase();
3034     if (anUpdateTool.parseRedrawMode (anArg))
3035     {
3036       continue;
3037     }
3038     else if (anArg == "-selected")
3039     {
3040       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
3041       toFit = Standard_False;
3042     }
3043     else
3044     {
3045       std::cout << "Syntax error at '" << anArg << "'\n";
3046     }
3047   }
3048
3049   if (toFit)
3050   {
3051     aView->FitAll (0.01, Standard_False);
3052   }
3053   return 0;
3054 }
3055
3056 //=======================================================================
3057 //function : VFitArea
3058 //purpose  : Fit view to show area located between two points
3059 //         : given in world 2D or 3D coordinates.
3060 //=======================================================================
3061 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
3062 {
3063   Handle(V3d_View) aView = ViewerTest::CurrentView();
3064   if (aView.IsNull())
3065   {
3066     std::cerr << theArgVec[0] << "Error: No active view.\n";
3067     return 1;
3068   }
3069
3070   // Parse arguments.
3071   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
3072   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
3073
3074   if (theArgNb == 5)
3075   {
3076     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3077     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3078     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
3079     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
3080   }
3081   else if (theArgNb == 7)
3082   {
3083     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3084     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3085     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
3086     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
3087     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
3088     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
3089   }
3090   else
3091   {
3092     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
3093     theDI.PrintHelp(theArgVec[0]);
3094     return 1;
3095   }
3096
3097   // Convert model coordinates to view space
3098   Handle(Graphic3d_Camera) aCamera = aView->Camera();
3099   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
3100   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
3101
3102   // Determine fit area
3103   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
3104   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
3105
3106   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
3107
3108   if (aDiagonal < Precision::Confusion())
3109   {
3110     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
3111     return 1;
3112   }
3113
3114   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
3115   return 0;
3116 }
3117
3118 //==============================================================================
3119 //function : VZFit
3120 //purpose  : ZFitall, no DRAW arguments
3121 //Draw arg : No args
3122 //==============================================================================
3123 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3124 {
3125   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
3126
3127   if (aCurrentView.IsNull())
3128   {
3129     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
3130     return 1;
3131   }
3132
3133   if (theArgsNb == 1)
3134   {
3135     aCurrentView->ZFitAll();
3136     aCurrentView->Redraw();
3137     return 0;
3138   }
3139
3140   Standard_Real aScale = 1.0;
3141
3142   if (theArgsNb >= 2)
3143   {
3144     aScale = Draw::Atoi (theArgVec[1]);
3145   }
3146
3147   aCurrentView->ZFitAll (aScale);
3148   aCurrentView->Redraw();
3149
3150   return 0;
3151 }
3152
3153 //==============================================================================
3154 //function : VRepaint
3155 //purpose  :
3156 //==============================================================================
3157 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
3158 {
3159   Handle(V3d_View) aView = ViewerTest::CurrentView();
3160   if (aView.IsNull())
3161   {
3162     std::cout << "Error: no active viewer!\n";
3163     return 1;
3164   }
3165
3166   Standard_Boolean isImmediateUpdate = Standard_False;
3167   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3168   {
3169     TCollection_AsciiString anArg (theArgVec[anArgIter]);
3170     anArg.LowerCase();
3171     if (anArg == "-immediate"
3172      || anArg == "-imm")
3173     {
3174       isImmediateUpdate = Standard_True;
3175       if (anArgIter + 1 < theArgNb
3176        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
3177       {
3178         ++anArgIter;
3179       }
3180     }
3181     else if (anArg == "-continuous"
3182           || anArg == "-cont"
3183           || anArg == "-fps"
3184           || anArg == "-framerate")
3185     {
3186       Standard_Real aFps = -1.0;
3187       if (anArgIter + 1 < theArgNb
3188        && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
3189       {
3190         aFps = Draw::Atof (theArgVec[++anArgIter]);
3191       }
3192
3193       ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
3194       if (Abs (aFps) >= 1.0)
3195       {
3196         aRedrawer.Start (aView->Window(), aFps);
3197       }
3198       else
3199       {
3200         aRedrawer.Stop();
3201       }
3202     }
3203     else
3204     {
3205       std::cout << "Syntax error at '" << anArg << "'\n";
3206       return 1;
3207     }
3208   }
3209
3210   if (isImmediateUpdate)
3211   {
3212     aView->RedrawImmediate();
3213   }
3214   else
3215   {
3216     aView->Redraw();
3217   }
3218   return 0;
3219 }
3220
3221 //==============================================================================
3222 //function : VClear
3223 //purpose  : Remove all the object from the viewer
3224 //Draw arg : No args
3225 //==============================================================================
3226
3227 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3228 {
3229   Handle(V3d_View) V = ViewerTest::CurrentView();
3230   if(!V.IsNull())
3231     ViewerTest::Clear();
3232   return 0;
3233 }
3234
3235 //==============================================================================
3236 //function : VPick
3237 //purpose  :
3238 //==============================================================================
3239
3240 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3241 { if (ViewerTest::CurrentView().IsNull() ) return 1;
3242
3243 if ( argc < 4 ) {
3244   di << argv[0] << "Invalid number of arguments\n";
3245   return 1;
3246 }
3247
3248 while (ViewerMainLoop( argc, argv)) {
3249 }
3250
3251 return 0;
3252 }
3253
3254 //==============================================================================
3255 //function : VSetBg
3256 //purpose  : Load image as background
3257 //==============================================================================
3258
3259 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3260 {
3261   if (argc < 2 || argc > 3)
3262   {
3263     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
3264     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
3265     return 1;
3266   }
3267
3268   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3269   if(AISContext.IsNull())
3270   {
3271     di << "use 'vinit' command before " << argv[0] << "\n";
3272     return 1;
3273   }
3274
3275   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
3276   if (argc == 3)
3277   {
3278     const char* szType = argv[2];
3279     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3280     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3281     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3282     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3283     else
3284     {
3285       di << "Wrong fill type : " << szType << "\n";
3286       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3287       return 1;
3288     }
3289   }
3290
3291   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3292   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
3293
3294   return 0;
3295 }
3296
3297 //==============================================================================
3298 //function : VSetBgMode
3299 //purpose  : Change background image fill type
3300 //==============================================================================
3301
3302 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3303 {
3304   if (argc != 2)
3305   {
3306     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
3307     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
3308     return 1;
3309   }
3310
3311   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3312   if(AISContext.IsNull())
3313   {
3314     di << "use 'vinit' command before " << argv[0] << "\n";
3315     return 1;
3316   }
3317   Aspect_FillMethod aFillType = Aspect_FM_NONE;
3318   const char* szType = argv[1];
3319   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3320   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3321   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3322   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3323   else
3324   {
3325     di << "Wrong fill type : " << szType << "\n";
3326     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3327     return 1;
3328   }
3329   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3330   V3dView->SetBgImageStyle(aFillType, Standard_True);
3331   return 0;
3332 }
3333
3334 //==============================================================================
3335 //function : VSetGradientBg
3336 //purpose  : Mount gradient background
3337 //==============================================================================
3338 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3339 {
3340   if (argc != 8 )
3341   {
3342     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
3343     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
3344     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3345     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3346     return 1;
3347   }
3348
3349   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3350   if(AISContext.IsNull())
3351   {
3352     di << "use 'vinit' command before " << argv[0] << "\n";
3353     return 1;
3354   }
3355   if (argc == 8)
3356   {
3357
3358     Standard_Real R1 = Draw::Atof(argv[1])/255.;
3359     Standard_Real G1 = Draw::Atof(argv[2])/255.;
3360     Standard_Real B1 = Draw::Atof(argv[3])/255.;
3361     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
3362
3363     Standard_Real R2 = Draw::Atof(argv[4])/255.;
3364     Standard_Real G2 = Draw::Atof(argv[5])/255.;
3365     Standard_Real B2 = Draw::Atof(argv[6])/255.;
3366
3367     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
3368     int aType = Draw::Atoi(argv[7]);
3369     if( aType < 0 || aType > 8 )
3370     {
3371       di << "Wrong fill type \n";
3372       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3373       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3374       return 1;
3375     }
3376
3377     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3378
3379     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3380     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
3381   }
3382
3383   return 0;
3384 }
3385
3386 //==============================================================================
3387 //function : VSetGradientBgMode
3388 //purpose  : Change gradient background fill style
3389 //==============================================================================
3390 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3391 {
3392   if (argc != 2 )
3393   {
3394     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
3395     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3396     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3397     return 1;
3398   }
3399
3400   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3401   if(AISContext.IsNull())
3402   {
3403     di << "use 'vinit' command before " << argv[0] << "\n";
3404     return 1;
3405   }
3406   if (argc == 2)
3407   {
3408     int aType = Draw::Atoi(argv[1]);
3409     if( aType < 0 || aType > 8 )
3410     {
3411       di << "Wrong fill type \n";
3412       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3413       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3414       return 1;
3415     }
3416
3417     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3418
3419     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3420     V3dView->SetBgGradientStyle( aMethod, 1 );
3421   }
3422
3423   return 0;
3424 }
3425
3426 //==============================================================================
3427 //function : VSetColorBg
3428 //purpose  : Set color background
3429 //==============================================================================
3430 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3431 {
3432   if (argc != 4 )
3433   {
3434     di << "Usage : " << argv[0] << " R G B : Set color background\n";
3435     di << "R,G,B = [0..255]\n";
3436     return 1;
3437   }
3438
3439   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3440   if(AISContext.IsNull())
3441   {
3442     di << "use 'vinit' command before " << argv[0] << "\n";
3443     return 1;
3444   }
3445   if (argc == 4)
3446   {
3447
3448     Standard_Real R = Draw::Atof(argv[1])/255.;
3449     Standard_Real G = Draw::Atof(argv[2])/255.;
3450     Standard_Real B = Draw::Atof(argv[3])/255.;
3451     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
3452
3453     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3454     V3dView->SetBackgroundColor( aColor );
3455     V3dView->Update();
3456   }
3457
3458   return 0;
3459 }
3460
3461 //==============================================================================
3462 //function : VSetDefaultBg
3463 //purpose  : Set default viewer background fill color
3464 //==============================================================================
3465 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3466 {
3467   if (theArgNb != 4
3468    && theArgNb != 8)
3469   {
3470     std::cout << "Error: wrong syntax! See usage:\n";
3471     theDI.PrintHelp (theArgVec[0]);
3472     return 1;
3473   }
3474
3475   ViewerTest_DefaultBackground.FillMethod =
3476     theArgNb == 4 ? Aspect_GFM_NONE
3477                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
3478
3479   if (theArgNb == 4)
3480   {
3481     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
3482     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
3483     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
3484     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
3485   }
3486   else
3487   {
3488     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
3489     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
3490     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
3491     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
3492
3493     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
3494     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
3495     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
3496     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
3497   }
3498
3499   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
3500        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
3501   {
3502     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
3503     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
3504     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
3505                                          ViewerTest_DefaultBackground.GradientColor2,
3506                                          ViewerTest_DefaultBackground.FillMethod);
3507   }
3508
3509   return 0;
3510 }
3511
3512 //==============================================================================
3513 //function : VScale
3514 //purpose  : View Scaling
3515 //==============================================================================
3516
3517 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3518 {
3519   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3520   if ( V3dView.IsNull() ) return 1;
3521
3522   if ( argc != 4 ) {
3523     di << argv[0] << "Invalid number of arguments\n";
3524     return 1;
3525   }
3526   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3527   return 0;
3528 }
3529 //==============================================================================
3530 //function : VZBuffTrihedron
3531 //purpose  :
3532 //==============================================================================
3533
3534 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3535                             Standard_Integer  theArgNb,
3536                             const char**      theArgVec)
3537 {
3538   Handle(V3d_View) aView = ViewerTest::CurrentView();
3539   if (aView.IsNull())
3540   {
3541     std::cout << "Error: no active viewer!\n";
3542     return 1;
3543   }
3544
3545   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3546
3547   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3548   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3549   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3550   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3551   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3552   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3553   Standard_Real                 aScale        = 0.1;
3554   Standard_Real                 aSizeRatio    = 0.8;
3555   Standard_Real                 anArrowDiam   = 0.05;
3556   Standard_Integer              aNbFacets     = 12;
3557   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3558   {
3559     Standard_CString        anArg = theArgVec[anArgIter];
3560     TCollection_AsciiString aFlag (anArg);
3561     aFlag.LowerCase();
3562     if (anUpdateTool.parseRedrawMode (aFlag))
3563     {
3564       continue;
3565     }
3566     else if (aFlag == "-on")
3567     {
3568       continue;
3569     }
3570     else if (aFlag == "-off")
3571     {
3572       aView->TriedronErase();
3573       return 0;
3574     }
3575     else if (aFlag == "-pos"
3576           || aFlag == "-position"
3577           || aFlag == "-corner")
3578     {
3579       if (++anArgIter >= theArgNb)
3580       {
3581         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3582         return 1;
3583       }
3584
3585       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3586       aPosName.LowerCase();
3587       if (aPosName == "center")
3588       {
3589         aPosition = Aspect_TOTP_CENTER;
3590       }
3591       else if (aPosName == "left_lower"
3592             || aPosName == "lower_left"
3593             || aPosName == "leftlower"
3594             || aPosName == "lowerleft")
3595       {
3596         aPosition = Aspect_TOTP_LEFT_LOWER;
3597       }
3598       else if (aPosName == "left_upper"
3599             || aPosName == "upper_left"
3600             || aPosName == "leftupper"
3601             || aPosName == "upperleft")
3602       {
3603         aPosition = Aspect_TOTP_LEFT_UPPER;
3604       }
3605       else if (aPosName == "right_lower"
3606             || aPosName == "lower_right"
3607             || aPosName == "rightlower"
3608             || aPosName == "lowerright")
3609       {
3610         aPosition = Aspect_TOTP_RIGHT_LOWER;
3611       }
3612       else if (aPosName == "right_upper"
3613             || aPosName == "upper_right"
3614             || aPosName == "rightupper"
3615             || aPosName == "upperright")
3616       {
3617         aPosition = Aspect_TOTP_RIGHT_UPPER;
3618       }
3619       else
3620       {
3621         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3622         return 1;
3623       }
3624     }
3625     else if (aFlag == "-type")
3626     {
3627       if (++anArgIter >= theArgNb)
3628       {
3629         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3630         return 1;
3631       }
3632
3633       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3634       aTypeName.LowerCase();
3635       if (aTypeName == "wireframe"
3636        || aTypeName == "wire")
3637       {
3638         aVisType = V3d_WIREFRAME;
3639       }
3640       else if (aTypeName == "zbuffer"
3641             || aTypeName == "shaded")
3642       {
3643         aVisType = V3d_ZBUFFER;
3644       }
3645       else
3646       {
3647         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3648       }
3649     }
3650     else if (aFlag == "-scale")
3651     {
3652       if (++anArgIter >= theArgNb)
3653       {
3654         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3655         return 1;
3656       }
3657
3658       aScale = Draw::Atof (theArgVec[anArgIter]);
3659     }
3660     else if (aFlag == "-size"
3661           || aFlag == "-sizeratio")
3662     {
3663       if (++anArgIter >= theArgNb)
3664       {
3665         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3666         return 1;
3667       }
3668
3669       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3670     }
3671     else if (aFlag == "-arrowdiam"
3672           || aFlag == "-arrowdiameter")
3673     {
3674       if (++anArgIter >= theArgNb)
3675       {
3676         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3677         return 1;
3678       }
3679
3680       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3681     }
3682     else if (aFlag == "-nbfacets")
3683     {
3684       if (++anArgIter >= theArgNb)
3685       {
3686         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3687         return 1;
3688       }
3689
3690       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3691     }
3692     else if (aFlag == "-colorlabel"
3693           || aFlag == "-colorlabels")
3694     {
3695       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3696                                                            theArgVec + anArgIter + 1,
3697                                                            aLabelsColor);
3698       if (aNbParsed == 0)
3699       {
3700         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3701         return 1;
3702       }
3703       anArgIter += aNbParsed;
3704     }
3705     else if (aFlag == "-colorarrowx")
3706     {
3707       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3708                                                            theArgVec + anArgIter + 1,
3709                                                            anArrowColorX);
3710       if (aNbParsed == 0)
3711       {
3712         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3713         return 1;
3714       }
3715       anArgIter += aNbParsed;
3716     }
3717     else if (aFlag == "-colorarrowy")
3718     {
3719       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3720                                                            theArgVec + anArgIter + 1,
3721                                                            anArrowColorY);
3722       if (aNbParsed == 0)
3723       {
3724         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3725         return 1;
3726       }
3727       anArgIter += aNbParsed;
3728     }
3729     else if (aFlag == "-colorarrowz")
3730     {
3731       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3732                                                            theArgVec + anArgIter + 1,
3733                                                            anArrowColorZ);
3734       if (aNbParsed == 0)
3735       {
3736         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3737         return 1;
3738       }
3739       anArgIter += aNbParsed;
3740     }
3741     else
3742     {
3743       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3744       return 1;
3745     }
3746   }
3747
3748   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3749                                aSizeRatio, anArrowDiam, aNbFacets);
3750   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3751   aView->ZFitAll();
3752   return 0;
3753 }
3754
3755 //==============================================================================
3756 //function : VRotate
3757 //purpose  : Camera Rotating
3758 //==============================================================================
3759
3760 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3761 {
3762   Handle(V3d_View) aView = ViewerTest::CurrentView();
3763   if (aView.IsNull())
3764   {
3765     std::cout << "No active view!\n";
3766     return 1;
3767   }
3768
3769   Standard_Boolean hasFlags = Standard_False;
3770   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3771   {
3772     Standard_CString        anArg (theArgVec[anArgIter]);
3773     TCollection_AsciiString aFlag (anArg);
3774     aFlag.LowerCase();
3775     if (aFlag == "-mousestart"
3776      || aFlag == "-mousefrom")
3777     {
3778       hasFlags = Standard_True;
3779       if (anArgIter + 2 >= theArgNb)
3780       {
3781         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3782         return 1;
3783       }
3784
3785       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3786       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3787       aView->StartRotation (anX, anY);
3788     }
3789     else if (aFlag == "-mousemove")
3790     {
3791       hasFlags = Standard_True;
3792       if (anArgIter + 2 >= theArgNb)
3793       {
3794         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3795         return 1;
3796       }
3797
3798       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3799       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3800       aView->Rotation (anX, anY);
3801     }
3802     else if (theArgNb != 4
3803           && theArgNb != 7)
3804     {
3805       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3806       return 1;
3807     }
3808   }
3809
3810   if (hasFlags)
3811   {
3812     return 0;
3813   }
3814   else if (theArgNb == 4)
3815   {
3816     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3817     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3818     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3819     aView->Rotate (anAX, anAY, anAZ);
3820     return 0;
3821   }
3822   else if (theArgNb == 7)
3823   {
3824     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3825     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3826     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3827
3828     Standard_Real anX = Draw::Atof (theArgVec[4]);
3829     Standard_Real anY = Draw::Atof (theArgVec[5]);
3830     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3831
3832     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3833     return 0;
3834   }
3835
3836   std::cout << "Error: Invalid number of arguments\n";
3837   return 1;
3838 }
3839
3840 //==============================================================================
3841 //function : VZoom
3842 //purpose  : View zoom in / out (relative to current zoom)
3843 //==============================================================================
3844
3845 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3846   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3847   if ( V3dView.IsNull() ) {
3848     return 1;
3849   }
3850
3851   if ( argc == 2 ) {
3852     Standard_Real coef = Draw::Atof(argv[1]);
3853     if ( coef <= 0.0 ) {
3854       di << argv[1] << "Invalid value\n";
3855       return 1;
3856     }
3857     V3dView->SetZoom( Draw::Atof(argv[1]) );
3858     return 0;
3859   } else {
3860     di << argv[0] << " Invalid number of arguments\n";
3861     return 1;
3862   }
3863 }
3864
3865 //==============================================================================
3866 //function : VPan
3867 //purpose  : View panning (in pixels)
3868 //==============================================================================
3869
3870 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3871   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3872   if ( V3dView.IsNull() ) return 1;
3873
3874   if ( argc == 3 ) {
3875     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3876     return 0;
3877   } else {
3878     di << argv[0] << " Invalid number of arguments\n";
3879     return 1;
3880   }
3881 }
3882
3883 //==============================================================================
3884 //function : VPlace
3885 //purpose  : Place the point (in pixels) at the center of the window
3886 //==============================================================================
3887 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3888 {
3889   Handle(V3d_View) aView = ViewerTest::CurrentView();
3890   if (aView.IsNull())
3891   {
3892     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3893     return 1;
3894   }
3895
3896   if (theArgNb != 3)
3897   {
3898     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3899     return 1;
3900   }
3901
3902   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3903
3904   return 0;
3905 }
3906
3907 static int VColorScale (Draw_Interpretor& theDI,
3908                         Standard_Integer  theArgNb,
3909                         const char**      theArgVec)
3910 {
3911   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3912   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3913   if (aContext.IsNull())
3914   {
3915     std::cout << "Error: no active view!\n";
3916     return 1;
3917   }
3918   if (theArgNb <= 1)
3919   {
3920     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3921     return 1;
3922   }
3923
3924   Handle(AIS_ColorScale) aColorScale;
3925   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3926   {
3927     // find existing object
3928     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3929     if (aColorScale.IsNull())
3930     {
3931       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3932       return 1;
3933     }
3934   }
3935
3936   if (theArgNb <= 2)
3937   {
3938     if (aColorScale.IsNull())
3939     {
3940       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3941       return 1;
3942     }
3943
3944     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3945           << "Min range: "            << aColorScale->GetMin() << "\n"
3946           << "Max range: "            << aColorScale->GetMax() << "\n"
3947           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3948           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3949           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3950           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3951           << "Label position: ";
3952     switch (aColorScale->GetLabelPosition())
3953     {
3954       case Aspect_TOCSP_NONE:
3955         theDI << "None\n";
3956         break;
3957       case Aspect_TOCSP_LEFT:
3958         theDI << "Left\n";
3959         break;
3960       case Aspect_TOCSP_RIGHT:
3961         theDI << "Right\n";
3962         break;
3963       case Aspect_TOCSP_CENTER:
3964         theDI << "Center\n";
3965         break;
3966     }
3967     return 0;
3968   }
3969
3970   if (aColorScale.IsNull())
3971   {
3972     aColorScale = new AIS_ColorScale();
3973     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3974     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3975   }
3976
3977   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3978   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3979   {
3980     Standard_CString        anArg = theArgVec[anArgIter];
3981     TCollection_AsciiString aFlag (anArg);
3982     aFlag.LowerCase();
3983     if (anUpdateTool.parseRedrawMode (aFlag))
3984     {
3985       continue;
3986     }
3987     else if (aFlag == "-range")
3988     {
3989       if (anArgIter + 3 >= theArgNb)
3990       {
3991         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3992         return 1;
3993       }
3994
3995       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3996       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3997       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3998       if (!aRangeMin.IsRealValue()
3999        || !aRangeMax.IsRealValue())
4000       {
4001         std::cout << "Error: the range values should be real!\n";
4002         return 1;
4003       }
4004       else if (!aNbIntervals.IsIntegerValue())
4005       {
4006         std::cout << "Error: the number of intervals should be integer!\n";
4007         return 1;
4008       }
4009
4010       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
4011       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
4012     }
4013     else if (aFlag == "-font")
4014     {
4015       if (anArgIter + 1 >= theArgNb)
4016       {
4017         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4018         return 1;
4019       }
4020       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
4021       if (!aFontArg.IsIntegerValue())
4022       {
4023         std::cout << "Error: HeightFont value should be integer!\n";
4024         return 1;
4025       }
4026
4027       aColorScale->SetTextHeight (aFontArg.IntegerValue());
4028       anArgIter += 1;
4029     }
4030     else if (aFlag == "-textpos")
4031     {
4032       if (anArgIter + 1 >= theArgNb)
4033       {
4034         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4035         return 1;
4036       }
4037
4038       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
4039       aTextPosArg.LowerCase();
4040       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
4041       if (aTextPosArg == "none")
4042       {
4043         aLabPosition = Aspect_TOCSP_NONE;
4044       }
4045       else if (aTextPosArg == "left")
4046       {
4047         aLabPosition = Aspect_TOCSP_LEFT;
4048       }
4049       else if (aTextPosArg == "right")
4050       {
4051         aLabPosition = Aspect_TOCSP_RIGHT;
4052       }
4053       else if (aTextPosArg == "center")
4054       {
4055         aLabPosition = Aspect_TOCSP_CENTER;
4056       }
4057       else
4058       {
4059         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
4060         return 1;
4061       }
4062       aColorScale->SetLabelPosition (aLabPosition);
4063     }
4064     else if (aFlag == "-logarithmic"
4065           || aFlag == "-log")
4066     {
4067       if (anArgIter + 1 >= theArgNb)
4068       {
4069         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4070         return 1;
4071       }
4072
4073       Standard_Boolean IsLog;
4074       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
4075       {
4076         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4077         return 1;
4078       }
4079       aColorScale->SetLogarithmic (IsLog);
4080     }
4081     else if (aFlag == "-huerange"
4082           || aFlag == "-hue")
4083     {
4084       if (anArgIter + 2 >= theArgNb)
4085       {
4086         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4087         return 1;
4088       }
4089
4090       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
4091       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
4092       aColorScale->SetHueRange (aHueMin, aHueMax);
4093     }
4094     else if (aFlag == "-colorrange")
4095     {
4096       Quantity_Color aColorMin, aColorMax;
4097       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4098                                                             theArgVec + (anArgIter + 1),
4099                                                             aColorMin);
4100       anArgIter += aNbParsed1;
4101       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4102                                                             theArgVec + (anArgIter + 1),
4103                                                             aColorMax);
4104       anArgIter += aNbParsed2;
4105       if (aNbParsed1 == 0
4106        || aNbParsed2 == 0)
4107       {
4108         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4109         return 1;
4110       }
4111
4112       aColorScale->SetColorRange (aColorMin, aColorMax);
4113     }
4114     else if (aFlag == "-reversed"
4115           || aFlag == "-inverted"
4116           || aFlag == "-topdown"
4117           || aFlag == "-bottomup")
4118     {
4119       Standard_Boolean toEnable = Standard_True;
4120       if (anArgIter + 1 < theArgNb
4121        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
4122       {
4123         ++anArgIter;
4124       }
4125       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
4126     }
4127     else if (aFlag == "-smooth"
4128           || aFlag == "-smoothtransition")
4129     {
4130       Standard_Boolean toEnable = Standard_True;
4131       if (anArgIter + 1 < theArgNb
4132        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4133       {
4134         ++anArgIter;
4135       }
4136       aColorScale->SetSmoothTransition (toEnable);
4137     }
4138     else if (aFlag == "-xy")
4139     {
4140       if (anArgIter + 2 >= theArgNb)
4141       {
4142         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4143         return 1;
4144       }
4145
4146       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
4147       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
4148       if (!anX.IsIntegerValue()
4149        || !anY.IsIntegerValue())
4150       {
4151         std::cout << "Error: coordinates should be integer values!\n";
4152         return 1;
4153       }
4154
4155       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
4156     }
4157     else if (aFlag == "-width"
4158           || aFlag == "-w"
4159           || aFlag == "-breadth")
4160     {
4161       if (anArgIter + 1 >= theArgNb)
4162       {
4163         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4164         return 1;
4165       }
4166
4167       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
4168       if (!aBreadth.IsIntegerValue())
4169       {
4170         std::cout << "Error: a width should be an integer value!\n";
4171         return 1;
4172       }
4173       aColorScale->SetBreadth (aBreadth.IntegerValue());
4174     }
4175     else if (aFlag == "-height"
4176           || aFlag == "-h")
4177     {
4178       if (anArgIter + 1 >= theArgNb)
4179       {
4180         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4181         return 1;
4182       }
4183
4184       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
4185       if (!aHeight.IsIntegerValue())
4186       {
4187         std::cout << "Error: a width should be an integer value!\n";
4188         return 1;
4189       }
4190       aColorScale->SetHeight (aHeight.IntegerValue());
4191     }
4192     else if (aFlag == "-color")
4193     {
4194       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4195       {
4196         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
4197         return 1;
4198       }
4199       else if (anArgIter + 2 >= theArgNb)
4200       {
4201         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4202         return 1;
4203       }
4204
4205       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
4206       if (!anInd.IsIntegerValue())
4207       {
4208         std::cout << "Error: Index value should be integer!\n";
4209         return 1;
4210       }
4211       const Standard_Integer anIndex = anInd.IntegerValue();
4212       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
4213       {
4214         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
4215         return 1;
4216       }
4217
4218       Quantity_Color aColor;
4219       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4220                                                            theArgVec + (anArgIter + 1),
4221                                                            aColor);
4222       if (aNbParsed == 0)
4223       {
4224         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4225         return 1;
4226       }
4227       aColorScale->SetIntervalColor (aColor, anIndex);
4228       aColorScale->SetColorType (Aspect_TOCSD_USER);
4229       anArgIter += aNbParsed;
4230     }
4231     else if (aFlag == "-label")
4232     {
4233       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4234       {
4235         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4236         return 1;
4237       }
4238       else if (anArgIter + 2 >= theArgNb)
4239       {
4240         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4241         return 1;
4242       }
4243
4244       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4245       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4246       {
4247         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4248         return 1;
4249       }
4250
4251       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4252       aColorScale->SetLabel     (aText, anIndex);
4253       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4254       anArgIter += 2;
4255     }
4256     else if (aFlag == "-labelat"
4257           || aFlag == "-labat"
4258           || aFlag == "-labelatborder"
4259           || aFlag == "-labatborder"
4260           || aFlag == "-labelatcenter"
4261           || aFlag == "-labatcenter")
4262     {
4263       Standard_Boolean toEnable = Standard_True;
4264       if (aFlag == "-labelat"
4265        || aFlag == "-labat")
4266       {
4267         Standard_Integer aLabAtBorder = -1;
4268         if (++anArgIter >= theArgNb)
4269         {
4270           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4271           anAtBorder.LowerCase();
4272           if (anAtBorder == "border")
4273           {
4274             aLabAtBorder = 1;
4275           }
4276           else if (anAtBorder == "center")
4277           {
4278             aLabAtBorder = 0;
4279           }
4280         }
4281         if (aLabAtBorder == -1)
4282         {
4283           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4284           return 1;
4285         }
4286         toEnable = (aLabAtBorder == 1);
4287       }
4288       else if (anArgIter + 1 < theArgNb
4289             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4290       {
4291         ++anArgIter;
4292       }
4293       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4294                                   || aFlag == "-labatcenter"
4295                                    ? !toEnable
4296                                    :  toEnable);
4297     }
4298     else if (aFlag == "-colors")
4299     {
4300       Aspect_SequenceOfColor aSeq;
4301       for (;;)
4302       {
4303         Quantity_Color aColor;
4304         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4305                                                              theArgVec + (anArgIter + 1),
4306                                                              aColor);
4307         if (aNbParsed == 0)
4308         {
4309           break;
4310         }
4311         anArgIter += aNbParsed;
4312         aSeq.Append (aColor);
4313       }
4314       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4315       {
4316         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4317                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4318         return 1;
4319       }
4320
4321       aColorScale->SetColors    (aSeq);
4322       aColorScale->SetColorType (Aspect_TOCSD_USER);
4323     }
4324     else if (aFlag == "-labels"
4325           || aFlag == "-freelabels")
4326     {
4327       if (anArgIter + 1 >= theArgNb)
4328       {
4329         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4330         return 1;
4331       }
4332
4333       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4334                                  ? aColorScale->GetNumberOfIntervals() + 1
4335                                  : aColorScale->GetNumberOfIntervals();
4336       if (aFlag == "-freelabels")
4337       {
4338         ++anArgIter;
4339         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4340       }
4341       if (anArgIter + aNbLabels >= theArgNb)
4342       {
4343         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4344         return 1;
4345       }
4346
4347       TColStd_SequenceOfExtendedString aSeq;
4348       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4349       {
4350         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4351       }
4352       aColorScale->SetLabels (aSeq);
4353       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4354     }
4355     else if (aFlag == "-title")
4356     {
4357       if (anArgIter + 1 >= theArgNb)
4358       {
4359         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4360         return 1;
4361       }
4362
4363       Standard_Boolean isTwoArgs = Standard_False;
4364       if (anArgIter + 2 < theArgNb)
4365       {
4366         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4367         aSecondArg.LowerCase();
4368       Standard_DISABLE_DEPRECATION_WARNINGS
4369         if (aSecondArg == "none")
4370         {
4371           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4372           isTwoArgs = Standard_True;
4373         }
4374         else if (aSecondArg == "left")
4375         {
4376           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4377           isTwoArgs = Standard_True;
4378         }
4379         else if (aSecondArg == "right")
4380         {
4381           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4382           isTwoArgs = Standard_True;
4383         }
4384         else if (aSecondArg == "center")
4385         {
4386           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4387           isTwoArgs = Standard_True;
4388         }
4389       Standard_ENABLE_DEPRECATION_WARNINGS
4390       }
4391
4392       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4393       if (isTwoArgs)
4394       {
4395         anArgIter += 1;
4396       }
4397       anArgIter += 1;
4398     }
4399     else if (aFlag == "-demoversion"
4400           || aFlag == "-demo")
4401     {
4402       aColorScale->SetPosition (0, 0);
4403       aColorScale->SetTextHeight (16);
4404       aColorScale->SetRange (0.0, 100.0);
4405       aColorScale->SetNumberOfIntervals (10);
4406       aColorScale->SetBreadth (0);
4407       aColorScale->SetHeight  (0);
4408       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4409       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4410       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4411     }
4412     else if (aFlag == "-findcolor")
4413     {
4414       if (anArgIter + 1 >= theArgNb)
4415       {
4416         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4417         return 1;
4418       }
4419
4420       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4421
4422       if (!anArg1.IsRealValue())
4423       {
4424         std::cout << "Error: the value should be real!\n";
4425         return 1;
4426       }
4427
4428       Quantity_Color aColor;
4429       aColorScale->FindColor (anArg1.RealValue(), aColor);
4430       theDI << Quantity_Color::StringName (aColor.Name());
4431       return 0;
4432     }
4433     else
4434     {
4435       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4436       return 1;
4437     }
4438   }
4439
4440   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4441   aView->Window()->Size (aWinWidth, aWinHeight);
4442   if (aColorScale->GetBreadth() == 0)
4443   {
4444     aColorScale->SetBreadth (aWinWidth);
4445   }
4446   if (aColorScale->GetHeight() == 0)
4447   {
4448     aColorScale->SetHeight (aWinHeight);
4449   }
4450   aColorScale->SetToUpdate();
4451   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4452   return 0;
4453 }
4454
4455 //==============================================================================
4456 //function : VGraduatedTrihedron
4457 //purpose  : Displays or hides a graduated trihedron
4458 //==============================================================================
4459 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4460                                   Quantity_Color& theColor)
4461 {
4462   Quantity_NameOfColor aColorName;
4463   TCollection_AsciiString aVal = theValue;
4464   aVal.UpperCase();
4465   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4466   {
4467     return Standard_False;
4468   }
4469   theColor = Quantity_Color (aColorName);
4470   return Standard_True;
4471 }
4472
4473 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4474 {
4475   if (theArgNum < 2)
4476   {
4477     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4478               << theArgs[0] <<"' for more information.\n";
4479     return 1;  //TCL_ERROR
4480   }
4481
4482   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4483   TCollection_AsciiString aParseKey;
4484   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4485   {
4486     TCollection_AsciiString anArg (theArgs [anArgIt]);
4487
4488     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4489     {
4490       aParseKey = anArg;
4491       aParseKey.Remove (1);
4492       aParseKey.LowerCase();
4493       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4494       continue;
4495     }
4496
4497     if (aParseKey.IsEmpty())
4498     {
4499       continue;
4500     }
4501
4502     aMapOfArgs(aParseKey)->Append (anArg);
4503   }
4504
4505   // Check parameters
4506   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4507        aMapIt.More(); aMapIt.Next())
4508   {
4509     const TCollection_AsciiString& aKey = aMapIt.Key();
4510     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4511
4512     // Bool key, without arguments
4513     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4514         && anArgs->IsEmpty())
4515     {
4516       continue;
4517     }
4518
4519     // One argument
4520     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4521           && anArgs->Length() == 1)
4522     {
4523       continue;
4524     }
4525
4526     // On/off arguments
4527     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4528         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4529         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4530         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4531         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4532     {
4533       continue;
4534     }
4535
4536     // One string argument
4537     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4538           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4539           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4540     {
4541       continue;
4542     }
4543
4544     // One integer argument
4545     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4546           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4547           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4548           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4549          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4550     {
4551       continue;
4552     }
4553
4554     // One real argument
4555     if ( aKey.IsEqual ("arrowlength")
4556          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4557     {
4558       continue;
4559     }
4560
4561     // Two string arguments
4562     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4563          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4564     {
4565       continue;
4566     }
4567
4568     TCollection_AsciiString aLowerKey;
4569     aLowerKey  = "-";
4570     aLowerKey += aKey;
4571     aLowerKey.LowerCase();
4572     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4573     std::cout << "Type help for more information.\n";
4574     return 1;
4575   }
4576
4577   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4578   if (anAISContext.IsNull())
4579   {
4580     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4581     return 1;
4582   }
4583
4584   Standard_Boolean toDisplay = Standard_True;
4585   Quantity_Color aColor;
4586   Graphic3d_GraduatedTrihedron aTrihedronData;
4587   // Process parameters
4588   Handle(TColStd_HSequenceOfAsciiString) aValues;
4589   if (aMapOfArgs.Find ("off", aValues))
4590   {
4591     toDisplay = Standard_False;
4592   }
4593
4594   // AXES NAMES
4595   if (aMapOfArgs.Find ("xname", aValues))
4596   {
4597     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4598   }
4599   if (aMapOfArgs.Find ("yname", aValues))
4600   {
4601     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4602   }
4603   if (aMapOfArgs.Find ("zname", aValues))
4604   {
4605     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4606   }
4607   if (aMapOfArgs.Find ("xdrawname", aValues))
4608   {
4609     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4610   }
4611   if (aMapOfArgs.Find ("ydrawname", aValues))
4612   {
4613     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4614   }
4615   if (aMapOfArgs.Find ("zdrawname", aValues))
4616   {
4617     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4618   }
4619   if (aMapOfArgs.Find ("xnameoffset", aValues))
4620   {
4621     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4622   }
4623   if (aMapOfArgs.Find ("ynameoffset", aValues))
4624   {
4625     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4626   }
4627   if (aMapOfArgs.Find ("znameoffset", aValues))
4628   {
4629     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4630   }
4631
4632   // COLORS
4633   if (aMapOfArgs.Find ("xnamecolor", aValues))
4634   {
4635     if (!GetColor (aValues->Value(1), aColor))
4636     {
4637       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4638       return 1;
4639     }
4640     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4641   }
4642   if (aMapOfArgs.Find ("ynamecolor", aValues))
4643   {
4644     if (!GetColor (aValues->Value(1), aColor))
4645     {
4646       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4647       return 1;
4648     }
4649     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4650   }
4651   if (aMapOfArgs.Find ("znamecolor", aValues))
4652   {
4653     if (!GetColor (aValues->Value(1), aColor))
4654     {
4655       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4656       return 1;
4657     }
4658     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4659   }
4660   if (aMapOfArgs.Find ("xcolor", aValues))
4661   {
4662     if (!GetColor (aValues->Value(1), aColor))
4663     {
4664       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4665       return 1;
4666     }
4667     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4668   }
4669   if (aMapOfArgs.Find ("ycolor", aValues))
4670   {
4671     if (!GetColor (aValues->Value(1), aColor))
4672     {
4673       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4674       return 1;
4675     }
4676     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4677   }
4678   if (aMapOfArgs.Find ("zcolor", aValues))
4679   {
4680     if (!GetColor (aValues->Value(1), aColor))
4681     {
4682       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4683       return 1;
4684     }
4685     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4686   }
4687
4688   // TICKMARKS
4689   if (aMapOfArgs.Find ("xticks", aValues))
4690   {
4691     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4692   }
4693   if (aMapOfArgs.Find ("yticks", aValues))
4694   {
4695     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4696   }
4697   if (aMapOfArgs.Find ("zticks", aValues))
4698   {
4699     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4700   }
4701   if (aMapOfArgs.Find ("xticklength", aValues))
4702   {
4703     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4704   }
4705   if (aMapOfArgs.Find ("yticklength", aValues))
4706   {
4707     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4708   }
4709   if (aMapOfArgs.Find ("zticklength", aValues))
4710   {
4711     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4712   }
4713   if (aMapOfArgs.Find ("xdrawticks", aValues))
4714   {
4715     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4716   }
4717   if (aMapOfArgs.Find ("ydrawticks", aValues))
4718   {
4719     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4720   }
4721   if (aMapOfArgs.Find ("zdrawticks", aValues))
4722   {
4723     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4724   }
4725
4726   // VALUES
4727   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4728   {
4729     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4730   }
4731   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4732   {
4733     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4734   }
4735   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4736   {
4737     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4738   }
4739   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4740   {
4741     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4742   }
4743   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4744   {
4745     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4746   }
4747   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4748   {
4749     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4750   }
4751
4752   // ARROWS
4753   if (aMapOfArgs.Find ("arrowlength", aValues))
4754   {
4755     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4756   }
4757
4758   // FONTS
4759   if (aMapOfArgs.Find ("namefont", aValues))
4760   {
4761     aTrihedronData.SetNamesFont (aValues->Value(1));
4762   }
4763   if (aMapOfArgs.Find ("valuesfont", aValues))
4764   {
4765     aTrihedronData.SetValuesFont (aValues->Value(1));
4766   }
4767
4768   if (aMapOfArgs.Find ("drawgrid", aValues))
4769   {
4770     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4771   }
4772   if (aMapOfArgs.Find ("drawaxes", aValues))
4773   {
4774     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4775   }
4776
4777   // The final step: display of erase trihedron
4778   if (toDisplay)
4779   {
4780     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4781   }
4782   else
4783   {
4784     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4785   }
4786
4787   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4788   ViewerTest::CurrentView()->Redraw();
4789
4790   return 0;
4791 }
4792
4793 //==============================================================================
4794 //function : VTile
4795 //purpose  :
4796 //==============================================================================
4797 static int VTile (Draw_Interpretor& theDI,
4798                   Standard_Integer  theArgNb,
4799                   const char**      theArgVec)
4800 {
4801   Handle(V3d_View) aView = ViewerTest::CurrentView();
4802   if (aView.IsNull())
4803   {
4804     std::cerr << "Error: no active viewer.\n";
4805     return 1;
4806   }
4807
4808   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4809   if (theArgNb < 2)
4810   {
4811     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4812           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4813           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4814     return 0;
4815   }
4816
4817   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4818   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4819   {
4820     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4821     anArg.LowerCase();
4822     if (anArg == "-lowerleft"
4823      || anArg == "-upperleft")
4824     {
4825       if (anArgIter + 3 < theArgNb)
4826       {
4827         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4828         return 1;
4829       }
4830       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4831       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4832       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4833     }
4834     else if (anArg == "-total"
4835           || anArg == "-totalsize"
4836           || anArg == "-viewsize")
4837     {
4838       if (anArgIter + 3 < theArgNb)
4839       {
4840         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4841         return 1;
4842       }
4843       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4844       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4845       if (aTile.TotalSize.x() < 1
4846        || aTile.TotalSize.y() < 1)
4847       {
4848         std::cerr << "Error: total size is incorrect.\n";
4849         return 1;
4850       }
4851     }
4852     else if (anArg == "-tilesize")
4853     {
4854       if (anArgIter + 3 < theArgNb)
4855       {
4856         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4857         return 1;
4858       }
4859
4860       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4861       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4862       if (aTile.TileSize.x() < 1
4863        || aTile.TileSize.y() < 1)
4864       {
4865         std::cerr << "Error: tile size is incorrect.\n";
4866         return 1;
4867       }
4868     }
4869     else if (anArg == "-unset")
4870     {
4871       aView->Camera()->SetTile (Graphic3d_CameraTile());
4872       aView->Redraw();
4873       return 0;
4874     }
4875   }
4876
4877   if (aTile.TileSize.x() < 1
4878    || aTile.TileSize.y() < 1)
4879   {
4880     std::cerr << "Error: tile size is undefined.\n";
4881     return 1;
4882   }
4883   else if (aTile.TotalSize.x() < 1
4884         || aTile.TotalSize.y() < 1)
4885   {
4886     std::cerr << "Error: total size is undefined.\n";
4887     return 1;
4888   }
4889
4890   aView->Camera()->SetTile (aTile);
4891   aView->Redraw();
4892   return 0;
4893 }
4894
4895 //! Format ZLayer ID.
4896 inline const char* formZLayerId (const Standard_Integer theLayerId)
4897 {
4898   switch (theLayerId)
4899   {
4900     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4901     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4902     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4903     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4904     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4905     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4906   }
4907   return "";
4908 }
4909
4910 //! Print the ZLayer information.
4911 inline void printZLayerInfo (Draw_Interpretor& theDI,
4912                              const Graphic3d_ZLayerSettings& theLayer)
4913 {
4914   if (!theLayer.Name().IsEmpty())
4915   {
4916     theDI << "  Name: " << theLayer.Name() << "\n";
4917   }
4918   if (theLayer.IsImmediate())
4919   {
4920     theDI << "  Immediate: TRUE\n";
4921   }
4922   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4923   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
4924   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
4925   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4926   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4927   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4928   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4929   {
4930     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4931   }
4932 }
4933
4934 //==============================================================================
4935 //function : VZLayer
4936 //purpose  : Test z layer operations for v3d viewer
4937 //==============================================================================
4938 static int VZLayer (Draw_Interpretor& theDI,
4939                     Standard_Integer  theArgNb,
4940                     const char**      theArgVec)
4941 {
4942   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4943   if (aContextAIS.IsNull())
4944   {
4945     std::cout << "No active viewer!\n";
4946     return 1;
4947   }
4948
4949   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4950   if (theArgNb < 2)
4951   {
4952     TColStd_SequenceOfInteger aLayers;
4953     aViewer->GetAllZLayers (aLayers);
4954     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4955     {
4956       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4957       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4958       printZLayerInfo (theDI, aSettings);
4959     }
4960     return 1;
4961   }
4962
4963   Standard_Integer anArgIter = 1;
4964   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4965   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4966   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4967   {
4968     ++anArgIter;
4969   }
4970
4971   {
4972     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4973     if (aFirstArg.IsIntegerValue())
4974     {
4975       ++anArgIter;
4976       aLayerId = aFirstArg.IntegerValue();
4977     }
4978     else
4979     {
4980       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
4981       {
4982         ++anArgIter;
4983       }
4984     }
4985   }
4986
4987   for (; anArgIter < theArgNb; ++anArgIter)
4988   {
4989     // perform operation
4990     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4991     anArg.LowerCase();
4992     if (anUpdateTool.parseRedrawMode (anArg))
4993     {
4994       //
4995     }
4996     else if (anArg == "-add"
4997           || anArg == "add")
4998     {
4999       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5000       if (!aViewer->AddZLayer (aLayerId))
5001       {
5002         std::cout << "Error: can not add a new z layer!\n";
5003         return 0;
5004       }
5005
5006       theDI << aLayerId;
5007     }
5008     else if (anArg == "-del"
5009           || anArg == "-delete"
5010           || anArg == "del")
5011     {
5012       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5013       {
5014         if (++anArgIter >= theArgNb)
5015         {
5016           std::cout << "Syntax error: id of z layer to remove is missing\n";
5017           return 1;
5018         }
5019
5020         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5021       }
5022
5023       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
5024        || aLayerId == Graphic3d_ZLayerId_Default
5025        || aLayerId == Graphic3d_ZLayerId_Top
5026        || aLayerId == Graphic3d_ZLayerId_Topmost
5027        || aLayerId == Graphic3d_ZLayerId_TopOSD
5028        || aLayerId == Graphic3d_ZLayerId_BotOSD)
5029       {
5030         std::cout << "Syntax error: standard Z layer can not be removed\n";
5031         return 1;
5032       }
5033
5034       // move all object displayed in removing layer to default layer
5035       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5036            anObjIter.More(); anObjIter.Next())
5037       {
5038         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
5039         if (aPrs.IsNull()
5040          || aPrs->ZLayer() != aLayerId)
5041         {
5042           continue;
5043         }
5044         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
5045       }
5046
5047       if (!aViewer->RemoveZLayer (aLayerId))
5048       {
5049         std::cout << "Z layer can not be removed!\n";
5050       }
5051       else
5052       {
5053         theDI << aLayerId << " ";
5054       }
5055     }
5056     else if (anArg == "-get"
5057           || anArg == "get")
5058     {
5059       TColStd_SequenceOfInteger aLayers;
5060       aViewer->GetAllZLayers (aLayers);
5061       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5062       {
5063         theDI << aLayeriter.Value() << " ";
5064       }
5065
5066       theDI << "\n";
5067     }
5068     else if (anArg == "-name")
5069     {
5070       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5071       {
5072         std::cout << "Syntax error: id of Z layer is missing\n";
5073         return 1;
5074       }
5075
5076       if (++anArgIter >= theArgNb)
5077       {
5078         std::cout << "Syntax error: name is missing\n";
5079         return 1;
5080       }
5081
5082       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5083       aSettings.SetName (theArgVec[anArgIter]);
5084       aViewer->SetZLayerSettings (aLayerId, aSettings);
5085     }
5086     else if (anArg == "-origin")
5087     {
5088       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5089       {
5090         std::cout << "Syntax error: id of Z layer is missing\n";
5091         return 1;
5092       }
5093
5094       if (anArgIter + 2 >= theArgNb)
5095       {
5096         std::cout << "Syntax error: origin coordinates are missing\n";
5097         return 1;
5098       }
5099
5100       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5101       gp_XYZ anOrigin;
5102       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5103       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5104       anOrigin.SetZ (0.0);
5105       if (anArgIter + 3 < theArgNb)
5106       {
5107         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5108         anArgIter += 3;
5109       }
5110       else
5111       {
5112         anArgIter += 2;
5113       }
5114       aSettings.SetOrigin (anOrigin);
5115       aViewer->SetZLayerSettings (aLayerId, aSettings);
5116     }
5117     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5118           && anArgIter + 1 < theArgNb
5119           && (anArg == "-cullingdistance"
5120            || anArg == "-cullingdist"
5121            || anArg == "-culldistance"
5122            || anArg == "-culldist"
5123            || anArg == "-distcull"
5124            || anArg == "-distculling"
5125            || anArg == "-distanceculling"))
5126     {
5127       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5128       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5129       aSettings.SetCullingDistance (aDist);
5130       aViewer->SetZLayerSettings (aLayerId, aSettings);
5131     }
5132     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5133           && anArgIter + 1 < theArgNb
5134           && (anArg == "-cullingsize"
5135            || anArg == "-cullsize"
5136            || anArg == "-sizecull"
5137            || anArg == "-sizeculling"))
5138     {
5139       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5140       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5141       aSettings.SetCullingSize (aSize);
5142       aViewer->SetZLayerSettings (aLayerId, aSettings);
5143     }
5144     else if (anArg == "-settings"
5145           || anArg == "settings")
5146     {
5147       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5148       {
5149         if (++anArgIter >= theArgNb)
5150         {
5151           std::cout << "Syntax error: id of Z layer is missing\n";
5152           return 1;
5153         }
5154
5155         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5156       }
5157
5158       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5159       printZLayerInfo (theDI, aSettings);
5160     }
5161     else if (anArg == "-enable"
5162           || anArg == "enable"
5163           || anArg == "-disable"
5164           || anArg == "disable")
5165     {
5166       const Standard_Boolean toEnable = anArg == "-enable"
5167                                      || anArg == "enable";
5168       if (++anArgIter >= theArgNb)
5169       {
5170         std::cout << "Syntax error: option name is missing\n";
5171         return 1;
5172       }
5173
5174       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5175       aSubOp.LowerCase();
5176       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5177       {
5178         if (++anArgIter >= theArgNb)
5179         {
5180           std::cout << "Syntax error: id of Z layer is missing\n";
5181           return 1;
5182         }
5183
5184         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5185       }
5186
5187       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5188       if (aSubOp == "depthtest"
5189        || aSubOp == "test")
5190       {
5191         aSettings.SetEnableDepthTest (toEnable);
5192       }
5193       else if (aSubOp == "depthwrite"
5194             || aSubOp == "write")
5195       {
5196         aSettings.SetEnableDepthWrite (toEnable);
5197       }
5198       else if (aSubOp == "depthclear"
5199             || aSubOp == "clear")
5200       {
5201         aSettings.SetClearDepth (toEnable);
5202       }
5203       else if (aSubOp == "depthoffset"
5204             || aSubOp == "offset")
5205       {
5206         Graphic3d_PolygonOffset aParams;
5207         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5208         if (toEnable)
5209         {
5210           if (anArgIter + 2 >= theArgNb)
5211           {
5212             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5213             return 1;
5214           }
5215
5216           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5217           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5218         }
5219         aSettings.SetPolygonOffset (aParams);
5220       }
5221       else if (aSubOp == "positiveoffset"
5222             || aSubOp == "poffset")
5223       {
5224         if (toEnable)
5225         {
5226           aSettings.SetDepthOffsetPositive();
5227         }
5228         else
5229         {
5230           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5231         }
5232       }
5233       else if (aSubOp == "negativeoffset"
5234             || aSubOp == "noffset")
5235       {
5236         if (toEnable)
5237         {
5238           aSettings.SetDepthOffsetNegative();
5239         }
5240         else
5241         {
5242           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5243         }
5244       }
5245       else if (aSubOp == "textureenv")
5246       {
5247         aSettings.SetEnvironmentTexture (toEnable);
5248       }
5249
5250       aViewer->SetZLayerSettings (aLayerId, aSettings);
5251     }
5252     else
5253     {
5254       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5255       return 1;
5256     }
5257   }
5258
5259   return 0;
5260 }
5261
5262 // The interactive presentation of 2d layer item
5263 // for "vlayerline" command it provides a presentation of
5264 // line with user-defined linewidth, linetype and transparency.
5265 class V3d_LineItem : public AIS_InteractiveObject
5266 {
5267 public:
5268   // CASCADE RTTI
5269   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5270
5271   // constructor
5272   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5273                                Standard_Real X2, Standard_Real Y2,
5274                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5275                                Standard_Real theWidth    = 0.5,
5276                                Standard_Real theTransp   = 1.0);
5277
5278   private:
5279
5280   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5281                 const Handle(Prs3d_Presentation)& thePresentation,
5282                 const Standard_Integer theMode) Standard_OVERRIDE;
5283
5284   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5285                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5286   {}
5287
5288 private:
5289
5290   Standard_Real       myX1, myY1, myX2, myY2;
5291   Aspect_TypeOfLine   myType;
5292   Standard_Real       myWidth;
5293 };
5294
5295 // default constructor for line item
5296 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5297                            Standard_Real X2, Standard_Real Y2,
5298                            Aspect_TypeOfLine theType,
5299                            Standard_Real theWidth,
5300                            Standard_Real theTransp) :
5301   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5302   myType(theType), myWidth(theWidth)
5303 {
5304   SetTransparency (1-theTransp);
5305 }
5306
5307 // render line
5308 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5309                             const Handle(Prs3d_Presentation)& thePresentation,
5310                             const Standard_Integer /*theMode*/)
5311 {
5312   thePresentation->Clear();
5313   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5314   Standard_Integer aWidth, aHeight;
5315   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5316   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5317   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5318   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5319   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5320   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5321   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5322   aGroup->AddPrimitiveArray (aPrim);
5323 }
5324
5325 //=============================================================================
5326 //function : VLayerLine
5327 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5328 //         : linewidth, transparency coefficient
5329 //============================================================================
5330 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5331 {
5332   // get the active view
5333   Handle(V3d_View) aView = ViewerTest::CurrentView();
5334   if (aView.IsNull())
5335   {
5336     di << "Call vinit before!\n";
5337     return 1;
5338   }
5339   else if (argc < 5)
5340   {
5341     di << "Use: " << argv[0];
5342     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5343     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5344     di << "              0 - solid  \n";
5345     di << "              1 - dashed \n";
5346     di << "              2 - dot    \n";
5347     di << "              3 - dashdot\n";
5348     di << " transparency : { 0.0 - 1.0 } \n";
5349     di << "                  0.0 - transparent\n";
5350     di << "                  1.0 - visible    \n";
5351     return 1;
5352   }
5353
5354   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5355   // get the input params
5356   Standard_Real X1 = Draw::Atof(argv[1]);
5357   Standard_Real Y1 = Draw::Atof(argv[2]);
5358   Standard_Real X2 = Draw::Atof(argv[3]);
5359   Standard_Real Y2 = Draw::Atof(argv[4]);
5360
5361   Standard_Real aWidth = 0.5;
5362   Standard_Real aTransparency = 1.0;
5363
5364   // has width
5365   if (argc > 5)
5366     aWidth = Draw::Atof(argv[5]);
5367
5368   // select appropriate line type
5369   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5370   if (argc > 6
5371   && !ViewerTest::ParseLineType (argv[6], aLineType))
5372   {
5373     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5374     return 1;
5375   }
5376
5377   // has transparency
5378   if (argc > 7)
5379   {
5380     aTransparency = Draw::Atof(argv[7]);
5381     if (aTransparency < 0 || aTransparency > 1.0)
5382       aTransparency = 1.0;
5383   }
5384
5385   static Handle (V3d_LineItem) aLine;
5386   if (!aLine.IsNull())
5387   {
5388     aContext->Erase (aLine, Standard_False);
5389   }
5390   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5391                             aLineType, aWidth,
5392                             aTransparency);
5393
5394   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5395   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5396   aLine->SetToUpdate();
5397   aContext->Display (aLine, Standard_True);
5398
5399   return 0;
5400 }
5401
5402
5403 //==============================================================================
5404 //function : VGrid
5405 //purpose  :
5406 //==============================================================================
5407
5408 static int VGrid (Draw_Interpretor& /*theDI*/,
5409                   Standard_Integer  theArgNb,
5410                   const char**      theArgVec)
5411 {
5412   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5413   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5414   if (aView.IsNull() || aViewer.IsNull())
5415   {
5416     std::cerr << "Error: no active view\n";
5417     return 1;
5418   }
5419
5420   Aspect_GridType     aType = aViewer->GridType();
5421   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5422   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5423   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5424   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
5425   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5426   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5427   {
5428     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5429     anArg.LowerCase();
5430     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5431     {
5432       continue;
5433     }
5434     else if (anArgIter + 1 < theArgNb
5435           && anArg == "-type")
5436     {
5437       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5438       anArgNext.LowerCase();
5439       if (anArgNext == "r"
5440        || anArgNext == "rect"
5441        || anArgNext == "rectangular")
5442       {
5443         aType = Aspect_GT_Rectangular;
5444       }
5445       else if (anArgNext == "c"
5446             || anArgNext == "circ"
5447             || anArgNext == "circular")
5448       {
5449         aType = Aspect_GT_Circular;
5450       }
5451       else
5452       {
5453         std::cout << "Syntax error at '" << anArgNext << "'\n";
5454         return 1;
5455       }
5456     }
5457     else if (anArgIter + 1 < theArgNb
5458           && anArg == "-mode")
5459     {
5460       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5461       anArgNext.LowerCase();
5462       if (anArgNext == "l"
5463        || anArgNext == "line"
5464        || anArgNext == "lines")
5465       {
5466         aMode = Aspect_GDM_Lines;
5467       }
5468       else if (anArgNext == "p"
5469             || anArgNext == "point"
5470             || anArgNext == "points")
5471       {
5472         aMode = Aspect_GDM_Points;
5473       }
5474       else
5475       {
5476         std::cout << "Syntax error at '" << anArgNext << "'\n";
5477         return 1;
5478       }
5479     }
5480     else if (anArgIter + 2 < theArgNb
5481           && (anArg == "-origin"
5482            || anArg == "-orig"))
5483     {
5484       hasOrigin = true;
5485       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5486                               Draw::Atof (theArgVec[anArgIter + 2]));
5487       anArgIter += 2;
5488     }
5489     else if (anArgIter + 2 < theArgNb
5490           && anArg == "-step")
5491     {
5492       hasStep = true;
5493       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5494                             Draw::Atof (theArgVec[anArgIter + 2]));
5495       if (aNewStepXY.x() <= 0.0
5496        || aNewStepXY.y() <= 0.0)
5497       {
5498         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5499         return 1;
5500       }
5501       anArgIter += 2;
5502     }
5503     else if (anArgIter + 1 < theArgNb
5504           && (anArg == "-angle"
5505            || anArg == "-rotangle"
5506            || anArg == "-rotationangle"))
5507     {
5508       hasRotAngle = true;
5509       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
5510     }
5511     else if (anArgIter + 1 < theArgNb
5512           && (anArg == "-zoffset"
5513            || anArg == "-dz"))
5514     {
5515       hasZOffset = true;
5516       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
5517     }
5518     else if (anArgIter + 1 < theArgNb
5519           && anArg == "-radius")
5520     {
5521       hasSize = true;
5522       ++anArgIter;
5523       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
5524       if (aNewStepXY.x() <= 0.0)
5525       {
5526         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
5527         return 1;
5528       }
5529     }
5530     else if (anArgIter + 2 < theArgNb
5531           && anArg == "-size")
5532     {
5533       hasSize = true;
5534       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5535                             Draw::Atof (theArgVec[anArgIter + 2]));
5536       if (aNewStepXY.x() <= 0.0
5537        || aNewStepXY.y() <= 0.0)
5538       {
5539         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5540         return 1;
5541       }
5542       anArgIter += 2;
5543     }
5544     else if (anArg == "r"
5545           || anArg == "rect"
5546           || anArg == "rectangular")
5547     {
5548       aType = Aspect_GT_Rectangular;
5549     }
5550     else if (anArg == "c"
5551           || anArg == "circ"
5552           || anArg == "circular")
5553     {
5554       aType = Aspect_GT_Circular;
5555     }
5556     else if (anArg == "l"
5557           || anArg == "line"
5558           || anArg == "lines")
5559     {
5560       aMode = Aspect_GDM_Lines;
5561     }
5562     else if (anArg == "p"
5563           || anArg == "point"
5564           || anArg == "points")
5565     {
5566       aMode = Aspect_GDM_Points;
5567     }
5568     else if (anArgIter + 1 >= theArgNb
5569           && anArg == "off")
5570     {
5571       aViewer->DeactivateGrid();
5572       return 0;
5573     }
5574     else
5575     {
5576       std::cout << "Syntax error at '" << anArg << "'\n";
5577       return 1;
5578     }
5579   }
5580
5581   if (aType == Aspect_GT_Rectangular)
5582   {
5583     Graphic3d_Vec2d anOrigXY, aStepXY;
5584     Standard_Real aRotAngle = 0.0;
5585     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5586     if (hasOrigin)
5587     {
5588       anOrigXY = aNewOriginXY;
5589     }
5590     if (hasStep)
5591     {
5592       aStepXY = aNewStepXY;
5593     }
5594     if (hasRotAngle)
5595     {
5596       aRotAngle = aNewRotAngle;
5597     }
5598     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5599     if (hasSize || hasZOffset)
5600     {
5601       Graphic3d_Vec3d aSize;
5602       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5603       if (hasSize)
5604       {
5605         aSize.x() = aNewSizeXY.x();
5606         aSize.y() = aNewSizeXY.y();
5607       }
5608       if (hasZOffset)
5609       {
5610         aSize.z() = aNewZOffset;
5611       }
5612       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5613     }
5614   }
5615   else if (aType == Aspect_GT_Circular)
5616   {
5617     Graphic3d_Vec2d anOrigXY;
5618     Standard_Real aRadiusStep;
5619     Standard_Integer aDivisionNumber;
5620     Standard_Real aRotAngle = 0.0;
5621     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5622     if (hasOrigin)
5623     {
5624       anOrigXY = aNewOriginXY;
5625     }
5626     if (hasStep)
5627     {
5628       aRadiusStep     = aNewStepXY[0];
5629       aDivisionNumber = (int )aNewStepXY[1];
5630       if (aDivisionNumber < 1)
5631       {
5632         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
5633         return 1;
5634       }
5635     }
5636     if (hasRotAngle)
5637     {
5638       aRotAngle = aNewRotAngle;
5639     }
5640
5641     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5642     if (hasSize || hasZOffset)
5643     {
5644       Standard_Real aRadius = 0.0, aZOffset = 0.0;
5645       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
5646       if (hasSize)
5647       {
5648         aRadius = aNewSizeXY.x();
5649         if (aNewSizeXY.y() != 0.0)
5650         {
5651           std::cout << "Syntax error: circular size should be specified as radius\n";
5652           return 1;
5653         }
5654       }
5655       if (hasZOffset)
5656       {
5657         aZOffset = aNewZOffset;
5658       }
5659       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
5660     }
5661   }
5662   aViewer->ActivateGrid (aType, aMode);
5663   return 0;
5664 }
5665
5666 //==============================================================================
5667 //function : VPriviledgedPlane
5668 //purpose  :
5669 //==============================================================================
5670
5671 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5672                               Standard_Integer  theArgNb,
5673                               const char**      theArgVec)
5674 {
5675   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5676   {
5677     std::cerr << "Error: wrong number of arguments! See usage:\n";
5678     theDI.PrintHelp (theArgVec[0]);
5679     return 1;
5680   }
5681
5682   // get the active viewer
5683   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5684   if (aViewer.IsNull())
5685   {
5686     std::cerr << "Error: no active viewer. Please call vinit.\n";
5687     return 1;
5688   }
5689
5690   if (theArgNb == 1)
5691   {
5692     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5693     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5694     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5695     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5696     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5697           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5698           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5699     return 0;
5700   }
5701
5702   Standard_Integer anArgIdx = 1;
5703   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5704   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5705   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5706   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5707   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5708   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5709
5710   gp_Ax3 aPriviledgedPlane;
5711   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5712   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5713   if (theArgNb > 7)
5714   {
5715     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5716     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5717     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5718     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5719     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5720   }
5721   else
5722   {
5723     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5724   }
5725
5726   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5727
5728   return 0;
5729 }
5730
5731 //==============================================================================
5732 //function : VConvert
5733 //purpose  :
5734 //==============================================================================
5735
5736 static int VConvert (Draw_Interpretor& theDI,
5737                      Standard_Integer  theArgNb,
5738                      const char**      theArgVec)
5739 {
5740   // get the active view
5741   Handle(V3d_View) aView = ViewerTest::CurrentView();
5742   if (aView.IsNull())
5743   {
5744     std::cerr << "Error: no active view. Please call vinit.\n";
5745     return 1;
5746   }
5747
5748   enum { Model, Ray, View, Window, Grid } aMode = Model;
5749
5750   // access coordinate arguments
5751   TColStd_SequenceOfReal aCoord;
5752   Standard_Integer anArgIdx = 1;
5753   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5754   {
5755     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5756     if (!anArg.IsRealValue())
5757     {
5758       break;
5759     }
5760     aCoord.Append (anArg.RealValue());
5761   }
5762
5763   // non-numeric argument too early
5764   if (aCoord.IsEmpty())
5765   {
5766     std::cerr << "Error: wrong number of arguments! See usage:\n";
5767     theDI.PrintHelp (theArgVec[0]);
5768     return 1;
5769   }
5770
5771   // collect all other arguments and options
5772   for (; anArgIdx < theArgNb; ++anArgIdx)
5773   {
5774     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5775     anArg.LowerCase();
5776     if      (anArg == "window") aMode = Window;
5777     else if (anArg == "view")   aMode = View;
5778     else if (anArg == "grid")   aMode = Grid;
5779     else if (anArg == "ray")    aMode = Ray;
5780     else
5781     {
5782       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5783       theDI.PrintHelp (theArgVec[0]);
5784       return 1;
5785     }
5786   }
5787
5788   // complete input checks
5789   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5790       (aCoord.Length() == 2 && theArgNb > 4) ||
5791       (aCoord.Length() == 3 && theArgNb > 5))
5792   {
5793     std::cerr << "Error: wrong number of arguments! See usage:\n";
5794     theDI.PrintHelp (theArgVec[0]);
5795     return 1;
5796   }
5797
5798   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5799   Standard_Integer aXYp[2] = {0, 0};
5800
5801   // convert one-dimensional coordinate
5802   if (aCoord.Length() == 1)
5803   {
5804     switch (aMode)
5805     {
5806       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5807       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5808       default:
5809         std::cerr << "Error: wrong arguments! See usage:\n";
5810         theDI.PrintHelp (theArgVec[0]);
5811         return 1;
5812     }
5813   }
5814
5815   // convert 2D coordinates from projection or view reference space
5816   if (aCoord.Length() == 2)
5817   {
5818     switch (aMode)
5819     {
5820       case Model :
5821         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5822         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5823         return 0;
5824
5825       case View :
5826         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5827         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5828         return 0;
5829
5830       case Window :
5831         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5832         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5833         return 0;
5834
5835       case Grid :
5836         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5837         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5838         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5839         return 0;
5840
5841       case Ray :
5842         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5843                                 (Standard_Integer) aCoord (2),
5844                                 aXYZ[0], aXYZ[1], aXYZ[2],
5845                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5846         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5847         return 0;
5848
5849       default:
5850         std::cerr << "Error: wrong arguments! See usage:\n";
5851         theDI.PrintHelp (theArgVec[0]);
5852         return 1;
5853     }
5854   }
5855
5856   // convert 3D coordinates from view reference space
5857   else if (aCoord.Length() == 3)
5858   {
5859     switch (aMode)
5860     {
5861       case Window :
5862         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5863         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5864         return 0;
5865
5866       case Grid :
5867         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5868         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5869         return 0;
5870
5871       default:
5872         std::cerr << "Error: wrong arguments! See usage:\n";
5873         theDI.PrintHelp (theArgVec[0]);
5874         return 1;
5875     }
5876   }
5877
5878   return 0;
5879 }
5880
5881 //==============================================================================
5882 //function : VFps
5883 //purpose  :
5884 //==============================================================================
5885
5886 static int VFps (Draw_Interpretor& theDI,
5887                  Standard_Integer  theArgNb,
5888                  const char**      theArgVec)
5889 {
5890   // get the active view
5891   Handle(V3d_View) aView = ViewerTest::CurrentView();
5892   if (aView.IsNull())
5893   {
5894     std::cerr << "No active view. Please call vinit.\n";
5895     return 1;
5896   }
5897
5898   Standard_Integer aFramesNb = -1;
5899   Standard_Real aDuration = -1.0;
5900   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5901   {
5902     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5903     anArg.LowerCase();
5904     if (aDuration < 0.0
5905      && anArgIter + 1 < theArgNb
5906      && (anArg == "-duration"
5907       || anArg == "-dur"
5908       || anArg == "-time"))
5909     {
5910       aDuration = Draw::Atof (theArgVec[++anArgIter]);
5911     }
5912     else if (aFramesNb < 0
5913           && anArg.IsIntegerValue())
5914     {
5915       aFramesNb = anArg.IntegerValue();
5916       if (aFramesNb <= 0)
5917       {
5918         std::cerr << "Syntax error at '" << anArg << "'\n";
5919         return 1;
5920       }
5921     }
5922     else
5923     {
5924       std::cerr << "Syntax error at '" << anArg << "'\n";
5925       return 1;
5926     }
5927   }
5928   if (aFramesNb < 0 && aDuration < 0.0)
5929   {
5930     aFramesNb = 100;
5931   }
5932
5933   // the time is meaningless for first call
5934   // due to async OpenGl rendering
5935   aView->Redraw();
5936
5937   // redraw view in loop to estimate average values
5938   OSD_Timer aTimer;
5939   aTimer.Start();
5940   Standard_Integer aFrameIter = 1;
5941   for (;; ++aFrameIter)
5942   {
5943     aView->Redraw();
5944     if ((aFramesNb > 0
5945       && aFrameIter >= aFramesNb)
5946      || (aDuration > 0.0
5947       && aTimer.ElapsedTime() >= aDuration))
5948     {
5949       break;
5950     }
5951   }
5952   aTimer.Stop();
5953   Standard_Real aCpu;
5954   const Standard_Real aTime = aTimer.ElapsedTime();
5955   aTimer.OSD_Chronometer::Show (aCpu);
5956
5957   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
5958   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
5959
5960   // return statistics
5961   theDI << "FPS: " << aFpsAver << "\n"
5962         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5963
5964   // compute additional statistics in ray-tracing mode
5965   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
5966   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5967   {
5968     Graphic3d_Vec2i aWinSize (0, 0);
5969     aView->Window()->Size (aWinSize.x(), aWinSize.y());
5970
5971     // 1 shadow ray and 1 secondary ray pew each bounce
5972     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5973     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5974   }
5975
5976   return 0;
5977 }
5978
5979 //! Auxiliary function for parsing glsl dump level argument.
5980 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
5981                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
5982 {
5983   TCollection_AsciiString aTypeStr (theArg);
5984   aTypeStr.LowerCase();
5985   if (aTypeStr == "off"
5986    || aTypeStr == "0")
5987   {
5988     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
5989   }
5990   else if (aTypeStr == "short")
5991   {
5992     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
5993   }
5994   else if (aTypeStr == "full"
5995         || aTypeStr == "1")
5996   {
5997     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
5998   }
5999   else
6000   {
6001     return Standard_False;
6002   }
6003   return Standard_True;
6004 }
6005
6006 //==============================================================================
6007 //function : VGlDebug
6008 //purpose  :
6009 //==============================================================================
6010
6011 static int VGlDebug (Draw_Interpretor& theDI,
6012                      Standard_Integer  theArgNb,
6013                      const char**      theArgVec)
6014 {
6015   Handle(OpenGl_GraphicDriver) aDriver;
6016   Handle(V3d_View) aView = ViewerTest::CurrentView();
6017   if (!aView.IsNull())
6018   {
6019     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
6020   }
6021   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
6022   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
6023
6024   if (theArgNb < 2)
6025   {
6026     TCollection_AsciiString aDebActive, aSyncActive;
6027     if (aCaps == NULL)
6028     {
6029       aCaps = aDefCaps;
6030     }
6031     else
6032     {
6033       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
6034                                                                   "GL_ARB_debug_output");
6035       aDebActive = isActive ? " (active)" : " (inactive)";
6036       if (isActive)
6037       {
6038         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
6039         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
6040       }
6041     }
6042
6043     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
6044       + "glslSourceCode: "
6045       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
6046          ? "Off"
6047          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
6048           ? "Short"
6049           : "Full")
6050       + "\n";
6051     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
6052           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
6053           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
6054           << aGlslCodeDebugStatus
6055           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
6056     return 0;
6057   }
6058
6059   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6060   {
6061     Standard_CString        anArg     = theArgVec[anArgIter];
6062     TCollection_AsciiString anArgCase (anArg);
6063     anArgCase.LowerCase();
6064     Standard_Boolean toEnableDebug = Standard_True;
6065     if (anArgCase == "-glsl"
6066      || anArgCase == "-glslwarn"
6067      || anArgCase == "-glslwarns"
6068      || anArgCase == "-glslwarnings")
6069     {
6070       Standard_Boolean toShowWarns = Standard_True;
6071       if (++anArgIter < theArgNb
6072       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
6073       {
6074         --anArgIter;
6075       }
6076       aDefCaps->glslWarnings = toShowWarns;
6077       if (aCaps != NULL)
6078       {
6079         aCaps->glslWarnings = toShowWarns;
6080       }
6081     }
6082     else if (anArgCase == "-extra"
6083           || anArgCase == "-extramsg"
6084           || anArgCase == "-extramessages")
6085     {
6086       Standard_Boolean toShow = Standard_True;
6087       if (++anArgIter < theArgNb
6088       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
6089       {
6090         --anArgIter;
6091       }
6092       aDefCaps->suppressExtraMsg = !toShow;
6093       if (aCaps != NULL)
6094       {
6095         aCaps->suppressExtraMsg = !toShow;
6096       }
6097     }
6098     else if (anArgCase == "-noextra"
6099           || anArgCase == "-noextramsg"
6100           || anArgCase == "-noextramessages")
6101     {
6102       Standard_Boolean toSuppress = Standard_True;
6103       if (++anArgIter < theArgNb
6104       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
6105       {
6106         --anArgIter;
6107       }
6108       aDefCaps->suppressExtraMsg = toSuppress;
6109       if (aCaps != NULL)
6110       {
6111         aCaps->suppressExtraMsg = toSuppress;
6112       }
6113     }
6114     else if (anArgCase == "-sync")
6115     {
6116       Standard_Boolean toSync = Standard_True;
6117       if (++anArgIter < theArgNb
6118       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
6119       {
6120         --anArgIter;
6121       }
6122       aDefCaps->contextSyncDebug = toSync;
6123       if (toSync)
6124       {
6125         aDefCaps->contextDebug = Standard_True;
6126       }
6127     }
6128     else if (anArgCase == "-glslsourcecode"
6129           || anArgCase == "-glslcode")
6130     {
6131       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6132       if (++anArgIter < theArgNb
6133       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
6134       {
6135         --anArgIter;
6136       }
6137       aDefCaps->glslDumpLevel = aGslsDumpLevel;
6138       if (aCaps != NULL)
6139       {
6140         aCaps->glslDumpLevel = aGslsDumpLevel;
6141       }
6142     }
6143     else if (anArgCase == "-debug")
6144     {
6145       if (++anArgIter < theArgNb
6146       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
6147       {
6148         --anArgIter;
6149       }
6150       aDefCaps->contextDebug = toEnableDebug;
6151     }
6152     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
6153           && (anArgIter + 1 == theArgNb))
6154     {
6155       // simple alias to turn on almost everything
6156       aDefCaps->contextDebug     = toEnableDebug;
6157       aDefCaps->contextSyncDebug = toEnableDebug;
6158       aDefCaps->glslWarnings     = toEnableDebug;
6159       if (!toEnableDebug)
6160       {
6161         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6162       }
6163       aDefCaps->suppressExtraMsg = !toEnableDebug;
6164       if (aCaps != NULL)
6165       {
6166         aCaps->contextDebug     = toEnableDebug;
6167         aCaps->contextSyncDebug = toEnableDebug;
6168         aCaps->glslWarnings     = toEnableDebug;
6169         if (!toEnableDebug)
6170         {
6171           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6172         }
6173         aCaps->suppressExtraMsg = !toEnableDebug;
6174       }
6175     }
6176     else
6177     {
6178       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
6179       return 1;
6180     }
6181   }
6182
6183   return 0;
6184 }
6185
6186 //==============================================================================
6187 //function : VVbo
6188 //purpose  :
6189 //==============================================================================
6190
6191 static int VVbo (Draw_Interpretor& theDI,
6192                  Standard_Integer  theArgNb,
6193                  const char**      theArgVec)
6194 {
6195   const Standard_Boolean toSet    = (theArgNb > 1);
6196   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
6197   if (toSet)
6198   {
6199     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
6200   }
6201
6202   // get the context
6203   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6204   if (aContextAIS.IsNull())
6205   {
6206     if (!toSet)
6207     {
6208       std::cerr << "No active view!\n";
6209     }
6210     return 1;
6211   }
6212   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
6213   if (!aDriver.IsNull())
6214   {
6215     if (!toSet)
6216     {
6217       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
6218     }
6219     else
6220     {
6221       aDriver->ChangeOptions().vboDisable = toUseVbo;
6222     }
6223   }
6224
6225   return 0;
6226 }
6227
6228 //==============================================================================
6229 //function : VCaps
6230 //purpose  :
6231 //==============================================================================
6232
6233 static int VCaps (Draw_Interpretor& theDI,
6234                   Standard_Integer  theArgNb,
6235                   const char**      theArgVec)
6236 {
6237   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
6238   Handle(OpenGl_GraphicDriver)   aDriver;
6239   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6240   if (!aContext.IsNull())
6241   {
6242     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
6243     aCaps   = &aDriver->ChangeOptions();
6244   }
6245
6246   if (theArgNb < 2)
6247   {
6248     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
6249     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
6250     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
6251     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
6252     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
6253     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
6254     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
6255     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
6256     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
6257     return 0;
6258   }
6259
6260   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6261   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6262   {
6263     Standard_CString        anArg     = theArgVec[anArgIter];
6264     TCollection_AsciiString anArgCase (anArg);
6265     anArgCase.LowerCase();
6266     if (anUpdateTool.parseRedrawMode (anArg))
6267     {
6268       continue;
6269     }
6270     else if (anArgCase == "-vsync"
6271           || anArgCase == "-swapinterval")
6272     {
6273       Standard_Boolean toEnable = Standard_True;
6274       if (++anArgIter < theArgNb
6275       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6276       {
6277         --anArgIter;
6278       }
6279       aCaps->swapInterval = toEnable;
6280     }
6281     else if (anArgCase == "-ffp")
6282     {
6283       Standard_Boolean toEnable = Standard_True;
6284       if (++anArgIter < theArgNb
6285       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6286       {
6287         --anArgIter;
6288       }
6289       aCaps->ffpEnable = toEnable;
6290     }
6291     else if (anArgCase == "-polygonmode")
6292     {
6293       Standard_Boolean toEnable = Standard_True;
6294       if (++anArgIter < theArgNb
6295       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6296       {
6297         --anArgIter;
6298       }
6299       aCaps->usePolygonMode = toEnable;
6300     }
6301     else if (anArgCase == "-vbo")
6302     {
6303       Standard_Boolean toEnable = Standard_True;
6304       if (++anArgIter < theArgNb
6305       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6306       {
6307         --anArgIter;
6308       }
6309       aCaps->vboDisable = !toEnable;
6310     }
6311     else if (anArgCase == "-sprite"
6312           || anArgCase == "-sprites")
6313     {
6314       Standard_Boolean toEnable = Standard_True;
6315       if (++anArgIter < theArgNb
6316       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6317       {
6318         --anArgIter;
6319       }
6320       aCaps->pntSpritesDisable = !toEnable;
6321     }
6322     else if (anArgCase == "-softmode")
6323     {
6324       Standard_Boolean toEnable = Standard_True;
6325       if (++anArgIter < theArgNb
6326       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6327       {
6328         --anArgIter;
6329       }
6330       aCaps->contextNoAccel = toEnable;
6331     }
6332     else if (anArgCase == "-winbuffer"
6333           || anArgCase == "-windowbuffer"
6334           || anArgCase == "-usewinbuffer"
6335           || anArgCase == "-usewindowbuffer"
6336           || anArgCase == "-usesystembuffer")
6337     {
6338       Standard_Boolean toEnable = Standard_True;
6339       if (++anArgIter < theArgNb
6340       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6341       {
6342         --anArgIter;
6343       }
6344       aCaps->useSystemBuffer = toEnable;
6345     }
6346     else if (anArgCase == "-accel"
6347           || anArgCase == "-acceleration")
6348     {
6349       Standard_Boolean toEnable = Standard_True;
6350       if (++anArgIter < theArgNb
6351       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6352       {
6353         --anArgIter;
6354       }
6355       aCaps->contextNoAccel = !toEnable;
6356     }
6357     else if (anArgCase == "-compat"
6358           || anArgCase == "-compatprofile"
6359           || anArgCase == "-compatible"
6360           || anArgCase == "-compatibleprofile")
6361     {
6362       Standard_Boolean toEnable = Standard_True;
6363       if (++anArgIter < theArgNb
6364       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6365       {
6366         --anArgIter;
6367       }
6368       aCaps->contextCompatible = toEnable;
6369       if (!aCaps->contextCompatible)
6370       {
6371         aCaps->ffpEnable = Standard_False;
6372       }
6373     }
6374     else if (anArgCase == "-core"
6375           || anArgCase == "-coreprofile")
6376     {
6377       Standard_Boolean toEnable = Standard_True;
6378       if (++anArgIter < theArgNb
6379       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6380       {
6381         --anArgIter;
6382       }
6383       aCaps->contextCompatible = !toEnable;
6384       if (!aCaps->contextCompatible)
6385       {
6386         aCaps->ffpEnable = Standard_False;
6387       }
6388     }
6389     else if (anArgCase == "-stereo"
6390           || anArgCase == "-quadbuffer")
6391     {
6392       Standard_Boolean toEnable = Standard_True;
6393       if (++anArgIter < theArgNb
6394       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6395       {
6396         --anArgIter;
6397       }
6398       aCaps->contextStereo = toEnable;
6399     }
6400     else
6401     {
6402       std::cout << "Error: unknown argument '" << anArg << "'\n";
6403       return 1;
6404     }
6405   }
6406   if (aCaps != &ViewerTest_myDefaultCaps)
6407   {
6408     ViewerTest_myDefaultCaps = *aCaps;
6409   }
6410   return 0;
6411 }
6412
6413 //==============================================================================
6414 //function : VMemGpu
6415 //purpose  :
6416 //==============================================================================
6417
6418 static int VMemGpu (Draw_Interpretor& theDI,
6419                     Standard_Integer  theArgNb,
6420                     const char**      theArgVec)
6421 {
6422   // get the context
6423   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6424   if (aContextAIS.IsNull())
6425   {
6426     std::cerr << "No active view. Please call vinit.\n";
6427     return 1;
6428   }
6429
6430   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
6431   if (aDriver.IsNull())
6432   {
6433     std::cerr << "Graphic driver not available.\n";
6434     return 1;
6435   }
6436
6437   Standard_Size aFreeBytes = 0;
6438   TCollection_AsciiString anInfo;
6439   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
6440   {
6441     std::cerr << "Information not available.\n";
6442     return 1;
6443   }
6444
6445   if (theArgNb > 1 && *theArgVec[1] == 'f')
6446   {
6447     theDI << Standard_Real (aFreeBytes);
6448   }
6449   else
6450   {
6451     theDI << anInfo;
6452   }
6453
6454   return 0;
6455 }
6456
6457 // ==============================================================================
6458 // function : VReadPixel
6459 // purpose  :
6460 // ==============================================================================
6461 static int VReadPixel (Draw_Interpretor& theDI,
6462                        Standard_Integer  theArgNb,
6463                        const char**      theArgVec)
6464 {
6465   // get the active view
6466   Handle(V3d_View) aView = ViewerTest::CurrentView();
6467   if (aView.IsNull())
6468   {
6469     std::cerr << "No active view. Please call vinit.\n";
6470     return 1;
6471   }
6472   else if (theArgNb < 3)
6473   {
6474     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
6475     return 1;
6476   }
6477
6478   Image_Format         aFormat     = Image_Format_RGBA;
6479   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
6480
6481   Standard_Integer aWidth, aHeight;
6482   aView->Window()->Size (aWidth, aHeight);
6483   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
6484   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
6485   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
6486   {
6487     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
6488     return 1;
6489   }
6490
6491   Standard_Boolean toShowName = Standard_False;
6492   Standard_Boolean toShowHls  = Standard_False;
6493   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6494   {
6495     TCollection_AsciiString aParam (theArgVec[anIter]);
6496     aParam.LowerCase();
6497     if (aParam == "-rgb"
6498      || aParam == "rgb")
6499     {
6500       aFormat     = Image_Format_RGB;
6501       aBufferType = Graphic3d_BT_RGB;
6502     }
6503     else if (aParam == "-hls"
6504           || aParam == "hls")
6505     {
6506       aFormat     = Image_Format_RGB;
6507       aBufferType = Graphic3d_BT_RGB;
6508       toShowHls   = Standard_True;
6509     }
6510     else if (aParam == "-rgbf"
6511           || aParam == "rgbf")
6512     {
6513       aFormat     = Image_Format_RGBF;
6514       aBufferType = Graphic3d_BT_RGB;
6515     }
6516     else if (aParam == "-rgba"
6517           || aParam == "rgba")
6518     {
6519       aFormat     = Image_Format_RGBA;
6520       aBufferType = Graphic3d_BT_RGBA;
6521     }
6522     else if (aParam == "-rgbaf"
6523           || aParam == "rgbaf")
6524     {
6525       aFormat     = Image_Format_RGBAF;
6526       aBufferType = Graphic3d_BT_RGBA;
6527     }
6528     else if (aParam == "-depth"
6529           || aParam == "depth")
6530     {
6531       aFormat     = Image_Format_GrayF;
6532       aBufferType = Graphic3d_BT_Depth;
6533     }
6534     else if (aParam == "-name"
6535           || aParam == "name")
6536     {
6537       toShowName = Standard_True;
6538     }
6539     else
6540     {
6541       std::cout << "Syntax error at '" << aParam << "'\n";
6542     }
6543   }
6544
6545   Image_PixMap anImage;
6546   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6547   {
6548     std::cerr << "Image allocation failed\n";
6549     return 1;
6550   }
6551   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6552   {
6553     std::cerr << "Image dump failed\n";
6554     return 1;
6555   }
6556
6557   // redirect possible warning messages that could have been added by ToPixMap
6558   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6559   // contaminate result of the command
6560   Standard_CString aWarnLog = theDI.Result();
6561   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6562   {
6563     std::cout << aWarnLog << std::endl;
6564   }
6565   theDI.Reset();
6566
6567   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6568   if (toShowName)
6569   {
6570     if (aBufferType == Graphic3d_BT_RGBA)
6571     {
6572       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6573     }
6574     else
6575     {
6576       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6577     }
6578   }
6579   else
6580   {
6581     switch (aBufferType)
6582     {
6583       default:
6584       case Graphic3d_BT_RGB:
6585       {
6586         if (toShowHls)
6587         {
6588           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6589         }
6590         else
6591         {
6592           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6593         }
6594         break;
6595       }
6596       case Graphic3d_BT_RGBA:
6597       {
6598         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6599         break;
6600       }
6601       case Graphic3d_BT_Depth:
6602       {
6603         theDI << aColor.GetRGB().Red();
6604         break;
6605       }
6606     }
6607   }
6608
6609   return 0;
6610 }
6611
6612 //! Auxiliary presentation for an image plane.
6613 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6614 {
6615 public:
6616   //! Main constructor.
6617   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6618                        const Standard_Real theWidth,
6619                        const Standard_Real theHeight,
6620                        const TCollection_AsciiString& theLabel)
6621   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6622   {
6623     SetDisplayMode (0);
6624     SetHilightMode (1);
6625     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6626     {
6627       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6628       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6629       Graphic3d_MaterialAspect aMat;
6630       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6631       aMat.SetAmbient  (1.0);
6632       aMat.SetDiffuse  (1.0);
6633       aMat.SetSpecular (1.0);
6634       aMat.SetEmissive (1.0);
6635       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6636       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6637       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6638       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6639       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6640       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6641       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6642       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6643       aFillAspect->SetFrontMaterial (aMat);
6644       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6645       aFillAspect->SetTextureMapOn();
6646     }
6647     {
6648       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6649       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6650       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6651       myDrawer->SetTextAspect (aTextAspect);
6652     }
6653     {
6654       const gp_Dir aNorm (0.0, 0.0, 1.0);
6655       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6656       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6657       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6658       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6659       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6660       myTris->AddEdge (1);
6661       myTris->AddEdge (2);
6662       myTris->AddEdge (3);
6663       myTris->AddEdge (3);
6664       myTris->AddEdge (2);
6665       myTris->AddEdge (4);
6666
6667       myRect = new Graphic3d_ArrayOfPolylines (4);
6668       myRect->AddVertex (myTris->Vertice (1));
6669       myRect->AddVertex (myTris->Vertice (3));
6670       myRect->AddVertex (myTris->Vertice (4));
6671       myRect->AddVertex (myTris->Vertice (2));
6672     }
6673   }
6674
6675   //! Returns TRUE for accepted display modes.
6676   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6677
6678   //! Compute presentation.
6679   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6680   {
6681     switch (theMode)
6682     {
6683       case 0:
6684       {
6685         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6686         aGroup->AddPrimitiveArray (myTris);
6687         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6688         aGroup->AddPrimitiveArray (myRect);
6689         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6690         return;
6691       }
6692       case 1:
6693       {
6694         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6695         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6696         aGroup->AddPrimitiveArray (myRect);
6697         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6698         return;
6699       }
6700     }
6701   }
6702
6703   //! Compute selection.
6704   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6705   {
6706     if (theMode == 0)
6707     {
6708       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6709       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6710       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6711       theSel->Add (aSensitive);
6712     }
6713   }
6714
6715 private:
6716   Handle(Graphic3d_ArrayOfTriangles) myTris;
6717   Handle(Graphic3d_ArrayOfPolylines) myRect;
6718   TCollection_AsciiString myLabel;
6719   Standard_Real myWidth;
6720   Standard_Real myHeight;
6721 };
6722
6723 //==============================================================================
6724 //function : VDiffImage
6725 //purpose  : The draw-command compares two images.
6726 //==============================================================================
6727
6728 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6729 {
6730   if (theArgNb < 3)
6731   {
6732     std::cout << "Syntax error: not enough arguments.\n";
6733     return 1;
6734   }
6735
6736   Standard_Integer anArgIter = 1;
6737   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6738   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6739   TCollection_AsciiString aDiffImagePath;
6740   Standard_Real    aTolColor        = -1.0;
6741   Standard_Integer toBlackWhite     = -1;
6742   Standard_Integer isBorderFilterOn = -1;
6743   Standard_Boolean isOldSyntax = Standard_False;
6744   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6745   for (; anArgIter < theArgNb; ++anArgIter)
6746   {
6747     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6748     anArg.LowerCase();
6749     if (anArgIter + 1 < theArgNb
6750      && (anArg == "-toleranceofcolor"
6751       || anArg == "-tolerancecolor"
6752       || anArg == "-tolerance"
6753       || anArg == "-toler"))
6754     {
6755       aTolColor = Atof (theArgVec[++anArgIter]);
6756       if (aTolColor < 0.0 || aTolColor > 1.0)
6757       {
6758         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6759         return 1;
6760       }
6761     }
6762     else if (anArg == "-blackwhite")
6763     {
6764       Standard_Boolean toEnable = Standard_True;
6765       if (anArgIter + 1 < theArgNb
6766        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6767       {
6768         ++anArgIter;
6769       }
6770       toBlackWhite = toEnable ? 1 : 0;
6771     }
6772     else if (anArg == "-borderfilter")
6773     {
6774       Standard_Boolean toEnable = Standard_True;
6775       if (anArgIter + 1 < theArgNb
6776        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6777       {
6778         ++anArgIter;
6779       }
6780       isBorderFilterOn = toEnable ? 1 : 0;
6781     }
6782     else if (anArg == "-exitonclose")
6783     {
6784       Draw_ToExitOnCloseView = true;
6785       if (anArgIter + 1 < theArgNb
6786        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6787       {
6788         ++anArgIter;
6789       }
6790     }
6791     else if (anArg == "-closeonescape"
6792           || anArg == "-closeonesc")
6793     {
6794       Draw_ToCloseViewOnEsc = true;
6795       if (anArgIter + 1 < theArgNb
6796        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6797       {
6798         ++anArgIter;
6799       }
6800     }
6801     else if (anArgIter + 3 < theArgNb
6802           && anArg == "-display")
6803     {
6804       aViewName   = theArgVec[++anArgIter];
6805       aPrsNameRef = theArgVec[++anArgIter];
6806       aPrsNameNew = theArgVec[++anArgIter];
6807       if (anArgIter + 1 < theArgNb
6808       && *theArgVec[anArgIter + 1] != '-')
6809       {
6810         aPrsNameDiff = theArgVec[++anArgIter];
6811       }
6812     }
6813     else if (aTolColor < 0.0
6814           && anArg.IsRealValue())
6815     {
6816       isOldSyntax = Standard_True;
6817       aTolColor = anArg.RealValue();
6818       if (aTolColor < 0.0 || aTolColor > 1.0)
6819       {
6820         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6821         return 1;
6822       }
6823     }
6824     else if (isOldSyntax
6825           && toBlackWhite == -1
6826           && (anArg == "0" || anArg == "1"))
6827     {
6828       toBlackWhite = anArg == "1" ? 1 : 0;
6829     }
6830     else if (isOldSyntax
6831           && isBorderFilterOn == -1
6832           && (anArg == "0" || anArg == "1"))
6833     {
6834       isBorderFilterOn = anArg == "1" ? 1 : 0;
6835     }
6836     else if (aDiffImagePath.IsEmpty())
6837     {
6838       aDiffImagePath = theArgVec[anArgIter];
6839     }
6840     else
6841     {
6842       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6843       return 1;
6844     }
6845   }
6846
6847   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6848   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6849   if (!anImgRef->Load (anImgPathRef))
6850   {
6851     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6852     return 1;
6853   }
6854   if (!anImgNew->Load (anImgPathNew))
6855   {
6856     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6857     return 1;
6858   }
6859
6860   // compare the images
6861   Image_Diff aComparer;
6862   Standard_Integer aDiffColorsNb = -1;
6863   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6864   {
6865     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6866     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6867     aDiffColorsNb = aComparer.Compare();
6868     theDI << aDiffColorsNb << "\n";
6869   }
6870
6871   // save image of difference
6872   Handle(Image_AlienPixMap) aDiff;
6873   if (aDiffColorsNb > 0
6874   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6875   {
6876     aDiff = new Image_AlienPixMap();
6877     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6878     {
6879       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6880       return 1;
6881     }
6882     aComparer.SaveDiffImage (*aDiff);
6883     if (!aDiffImagePath.IsEmpty()
6884      && !aDiff->Save (aDiffImagePath))
6885     {
6886       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6887       return 1;
6888     }
6889   }
6890
6891   if (aViewName.IsEmpty())
6892   {
6893     return 0;
6894   }
6895
6896   ViewerTest_Names aViewNames (aViewName);
6897   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6898   {
6899     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6900     theDI.Eval (aCommand.ToCString());
6901   }
6902
6903   Standard_Integer aPxLeft = 0;
6904   Standard_Integer aPxTop  = 0;
6905   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6906   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6907                               ? int(anImgRef->SizeY() * 2)
6908                               : int(anImgRef->SizeY());
6909   TCollection_AsciiString aDisplayName;
6910   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
6911                                                             aViewName, aDisplayName);
6912
6913   Standard_Real aRatio = anImgRef->Ratio();
6914   Standard_Real aSizeX = 1.0;
6915   Standard_Real aSizeY = aSizeX / aRatio;
6916   {
6917     OSD_Path aPath (anImgPathRef);
6918     TCollection_AsciiString aLabelRef;
6919     if (!aPath.Name().IsEmpty())
6920     {
6921       aLabelRef = aPath.Name() + aPath.Extension();
6922     }
6923     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6924
6925     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6926     gp_Trsf aTrsfRef;
6927     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6928     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6929     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6930   }
6931   {
6932     OSD_Path aPath (anImgPathNew);
6933     TCollection_AsciiString aLabelNew;
6934     if (!aPath.Name().IsEmpty())
6935     {
6936       aLabelNew = aPath.Name() + aPath.Extension();
6937     }
6938     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6939
6940     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6941     gp_Trsf aTrsfRef;
6942     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6943     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6944     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6945   }
6946   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6947   if (!aDiff.IsNull())
6948   {
6949     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6950     gp_Trsf aTrsfDiff;
6951     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6952     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6953   }
6954   if (!aPrsNameDiff.IsEmpty())
6955   {
6956     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6957   }
6958   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6959   ViewerTest::CurrentView()->FitAll();
6960   return 0;
6961 }
6962
6963 //=======================================================================
6964 //function : VSelect
6965 //purpose  : Emulates different types of selection by mouse:
6966 //           1) single click selection
6967 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6968 //           3) selection with polygon having corners at
6969 //           pixel positions (x1,y1),...,(xn,yn)
6970 //           4) any of these selections with shift button pressed
6971 //=======================================================================
6972 static Standard_Integer VSelect (Draw_Interpretor& di,
6973                                  Standard_Integer argc,
6974                                  const char ** argv)
6975 {
6976   if(argc < 3)
6977   {
6978     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6979     return 1;
6980   }
6981
6982   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6983   if(myAIScontext.IsNull())
6984   {
6985     di << "use 'vinit' command before " << argv[0] << "\n";
6986     return 1;
6987   }
6988
6989   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6990   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6991   TCollection_AsciiString anArg;
6992   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6993   anArg.LowerCase();
6994   if (anArg == "-allowoverlap")
6995   {
6996     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6997       : argc == 7;
6998     if (!isValidated)
6999     {
7000       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
7001       return 1;
7002     }
7003
7004     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
7005     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
7006     aCoordsNb -= 2;
7007   }
7008
7009   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7010   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
7011   if(aCoordsNb == 2)
7012   {
7013     if(isShiftSelection)
7014       aCurrentEventManager->ShiftSelect();
7015     else
7016       aCurrentEventManager->Select();
7017   }
7018   else if(aCoordsNb == 4)
7019   {
7020     if(isShiftSelection)
7021       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
7022     else
7023       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
7024   }
7025   else
7026   {
7027     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
7028
7029     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
7030       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
7031
7032     if(isShiftSelection)
7033       aCurrentEventManager->ShiftSelect(aPolyline);
7034     else
7035       aCurrentEventManager->Select(aPolyline);
7036   }
7037   return 0;
7038 }
7039
7040 //=======================================================================
7041 //function : VMoveTo
7042 //purpose  : Emulates cursor movement to defined pixel position
7043 //=======================================================================
7044 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7045                                 Standard_Integer theNbArgs,
7046                                 const char**     theArgVec)
7047 {
7048   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7049   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7050   if (aContext.IsNull())
7051   {
7052     std::cout << "Error: no active View\n";
7053     return 1;
7054   }
7055
7056   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7057   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7058   {
7059     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7060     anArgStr.LowerCase();
7061     if (anArgStr == "-reset"
7062      || anArgStr == "-clear")
7063     {
7064       if (anArgIter + 1 < theNbArgs)
7065       {
7066         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7067         return 1;
7068       }
7069
7070       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7071                                        && aContext->CurrentViewer()->GridEcho();
7072       if (toEchoGrid)
7073       {
7074         aContext->CurrentViewer()->HideGridEcho (aView);
7075       }
7076       if (aContext->ClearDetected() || toEchoGrid)
7077       {
7078         aContext->CurrentViewer()->RedrawImmediate();
7079       }
7080       return 0;
7081     }
7082     else if (aMousePos.x() == IntegerLast()
7083           && anArgStr.IsIntegerValue())
7084     {
7085       aMousePos.x() = anArgStr.IntegerValue();
7086     }
7087     else if (aMousePos.y() == IntegerLast()
7088           && anArgStr.IsIntegerValue())
7089     {
7090       aMousePos.y() = anArgStr.IntegerValue();
7091     }
7092     else
7093     {
7094       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7095       return 1;
7096     }
7097   }
7098
7099   if (aMousePos.x() == IntegerLast()
7100    || aMousePos.y() == IntegerLast())
7101   {
7102     std::cout << "Syntax error: wrong number of arguments\n";
7103     return 1;
7104   }
7105
7106   ViewerTest::CurrentEventManager()->MoveTo (aMousePos.x(), aMousePos.y());
7107   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7108   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7109   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7110   {
7111     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7112     {
7113       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7114       break;
7115     }
7116   }
7117   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7118   return 0;
7119 }
7120
7121 namespace
7122 {
7123   //! Global map storing all animations registered in ViewerTest.
7124   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7125
7126   //! The animation calling the Draw Harness command.
7127   class ViewerTest_AnimationProc : public AIS_Animation
7128   {
7129   public:
7130
7131     //! Main constructor.
7132     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7133                               Draw_Interpretor* theDI,
7134                               const TCollection_AsciiString& theCommand)
7135     : AIS_Animation (theAnimationName),
7136       myDrawInter(theDI),
7137       myCommand  (theCommand)
7138     {
7139       //
7140     }
7141
7142   protected:
7143
7144     //! Evaluate the command.
7145     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7146     {
7147       TCollection_AsciiString aCmd = myCommand;
7148       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7149       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7150       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7151       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7152       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7153       myDrawInter->Eval (aCmd.ToCString());
7154     }
7155
7156     //! Find the keyword in the command and replace it with value.
7157     //! @return the position of the keyword to pass value
7158     void replace (TCollection_AsciiString&       theCmd,
7159                   const TCollection_AsciiString& theKey,
7160                   const TCollection_AsciiString& theVal)
7161     {
7162       TCollection_AsciiString aCmd (theCmd);
7163       aCmd.LowerCase();
7164       const Standard_Integer aPos = aCmd.Search (theKey);
7165       if (aPos == -1)
7166       {
7167         return;
7168       }
7169
7170       TCollection_AsciiString aPart1, aPart2;
7171       Standard_Integer aPart1To = aPos - 1;
7172       if (aPart1To >= 1
7173        && aPart1To <= theCmd.Length())
7174       {
7175         aPart1 = theCmd.SubString (1, aPart1To);
7176       }
7177
7178       Standard_Integer aPart2From = aPos + theKey.Length();
7179       if (aPart2From >= 1
7180        && aPart2From <= theCmd.Length())
7181       {
7182         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7183       }
7184
7185       theCmd = aPart1 + theVal + aPart2;
7186     }
7187
7188   protected:
7189
7190     Draw_Interpretor*       myDrawInter;
7191     TCollection_AsciiString myCommand;
7192
7193   };
7194
7195   //! Replace the animation with the new one.
7196   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7197                                 Handle(AIS_Animation)&       theAnimation,
7198                                 const Handle(AIS_Animation)& theAnimationNew)
7199   {
7200     theAnimationNew->CopyFrom (theAnimation);
7201     if (!theParentAnimation.IsNull())
7202     {
7203       theParentAnimation->Replace (theAnimation, theAnimationNew);
7204     }
7205     else
7206     {
7207       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
7208       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7209     }
7210     theAnimation = theAnimationNew;
7211   }
7212
7213   //! Parse the point.
7214   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7215   {
7216     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7217     if (!anXYZ[0].IsRealValue()
7218      || !anXYZ[1].IsRealValue()
7219      || !anXYZ[2].IsRealValue())
7220     {
7221       return Standard_False;
7222     }
7223
7224     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7225     return Standard_True;
7226   }
7227
7228   //! Parse the quaternion.
7229   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7230   {
7231     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7232     if (!anXYZW[0].IsRealValue()
7233      || !anXYZW[1].IsRealValue()
7234      || !anXYZW[2].IsRealValue()
7235      || !anXYZW[3].IsRealValue())
7236     {
7237       return Standard_False;
7238     }
7239
7240     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7241     return Standard_True;
7242   }
7243
7244   //! Auxiliary class for flipping image upside-down.
7245   class ImageFlipper
7246   {
7247   public:
7248
7249     //! Empty constructor.
7250     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7251
7252     //! Perform flipping.
7253     Standard_Boolean FlipY (Image_PixMap& theImage)
7254     {
7255       if (theImage.IsEmpty()
7256        || theImage.SizeX() == 0
7257        || theImage.SizeY() == 0)
7258       {
7259         return Standard_False;
7260       }
7261
7262       const Standard_Size aRowSize = theImage.SizeRowBytes();
7263       if (myTmp.Size() < aRowSize
7264       && !myTmp.Allocate (aRowSize))
7265       {
7266         return Standard_False;
7267       }
7268
7269       // for odd height middle row should be left as is
7270       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7271       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7272       {
7273         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7274         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7275         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7276         memcpy (aTop,               aBot,         aRowSize);
7277         memcpy (aBot,               myTmp.Data(), aRowSize);
7278       }
7279       return Standard_True;
7280     }
7281
7282   private:
7283     NCollection_Buffer myTmp;
7284   };
7285
7286 }
7287
7288 //=================================================================================================
7289 //function : VViewParams
7290 //purpose  : Gets or sets AIS View characteristics
7291 //=================================================================================================
7292 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7293 {
7294   Handle(V3d_View) aView = ViewerTest::CurrentView();
7295   if (aView.IsNull())
7296   {
7297     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7298     return 1;
7299   }
7300
7301   Standard_Boolean toSetProj     = Standard_False;
7302   Standard_Boolean toSetUp       = Standard_False;
7303   Standard_Boolean toSetAt       = Standard_False;
7304   Standard_Boolean toSetEye      = Standard_False;
7305   Standard_Boolean toSetScale    = Standard_False;
7306   Standard_Boolean toSetSize     = Standard_False;
7307   Standard_Boolean toSetCenter2d = Standard_False;
7308   Standard_Real    aViewScale = aView->Scale();
7309   Standard_Real    aViewSize  = 1.0;
7310   Graphic3d_Vec2i  aCenter2d;
7311   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7312   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7313   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7314   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7315   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7316   if (theArgsNb == 1)
7317   {
7318     // print all of the available view parameters
7319     char aText[4096];
7320     Sprintf (aText,
7321              "Scale: %g\n"
7322              "Proj:  %12g %12g %12g\n"
7323              "Up:    %12g %12g %12g\n"
7324              "At:    %12g %12g %12g\n"
7325              "Eye:   %12g %12g %12g\n",
7326               aViewScale,
7327               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7328               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7329               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7330               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7331     theDi << aText;
7332     return 0;
7333   }
7334
7335   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7336   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7337   {
7338     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7339     anArg.LowerCase();
7340     if (anUpdateTool.parseRedrawMode (anArg))
7341     {
7342       continue;
7343     }
7344     else if (anArg == "-cmd"
7345           || anArg == "-command"
7346           || anArg == "-args")
7347     {
7348       char aText[4096];
7349       Sprintf (aText,
7350                "-scale %g "
7351                "-proj %g %g %g "
7352                "-up %g %g %g "
7353                "-at %g %g %g\n",
7354                 aViewScale,
7355                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7356                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7357                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7358       theDi << aText;
7359     }
7360     else if (anArg == "-scale"
7361           || anArg == "-size")
7362     {
7363       if (anArgIter + 1 < theArgsNb
7364        && *theArgVec[anArgIter + 1] != '-')
7365       {
7366         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
7367         if (aValueArg.IsRealValue())
7368         {
7369           ++anArgIter;
7370           if (anArg == "-scale")
7371           {
7372             toSetScale = Standard_True;
7373             aViewScale = aValueArg.RealValue();
7374           }
7375           else if (anArg == "-size")
7376           {
7377             toSetSize = Standard_True;
7378             aViewSize = aValueArg.RealValue();
7379           }
7380           continue;
7381         }
7382       }
7383       if (anArg == "-scale")
7384       {
7385         theDi << "Scale: " << aView->Scale() << "\n";
7386       }
7387       else if (anArg == "-size")
7388       {
7389         Graphic3d_Vec2d aSizeXY;
7390         aView->Size (aSizeXY.x(), aSizeXY.y());
7391         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
7392       }
7393     }
7394     else if (anArg == "-eye"
7395           || anArg == "-at"
7396           || anArg == "-up"
7397           || anArg == "-proj")
7398     {
7399       if (anArgIter + 3 < theArgsNb)
7400       {
7401         gp_XYZ anXYZ;
7402         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
7403         {
7404           anArgIter += 3;
7405           if (anArg == "-eye")
7406           {
7407             toSetEye = Standard_True;
7408             aViewEye = anXYZ;
7409           }
7410           else if (anArg == "-at")
7411           {
7412             toSetAt = Standard_True;
7413             aViewAt = anXYZ;
7414           }
7415           else if (anArg == "-up")
7416           {
7417             toSetUp = Standard_True;
7418             aViewUp = anXYZ;
7419           }
7420           else if (anArg == "-proj")
7421           {
7422             toSetProj = Standard_True;
7423             aViewProj = anXYZ;
7424           }
7425           continue;
7426         }
7427       }
7428
7429       if (anArg == "-eye")
7430       {
7431         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
7432       }
7433       else if (anArg == "-at")
7434       {
7435         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
7436       }
7437       else if (anArg == "-up")
7438       {
7439         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
7440       }
7441       else if (anArg == "-proj")
7442       {
7443         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
7444       }
7445     }
7446     else if (anArg == "-center")
7447     {
7448       if (anArgIter + 2 < theArgsNb)
7449       {
7450         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
7451         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
7452         if (anX.IsIntegerValue()
7453          && anY.IsIntegerValue())
7454         {
7455           toSetCenter2d = Standard_True;
7456           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
7457         }
7458       }
7459     }
7460     else
7461     {
7462       std::cout << "Syntax error at '" << anArg << "'\n";
7463       return 1;
7464     }
7465   }
7466
7467   // change view parameters in proper order
7468   if (toSetScale)
7469   {
7470     aView->SetScale (aViewScale);
7471   }
7472   if (toSetSize)
7473   {
7474     aView->SetSize (aViewSize);
7475   }
7476   if (toSetEye)
7477   {
7478     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7479   }
7480   if (toSetAt)
7481   {
7482     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7483   }
7484   if (toSetProj)
7485   {
7486     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7487   }
7488   if (toSetUp)
7489   {
7490     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7491   }
7492   if (toSetCenter2d)
7493   {
7494     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
7495   }
7496
7497   return 0;
7498 }
7499
7500 //==============================================================================
7501 //function : V2DMode
7502 //purpose  :
7503 //==============================================================================
7504 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7505 {
7506   bool is2dMode = true;
7507   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7508   if (aV3dView.IsNull())
7509   {
7510     std::cout << "Error: no active view.\n";
7511     return 1;
7512   }
7513   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7514   {
7515     const TCollection_AsciiString anArg = theArgVec[anArgIt];
7516     TCollection_AsciiString anArgCase = anArg;
7517     anArgCase.LowerCase();
7518     if (anArgIt + 1 < theArgsNb
7519      && anArgCase == "-name")
7520     {
7521       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
7522       TCollection_AsciiString aViewName = aViewNames.GetViewName();
7523       if (!ViewerTest_myViews.IsBound1 (aViewName))
7524       {
7525         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
7526         return 1;
7527       }
7528       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7529     }
7530     else if (anArgCase == "-mode")
7531     {
7532       if (anArgIt + 1 < theArgsNb
7533        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
7534       {
7535         ++anArgIt;
7536       }
7537     }
7538     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
7539     {
7540       //
7541     }
7542     else
7543     {
7544       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
7545       return 1;
7546     }
7547   }
7548
7549   aV3dView->SetView2DMode (is2dMode);
7550   return 0;
7551 }
7552
7553 //==============================================================================
7554 //function : VAnimation
7555 //purpose  :
7556 //==============================================================================
7557 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7558                                     Standard_Integer  theArgNb,
7559                                     const char**      theArgVec)
7560 {
7561   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7562   if (theArgNb < 2)
7563   {
7564     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7565          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7566     {
7567       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
7568     }
7569     return 0;
7570   }
7571   if (aCtx.IsNull())
7572   {
7573     std::cout << "Error: no active view\n";
7574     return 1;
7575   }
7576
7577   Standard_Integer anArgIter = 1;
7578   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7579   if (aNameArg.IsEmpty())
7580   {
7581     std::cout << "Syntax error: animation name is not defined.\n";
7582     return 1;
7583   }
7584
7585   TCollection_AsciiString aNameArgLower = aNameArg;
7586   aNameArgLower.LowerCase();
7587   if (aNameArgLower == "-reset"
7588    || aNameArgLower == "-clear")
7589   {
7590     ViewerTest_AnimationTimelineMap.Clear();
7591     return 0;
7592   }
7593   else if (aNameArg.Value (1) == '-')
7594   {
7595     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
7596     return 1;
7597   }
7598
7599   const char* aNameSplitter = "/";
7600   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7601   if (aSplitPos == -1)
7602   {
7603     aNameSplitter = ".";
7604     aSplitPos = aNameArg.Search (aNameSplitter);
7605   }
7606
7607   // find existing or create a new animation by specified name within syntax "parent.child".
7608   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
7609   for (; !aNameArg.IsEmpty();)
7610   {
7611     TCollection_AsciiString aNameParent;
7612     if (aSplitPos != -1)
7613     {
7614       if (aSplitPos == aNameArg.Length())
7615       {
7616         std::cout << "Syntax error: animation name is not defined.\n";
7617         return 1;
7618       }
7619
7620       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7621       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7622
7623       aSplitPos = aNameArg.Search (aNameSplitter);
7624     }
7625     else
7626     {
7627       aNameParent = aNameArg;
7628       aNameArg.Clear();
7629     }
7630
7631     if (anAnimation.IsNull())
7632     {
7633       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7634       {
7635         anAnimation = new AIS_Animation (aNameParent);
7636         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7637       }
7638       aRootAnimation = anAnimation;
7639     }
7640     else
7641     {
7642       aParentAnimation = anAnimation;
7643       anAnimation = aParentAnimation->Find (aNameParent);
7644       if (anAnimation.IsNull())
7645       {
7646         anAnimation = new AIS_Animation (aNameParent);
7647         aParentAnimation->Add (anAnimation);
7648       }
7649     }
7650   }
7651
7652   if (anArgIter >= theArgNb)
7653   {
7654     // just print the list of children
7655     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7656     {
7657       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7658     }
7659     return 0;
7660   }
7661
7662   // animation parameters
7663   Standard_Boolean toPlay = Standard_False;
7664   Standard_Real aPlaySpeed     = 1.0;
7665   Standard_Real aPlayStartTime = anAnimation->StartPts();
7666   Standard_Real aPlayDuration  = anAnimation->Duration();
7667   Standard_Boolean isFreeCamera = Standard_False;
7668   Standard_Boolean isLockLoop   = Standard_False;
7669
7670   // video recording parameters
7671   TCollection_AsciiString aRecFile;
7672   Image_VideoParams aRecParams;
7673
7674   Handle(V3d_View) aView = ViewerTest::CurrentView();
7675   for (; anArgIter < theArgNb; ++anArgIter)
7676   {
7677     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7678     anArg.LowerCase();
7679     // general options
7680     if (anArg == "-reset"
7681      || anArg == "-clear")
7682     {
7683       anAnimation->Clear();
7684     }
7685     else if (anArg == "-remove"
7686           || anArg == "-del"
7687           || anArg == "-delete")
7688     {
7689       if (!aParentAnimation.IsNull())
7690       {
7691         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7692       }
7693       else
7694       {
7695         aParentAnimation->Remove (anAnimation);
7696       }
7697     }
7698     // playback options
7699     else if (anArg == "-play")
7700     {
7701       toPlay = Standard_True;
7702       if (++anArgIter < theArgNb)
7703       {
7704         if (*theArgVec[anArgIter] == '-')
7705         {
7706           --anArgIter;
7707           continue;
7708         }
7709         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7710
7711         if (++anArgIter < theArgNb)
7712         {
7713           if (*theArgVec[anArgIter] == '-')
7714           {
7715             --anArgIter;
7716             continue;
7717           }
7718           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7719         }
7720       }
7721     }
7722     else if (anArg == "-resume")
7723     {
7724       toPlay = Standard_True;
7725       aPlayStartTime = anAnimation->ElapsedTime();
7726       if (++anArgIter < theArgNb)
7727       {
7728         if (*theArgVec[anArgIter] == '-')
7729         {
7730           --anArgIter;
7731           continue;
7732         }
7733
7734         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7735       }
7736     }
7737     else if (anArg == "-playspeed"
7738           || anArg == "-speed")
7739     {
7740       if (++anArgIter >= theArgNb)
7741       {
7742         std::cout << "Syntax error at " << anArg << ".\n";
7743         return 1;
7744       }
7745       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7746     }
7747     else if (anArg == "-lock"
7748           || anArg == "-lockloop"
7749           || anArg == "-playlockloop")
7750     {
7751       isLockLoop = Standard_True;
7752     }
7753     else if (anArg == "-freecamera"
7754           || anArg == "-playfreecamera"
7755           || anArg == "-freelook")
7756     {
7757       isFreeCamera = Standard_True;
7758     }
7759     // video recodring options
7760     else if (anArg == "-rec"
7761           || anArg == "-record")
7762     {
7763       if (++anArgIter >= theArgNb)
7764       {
7765         std::cout << "Syntax error at " << anArg << ".\n";
7766         return 1;
7767       }
7768
7769       aRecFile = theArgVec[anArgIter];
7770       if (aRecParams.FpsNum <= 0)
7771       {
7772         aRecParams.FpsNum = 24;
7773       }
7774
7775       if (anArgIter + 2 < theArgNb
7776       && *theArgVec[anArgIter + 1] != '-'
7777       && *theArgVec[anArgIter + 2] != '-')
7778       {
7779         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7780         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7781         if (aWidthArg .IsIntegerValue()
7782          && aHeightArg.IsIntegerValue())
7783         {
7784           aRecParams.Width  = aWidthArg .IntegerValue();
7785           aRecParams.Height = aHeightArg.IntegerValue();
7786           anArgIter += 2;
7787         }
7788       }
7789     }
7790     else if (anArg == "-fps")
7791     {
7792       if (++anArgIter >= theArgNb)
7793       {
7794         std::cout << "Syntax error at " << anArg << ".\n";
7795         return 1;
7796       }
7797
7798       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7799       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7800       if (aSplitIndex == 0)
7801       {
7802         aRecParams.FpsNum = aFpsArg.IntegerValue();
7803       }
7804       else
7805       {
7806         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7807         aFpsArg.Split (aFpsArg.Length() - 1);
7808         const TCollection_AsciiString aNumStr = aFpsArg;
7809         aRecParams.FpsNum = aNumStr.IntegerValue();
7810         aRecParams.FpsDen = aDenStr.IntegerValue();
7811         if (aRecParams.FpsDen < 1)
7812         {
7813           std::cout << "Syntax error at " << anArg << ".\n";
7814           return 1;
7815         }
7816       }
7817     }
7818     else if (anArg == "-format")
7819     {
7820       if (++anArgIter >= theArgNb)
7821       {
7822         std::cout << "Syntax error at " << anArg << ".\n";
7823         return 1;
7824       }
7825       aRecParams.Format = theArgVec[anArgIter];
7826     }
7827     else if (anArg == "-pix_fmt"
7828           || anArg == "-pixfmt"
7829           || anArg == "-pixelformat")
7830     {
7831       if (++anArgIter >= theArgNb)
7832       {
7833         std::cout << "Syntax error at " << anArg << ".\n";
7834         return 1;
7835       }
7836       aRecParams.PixelFormat = theArgVec[anArgIter];
7837     }
7838     else if (anArg == "-codec"
7839           || anArg == "-vcodec"
7840           || anArg == "-videocodec")
7841     {
7842       if (++anArgIter >= theArgNb)
7843       {
7844         std::cout << "Syntax error at " << anArg << ".\n";
7845         return 1;
7846       }
7847       aRecParams.VideoCodec = theArgVec[anArgIter];
7848     }
7849     else if (anArg == "-crf"
7850           || anArg == "-preset"
7851           || anArg == "-qp")
7852     {
7853       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7854       if (++anArgIter >= theArgNb)
7855       {
7856         std::cout << "Syntax error at " << anArg << ".\n";
7857         return 1;
7858       }
7859
7860       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7861     }
7862     // animation definition options
7863     else if (anArg == "-start"
7864           || anArg == "-starttime"
7865           || anArg == "-startpts")
7866     {
7867       if (++anArgIter >= theArgNb)
7868       {
7869         std::cout << "Syntax error at " << anArg << ".\n";
7870         return 1;
7871       }
7872
7873       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7874       aRootAnimation->UpdateTotalDuration();
7875     }
7876     else if (anArg == "-end"
7877           || anArg == "-endtime"
7878           || anArg == "-endpts")
7879     {
7880       if (++anArgIter >= theArgNb)
7881       {
7882         std::cout << "Syntax error at " << anArg << ".\n";
7883         return 1;
7884       }
7885
7886       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7887       aRootAnimation->UpdateTotalDuration();
7888     }
7889     else if (anArg == "-dur"
7890           || anArg == "-duration")
7891     {
7892       if (++anArgIter >= theArgNb)
7893       {
7894         std::cout << "Syntax error at " << anArg << ".\n";
7895         return 1;
7896       }
7897
7898       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7899       aRootAnimation->UpdateTotalDuration();
7900     }
7901     else if (anArg == "-command"
7902           || anArg == "-cmd"
7903           || anArg == "-invoke"
7904           || anArg == "-eval"
7905           || anArg == "-proc")
7906     {
7907       if (++anArgIter >= theArgNb)
7908       {
7909         std::cout << "Syntax error at " << anArg << ".\n";
7910         return 1;
7911       }
7912
7913       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7914       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7915     }
7916     else if (anArg == "-objecttrsf"
7917           || anArg == "-objectransformation"
7918           || anArg == "-objtransformation"
7919           || anArg == "-objtrsf"
7920           || anArg == "-object"
7921           || anArg == "-obj")
7922     {
7923       if (++anArgIter >= theArgNb)
7924       {
7925         std::cout << "Syntax error at " << anArg << ".\n";
7926         return 1;
7927       }
7928
7929       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7930       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7931       Handle(AIS_InteractiveObject) anObject;
7932       if (!aMapOfAIS.Find2 (anObjName, anObject))
7933       {
7934         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7935         return 1;
7936       }
7937
7938       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7939       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7940       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7941       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7942       Standard_Boolean isTrsfSet = Standard_False;
7943       Standard_Integer aTrsfArgIter = anArgIter + 1;
7944       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7945       {
7946         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7947         aTrsfArg.LowerCase();
7948         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7949         if (aTrsfArg.StartsWith ("-rotation")
7950          || aTrsfArg.StartsWith ("-rot"))
7951         {
7952           isTrsfSet = Standard_True;
7953           if (aTrsfArgIter + 4 >= theArgNb
7954           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7955           {
7956             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7957             return 1;
7958           }
7959           aTrsfArgIter += 4;
7960         }
7961         else if (aTrsfArg.StartsWith ("-location")
7962               || aTrsfArg.StartsWith ("-loc"))
7963         {
7964           isTrsfSet = Standard_True;
7965           if (aTrsfArgIter + 3 >= theArgNb
7966           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7967           {
7968             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7969             return 1;
7970           }
7971           aTrsfArgIter += 3;
7972         }
7973         else if (aTrsfArg.StartsWith ("-scale"))
7974         {
7975           isTrsfSet = Standard_True;
7976           if (++aTrsfArgIter >= theArgNb)
7977           {
7978             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7979             return 1;
7980           }
7981
7982           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7983           if (!aScaleStr.IsRealValue())
7984           {
7985             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7986             return 1;
7987           }
7988           aScales[anIndex] = aScaleStr.RealValue();
7989         }
7990         else
7991         {
7992           anArgIter = aTrsfArgIter - 1;
7993           break;
7994         }
7995       }
7996       if (!isTrsfSet)
7997       {
7998         std::cout << "Syntax error at " << anArg << ".\n";
7999         return 1;
8000       }
8001       else if (aTrsfArgIter >= theArgNb)
8002       {
8003         anArgIter = theArgNb;
8004       }
8005
8006       aTrsfs[0].SetRotation        (aRotQuats[0]);
8007       aTrsfs[1].SetRotation        (aRotQuats[1]);
8008       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8009       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8010       aTrsfs[0].SetScaleFactor     (aScales[0]);
8011       aTrsfs[1].SetScaleFactor     (aScales[1]);
8012
8013       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8014       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8015     }
8016     else if (anArg == "-viewtrsf"
8017           || anArg == "-view")
8018     {
8019       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8020       if (aCamAnimation.IsNull())
8021       {
8022         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8023         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8024       }
8025
8026       Handle(Graphic3d_Camera) aCams[2] =
8027       {
8028         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8029         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8030       };
8031
8032       Standard_Boolean isTrsfSet = Standard_False;
8033       Standard_Integer aViewArgIter = anArgIter + 1;
8034       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8035       {
8036         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8037         aViewArg.LowerCase();
8038         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8039         if (aViewArg.StartsWith ("-scale"))
8040         {
8041           isTrsfSet = Standard_True;
8042           if (++aViewArgIter >= theArgNb)
8043           {
8044             std::cout << "Syntax error at " << anArg << ".\n";
8045             return 1;
8046           }
8047
8048           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8049           if (!aScaleStr.IsRealValue())
8050           {
8051             std::cout << "Syntax error at " << aViewArg << ".\n";
8052             return 1;
8053           }
8054           Standard_Real aScale = aScaleStr.RealValue();
8055           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8056           aCams[anIndex]->SetScale (aScale);
8057         }
8058         else if (aViewArg.StartsWith ("-eye")
8059               || aViewArg.StartsWith ("-center")
8060               || aViewArg.StartsWith ("-at")
8061               || aViewArg.StartsWith ("-up"))
8062         {
8063           isTrsfSet = Standard_True;
8064           gp_XYZ anXYZ;
8065           if (aViewArgIter + 3 >= theArgNb
8066           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8067           {
8068             std::cout << "Syntax error at " << aViewArg << ".\n";
8069             return 1;
8070           }
8071           aViewArgIter += 3;
8072
8073           if (aViewArg.StartsWith ("-eye"))
8074           {
8075             aCams[anIndex]->SetEye (anXYZ);
8076           }
8077           else if (aViewArg.StartsWith ("-center")
8078                 || aViewArg.StartsWith ("-at"))
8079           {
8080             aCams[anIndex]->SetCenter (anXYZ);
8081           }
8082           else if (aViewArg.StartsWith ("-up"))
8083           {
8084             aCams[anIndex]->SetUp (anXYZ);
8085           }
8086         }
8087         else
8088         {
8089           anArgIter = aViewArgIter - 1;
8090           break;
8091         }
8092       }
8093       if (!isTrsfSet)
8094       {
8095         std::cout << "Syntax error at " << anArg << ".\n";
8096         return 1;
8097       }
8098       else if (aViewArgIter >= theArgNb)
8099       {
8100         anArgIter = theArgNb;
8101       }
8102
8103       aCamAnimation->SetCameraStart(aCams[0]);
8104       aCamAnimation->SetCameraEnd  (aCams[1]);
8105     }
8106     else
8107     {
8108       std::cout << "Syntax error at " << anArg << ".\n";
8109       return 1;
8110     }
8111   }
8112
8113   if (!toPlay && aRecFile.IsEmpty())
8114   {
8115     return 0;
8116   }
8117
8118   // Start animation timeline and process frame updating.
8119   TheIsAnimating = Standard_True;
8120   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8121   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8122   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8123   if (isFreeCamera)
8124   {
8125     aView->Camera()->Copy (aCameraBack);
8126   }
8127
8128   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8129   if (aRecParams.FpsNum <= 0)
8130   {
8131     while (!anAnimation->IsStopped())
8132     {
8133       aCameraBack->Copy (aView->Camera());
8134       const Standard_Real aPts = anAnimation->UpdateTimer();
8135       if (isFreeCamera)
8136       {
8137         aView->Camera()->Copy (aCameraBack);
8138       }
8139
8140       if (aPts >= anUpperPts)
8141       {
8142         anAnimation->Pause();
8143         break;
8144       }
8145
8146       if (aView->IsInvalidated())
8147       {
8148         aView->Redraw();
8149       }
8150       else
8151       {
8152         aView->RedrawImmediate();
8153       }
8154
8155       if (!isLockLoop)
8156       {
8157         // handle user events
8158         theDI.Eval ("after 1 set waiter 1");
8159         theDI.Eval ("vwait waiter");
8160       }
8161       if (!TheIsAnimating)
8162       {
8163         anAnimation->Pause();
8164         theDI << aPts;
8165         break;
8166       }
8167     }
8168
8169     if (aView->IsInvalidated())
8170     {
8171       aView->Redraw();
8172     }
8173     else
8174     {
8175       aView->RedrawImmediate();
8176     }
8177   }
8178   else
8179   {
8180     OSD_Timer aPerfTimer;
8181     aPerfTimer.Start();
8182
8183     Handle(Image_VideoRecorder) aRecorder;
8184     ImageFlipper aFlipper;
8185     Handle(Draw_ProgressIndicator) aProgress;
8186     if (!aRecFile.IsEmpty())
8187     {
8188       if (aRecParams.Width  <= 0
8189        || aRecParams.Height <= 0)
8190       {
8191         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8192       }
8193
8194       aRecorder = new Image_VideoRecorder();
8195       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8196       {
8197         std::cout << "Error: failed to open video file for recording\n";
8198         return 0;
8199       }
8200
8201       aProgress = new Draw_ProgressIndicator (theDI, 1);
8202     }
8203
8204     // Manage frame-rated animation here
8205     Standard_Real aPts = aPlayStartTime;
8206     int64_t aNbFrames = 0;
8207     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
8208     Standard_Integer aSecondsProgress = 0;
8209     for (; aPts <= anUpperPts && aPSentry.More();)
8210     {
8211       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8212       aPts = aPlayStartTime + aRecPts;
8213       ++aNbFrames;
8214       if (!anAnimation->Update (aPts))
8215       {
8216         break;
8217       }
8218
8219       if (!aRecorder.IsNull())
8220       {
8221         V3d_ImageDumpOptions aDumpParams;
8222         aDumpParams.Width          = aRecParams.Width;
8223         aDumpParams.Height         = aRecParams.Height;
8224         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8225         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8226         aDumpParams.ToAdjustAspect = Standard_True;
8227         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8228         {
8229           std::cout << "Error: view dump is failed!\n";
8230           return 0;
8231         }
8232         aFlipper.FlipY (aRecorder->ChangeFrame());
8233         if (!aRecorder->PushFrame())
8234         {
8235           return 0;
8236         }
8237       }
8238       else
8239       {
8240         aView->Redraw();
8241       }
8242
8243       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8244       {
8245         aPSentry.Next();
8246         ++aSecondsProgress;
8247       }
8248     }
8249
8250     aPerfTimer.Stop();
8251     anAnimation->Stop();
8252     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8253     theDI << "Average FPS: " << aRecFps << "\n"
8254           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8255
8256     aView->Redraw();
8257   }
8258
8259   aView->SetImmediateUpdate (wasImmediateUpdate);
8260   TheIsAnimating = Standard_False;
8261   return 0;
8262 }
8263
8264
8265 //=======================================================================
8266 //function : VChangeSelected
8267 //purpose  : Adds the shape to selection or remove one from it
8268 //=======================================================================
8269 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8270                                 Standard_Integer argc,
8271                                 const char ** argv)
8272 {
8273   if(argc != 2)
8274   {
8275     di<<"Usage : " << argv[0] << " shape \n";
8276     return 1;
8277   }
8278   //get AIS_Shape:
8279   TCollection_AsciiString aName(argv[1]);
8280   Handle(AIS_InteractiveObject) anAISObject;
8281   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8282     || anAISObject.IsNull())
8283   {
8284     di<<"Use 'vdisplay' before";
8285     return 1;
8286   }
8287
8288   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8289   return 0;
8290 }
8291
8292 //=======================================================================
8293 //function : VNbSelected
8294 //purpose  : Returns number of selected objects
8295 //=======================================================================
8296 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8297                                 Standard_Integer argc,
8298                                 const char ** argv)
8299 {
8300   if(argc != 1)
8301   {
8302     di << "Usage : " << argv[0] << "\n";
8303     return 1;
8304   }
8305   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8306   if(aContext.IsNull())
8307   {
8308     di << "use 'vinit' command before " << argv[0] << "\n";
8309     return 1;
8310   }
8311   di << aContext->NbSelected() << "\n";
8312   return 0;
8313 }
8314
8315 //=======================================================================
8316 //function : VPurgeDisplay
8317 //purpose  : Switches altialiasing on or off
8318 //=======================================================================
8319 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8320                                 Standard_Integer argc,
8321                                 const char ** argv)
8322 {
8323   if (argc > 1)
8324   {
8325     di << "Usage : " << argv[0] << "\n";
8326     return 1;
8327   }
8328   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8329   if (aContext.IsNull())
8330   {
8331     di << "use 'vinit' command before " << argv[0] << "\n";
8332     return 1;
8333   }
8334
8335   di << aContext->PurgeDisplay() << "\n";
8336   return 0;
8337 }
8338
8339 //=======================================================================
8340 //function : VSetViewSize
8341 //purpose  :
8342 //=======================================================================
8343 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8344                                 Standard_Integer argc,
8345                                 const char ** argv)
8346 {
8347   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8348   if(aContext.IsNull())
8349   {
8350     di << "use 'vinit' command before " << argv[0] << "\n";
8351     return 1;
8352   }
8353   if(argc != 2)
8354   {
8355     di<<"Usage : " << argv[0] << " Size\n";
8356     return 1;
8357   }
8358   Standard_Real aSize = Draw::Atof (argv[1]);
8359   if (aSize <= 0.)
8360   {
8361     di<<"Bad Size value  : " << aSize << "\n";
8362     return 1;
8363   }
8364
8365   Handle(V3d_View) aView = ViewerTest::CurrentView();
8366   aView->SetSize(aSize);
8367   return 0;
8368 }
8369
8370 //=======================================================================
8371 //function : VMoveView
8372 //purpose  :
8373 //=======================================================================
8374 static Standard_Integer VMoveView (Draw_Interpretor& di,
8375                                 Standard_Integer argc,
8376                                 const char ** argv)
8377 {
8378   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8379   if(aContext.IsNull())
8380   {
8381     di << "use 'vinit' command before " << argv[0] << "\n";
8382     return 1;
8383   }
8384   if(argc < 4 || argc > 5)
8385   {
8386     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8387     return 1;
8388   }
8389   Standard_Real Dx = Draw::Atof (argv[1]);
8390   Standard_Real Dy = Draw::Atof (argv[2]);
8391   Standard_Real Dz = Draw::Atof (argv[3]);
8392   Standard_Boolean aStart = Standard_True;
8393   if (argc == 5)
8394   {
8395       aStart = (Draw::Atoi (argv[4]) > 0);
8396   }
8397
8398   Handle(V3d_View) aView = ViewerTest::CurrentView();
8399   aView->Move(Dx,Dy,Dz,aStart);
8400   return 0;
8401 }
8402
8403 //=======================================================================
8404 //function : VTranslateView
8405 //purpose  :
8406 //=======================================================================
8407 static Standard_Integer VTranslateView (Draw_Interpretor& di,
8408                                 Standard_Integer argc,
8409                                 const char ** argv)
8410 {
8411   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8412   if(aContext.IsNull())
8413   {
8414     di << "use 'vinit' command before " << argv[0] << "\n";
8415     return 1;
8416   }
8417   if(argc < 4 || argc > 5)
8418   {
8419     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8420     return 1;
8421   }
8422   Standard_Real Dx = Draw::Atof (argv[1]);
8423   Standard_Real Dy = Draw::Atof (argv[2]);
8424   Standard_Real Dz = Draw::Atof (argv[3]);
8425   Standard_Boolean aStart = Standard_True;
8426   if (argc == 5)
8427   {
8428       aStart = (Draw::Atoi (argv[4]) > 0);
8429   }
8430
8431   Handle(V3d_View) aView = ViewerTest::CurrentView();
8432   aView->Translate(Dx,Dy,Dz,aStart);
8433   return 0;
8434 }
8435
8436 //=======================================================================
8437 //function : VTurnView
8438 //purpose  :
8439 //=======================================================================
8440 static Standard_Integer VTurnView (Draw_Interpretor& di,
8441                                 Standard_Integer argc,
8442                                 const char ** argv)
8443 {
8444   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8445   if(aContext.IsNull()) {
8446     di << "use 'vinit' command before " << argv[0] << "\n";
8447     return 1;
8448   }
8449   if(argc < 4 || argc > 5){
8450     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
8451     return 1;
8452   }
8453   Standard_Real Ax = Draw::Atof (argv[1]);
8454   Standard_Real Ay = Draw::Atof (argv[2]);
8455   Standard_Real Az = Draw::Atof (argv[3]);
8456   Standard_Boolean aStart = Standard_True;
8457   if (argc == 5)
8458   {
8459       aStart = (Draw::Atoi (argv[4]) > 0);
8460   }
8461
8462   Handle(V3d_View) aView = ViewerTest::CurrentView();
8463   aView->Turn(Ax,Ay,Az,aStart);
8464   return 0;
8465 }
8466
8467 //==============================================================================
8468 //function : VTextureEnv
8469 //purpose  : ENables or disables environment mapping
8470 //==============================================================================
8471 class OCC_TextureEnv : public Graphic3d_TextureEnv
8472 {
8473 public:
8474   OCC_TextureEnv(const Standard_CString FileName);
8475   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8476   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8477                             const Standard_Boolean theModulateFlag,
8478                             const Graphic3d_TypeOfTextureFilter theFilter,
8479                             const Standard_ShortReal theXScale,
8480                             const Standard_ShortReal theYScale,
8481                             const Standard_ShortReal theXShift,
8482                             const Standard_ShortReal theYShift,
8483                             const Standard_ShortReal theAngle);
8484   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
8485 };
8486 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
8487
8488 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8489   : Graphic3d_TextureEnv(theFileName)
8490 {
8491 }
8492
8493 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8494   : Graphic3d_TextureEnv(theTexId)
8495 {
8496 }
8497
8498 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8499                                           const Standard_Boolean theModulateFlag,
8500                                           const Graphic3d_TypeOfTextureFilter theFilter,
8501                                           const Standard_ShortReal theXScale,
8502                                           const Standard_ShortReal theYScale,
8503                                           const Standard_ShortReal theXShift,
8504                                           const Standard_ShortReal theYShift,
8505                                           const Standard_ShortReal theAngle)
8506 {
8507   myParams->SetRepeat     (theRepeatFlag);
8508   myParams->SetModulate   (theModulateFlag);
8509   myParams->SetFilter     (theFilter);
8510   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
8511   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8512   myParams->SetRotation   (theAngle);
8513 }
8514
8515 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
8516 {
8517   // get the active view
8518   Handle(V3d_View) aView = ViewerTest::CurrentView();
8519   if (aView.IsNull())
8520   {
8521     std::cerr << "No active view. Please call vinit.\n";
8522     return 1;
8523   }
8524
8525   // Checking the input arguments
8526   Standard_Boolean anEnableFlag = Standard_False;
8527   Standard_Boolean isOk         = theArgNb >= 2;
8528   if (isOk)
8529   {
8530     TCollection_AsciiString anEnableOpt(theArgVec[1]);
8531     anEnableFlag = anEnableOpt.IsEqual("on");
8532     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
8533   }
8534   if (anEnableFlag)
8535   {
8536     isOk = (theArgNb == 3 || theArgNb == 11);
8537     if (isOk)
8538     {
8539       TCollection_AsciiString aTextureOpt(theArgVec[2]);
8540       isOk = (!aTextureOpt.IsIntegerValue() ||
8541              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8542
8543       if (isOk && theArgNb == 11)
8544       {
8545         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
8546                                 aModulateOpt(theArgVec[4]),
8547                                 aFilterOpt  (theArgVec[5]),
8548                                 aSScaleOpt  (theArgVec[6]),
8549                                 aTScaleOpt  (theArgVec[7]),
8550                                 aSTransOpt  (theArgVec[8]),
8551                                 aTTransOpt  (theArgVec[9]),
8552                                 anAngleOpt  (theArgVec[10]);
8553         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
8554                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8555                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
8556                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
8557                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
8558                 anAngleOpt.IsRealValue());
8559       }
8560     }
8561   }
8562
8563   if (!isOk)
8564   {
8565     std::cerr << "Usage :" << std::endl;
8566     std::cerr << theArgVec[0] << " off" << std::endl;
8567     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;
8568     return 1;
8569   }
8570
8571   if (anEnableFlag)
8572   {
8573     TCollection_AsciiString aTextureOpt(theArgVec[2]);
8574     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8575                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8576                                      new OCC_TextureEnv(theArgVec[2]);
8577
8578     if (theArgNb == 11)
8579     {
8580       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8581       aTexEnv->SetTextureParameters(
8582         aRepeatOpt.  IsEqual("repeat"),
8583         aModulateOpt.IsEqual("modulate"),
8584         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8585                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8586                                                                            Graphic3d_TOTF_TRILINEAR,
8587         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8588         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8589         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8590         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8591         (Standard_ShortReal)Draw::Atof(theArgVec[10])
8592         );
8593     }
8594     aView->SetTextureEnv(aTexEnv);
8595   }
8596   else // Disabling environment mapping
8597   {
8598     Handle(Graphic3d_TextureEnv) aTexture;
8599     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8600   }
8601
8602   aView->Redraw();
8603   return 0;
8604 }
8605
8606 namespace
8607 {
8608   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8609
8610   //! Remove registered clipping plane from all views and objects.
8611   static void removePlane (MapOfPlanes& theRegPlanes,
8612                            const TCollection_AsciiString& theName)
8613   {
8614     Handle(Graphic3d_ClipPlane) aClipPlane;
8615     if (!theRegPlanes.Find (theName, aClipPlane))
8616     {
8617       std::cout << "Warning: no such plane.\n";
8618       return;
8619     }
8620
8621     theRegPlanes.UnBind (theName);
8622     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8623          anIObjIt.More(); anIObjIt.Next())
8624     {
8625       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
8626       aPrs->RemoveClipPlane (aClipPlane);
8627     }
8628
8629     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8630          aViewIt.More(); aViewIt.Next())
8631     {
8632       const Handle(V3d_View)& aView = aViewIt.Key2();
8633       aView->RemoveClipPlane(aClipPlane);
8634     }
8635
8636     ViewerTest::RedrawAllViews();
8637   }
8638 }
8639
8640 //===============================================================================================
8641 //function : VClipPlane
8642 //purpose  :
8643 //===============================================================================================
8644 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8645 {
8646   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8647   static MapOfPlanes aRegPlanes;
8648
8649   if (theArgsNb < 2)
8650   {
8651     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8652     {
8653       theDi << aPlaneIter.Key() << " ";
8654     }
8655     return 0;
8656   }
8657
8658   TCollection_AsciiString aCommand (theArgVec[1]);
8659   aCommand.LowerCase();
8660   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8661   if (anActiveView.IsNull())
8662   {
8663     std::cout << "Error: no active view.\n";
8664     return 1;
8665   }
8666
8667   // print maximum number of planes for current viewer
8668   if (aCommand == "-maxplanes"
8669    || aCommand == "maxplanes")
8670   {
8671     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8672           << " plane slots provided by driver.\n";
8673     return 0;
8674   }
8675
8676   // create / delete plane instance
8677   if (aCommand == "-create"
8678    || aCommand == "create"
8679    || aCommand == "-delete"
8680    || aCommand == "delete"
8681    || aCommand == "-clone"
8682    || aCommand == "clone")
8683   {
8684     if (theArgsNb < 3)
8685     {
8686       std::cout << "Syntax error: plane name is required.\n";
8687       return 1;
8688     }
8689
8690     Standard_Boolean toCreate = aCommand == "-create"
8691                              || aCommand == "create";
8692     Standard_Boolean toClone  = aCommand == "-clone"
8693                              || aCommand == "clone";
8694     Standard_Boolean toDelete = aCommand == "-delete"
8695                              || aCommand == "delete";
8696     TCollection_AsciiString aPlane (theArgVec[2]);
8697
8698     if (toCreate)
8699     {
8700       if (aRegPlanes.IsBound (aPlane))
8701       {
8702         std::cout << "Warning: existing plane has been overridden.\n";
8703         toDelete = true;
8704       }
8705       else
8706       {
8707         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8708         return 0;
8709       }
8710     }
8711     else if (toClone) // toClone
8712     {
8713       if (!aRegPlanes.IsBound (aPlane))
8714       {
8715         std::cout << "Error: no such plane.\n";
8716         return 1;
8717       }
8718       else if (theArgsNb < 4)
8719       {
8720         std::cout << "Syntax error: enter name for new plane.\n";
8721         return 1;
8722       }
8723
8724       TCollection_AsciiString aClone (theArgVec[3]);
8725       if (aRegPlanes.IsBound (aClone))
8726       {
8727         std::cout << "Error: plane name is in use.\n";
8728         return 1;
8729       }
8730
8731       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8732
8733       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8734       return 0;
8735     }
8736
8737     if (toDelete)
8738     {
8739       if (aPlane == "ALL"
8740        || aPlane == "all"
8741        || aPlane == "*")
8742       {
8743         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8744         {
8745           aPlane = aPlaneIter.Key();
8746           removePlane (aRegPlanes, aPlane);
8747           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8748         }
8749       }
8750       else
8751       {
8752         removePlane (aRegPlanes, aPlane);
8753       }
8754     }
8755
8756     if (toCreate)
8757     {
8758       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8759     }
8760     return 0;
8761   }
8762
8763   // set / unset plane command
8764   if (aCommand == "set"
8765    || aCommand == "unset")
8766   {
8767     if (theArgsNb < 5)
8768     {
8769       std::cout << "Syntax error: need more arguments.\n";
8770       return 1;
8771     }
8772
8773     // redirect to new syntax
8774     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8775     anArgVec.SetValue (1, theArgVec[0]);
8776     anArgVec.SetValue (2, theArgVec[2]);
8777     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8778     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8779     {
8780       anArgVec.SetValue (anIt, theArgVec[anIt]);
8781     }
8782
8783     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8784   }
8785
8786   // change plane command
8787   TCollection_AsciiString aPlaneName;
8788   Handle(Graphic3d_ClipPlane) aClipPlane;
8789   Standard_Integer anArgIter = 0;
8790   if (aCommand == "-change"
8791    || aCommand == "change")
8792   {
8793     // old syntax support
8794     if (theArgsNb < 3)
8795     {
8796       std::cout << "Syntax error: need more arguments.\n";
8797       return 1;
8798     }
8799
8800     anArgIter  = 3;
8801     aPlaneName = theArgVec[2];
8802     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8803     {
8804       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8805       return 1;
8806     }
8807   }
8808   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8809   {
8810     anArgIter  = 2;
8811     aPlaneName = theArgVec[1];
8812   }
8813   else
8814   {
8815     anArgIter  = 2;
8816     aPlaneName = theArgVec[1];
8817     aClipPlane = new Graphic3d_ClipPlane();
8818     aRegPlanes.Bind (aPlaneName, aClipPlane);
8819     theDi << "Created new plane " << aPlaneName << ".\n";
8820   }
8821
8822   if (theArgsNb - anArgIter < 1)
8823   {
8824     std::cout << "Syntax error: need more arguments.\n";
8825     return 1;
8826   }
8827
8828   for (; anArgIter < theArgsNb; ++anArgIter)
8829   {
8830     const char**     aChangeArgs   = theArgVec + anArgIter;
8831     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8832     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8833     aChangeArg.LowerCase();
8834
8835     Standard_Boolean toEnable = Standard_True;
8836     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8837     {
8838       aClipPlane->SetOn (toEnable);
8839     }
8840     else if (aChangeArg.StartsWith ("-equation")
8841           || aChangeArg.StartsWith ("equation"))
8842     {
8843       if (aNbChangeArgs < 5)
8844       {
8845         std::cout << "Syntax error: need more arguments.\n";
8846         return 1;
8847       }
8848
8849       Standard_Integer aSubIndex = 1;
8850       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
8851       if (aPrefixLen < aChangeArg.Length())
8852       {
8853         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
8854         if (!aSubStr.IsIntegerValue()
8855           || aSubStr.IntegerValue() <= 0)
8856         {
8857           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8858           return 1;
8859         }
8860         aSubIndex = aSubStr.IntegerValue();
8861       }
8862
8863       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
8864       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
8865       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
8866       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
8867       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8868       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
8869       {
8870         if (aSubPln->ChainNextPlane().IsNull())
8871         {
8872           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8873         }
8874         aSubPln = aSubPln->ChainNextPlane();
8875       }
8876       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8877       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8878       anArgIter += 4;
8879     }
8880     else if ((aChangeArg == "-boxinterior"
8881            || aChangeArg == "-boxint"
8882            || aChangeArg == "-box")
8883             && aNbChangeArgs >= 7)
8884     {
8885       Graphic3d_BndBox3d aBndBox;
8886       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
8887       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
8888       anArgIter += 6;
8889
8890       Standard_Integer aNbSubPlanes = 6;
8891       const Graphic3d_Vec3d aDirArray[6] =
8892       {
8893         Graphic3d_Vec3d (-1, 0, 0),
8894         Graphic3d_Vec3d ( 1, 0, 0),
8895         Graphic3d_Vec3d ( 0,-1, 0),
8896         Graphic3d_Vec3d ( 0, 1, 0),
8897         Graphic3d_Vec3d ( 0, 0,-1),
8898         Graphic3d_Vec3d ( 0, 0, 1),
8899       };
8900       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8901       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
8902       {
8903         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
8904         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
8905         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
8906         if (aSubPlaneIter + 1 == aNbSubPlanes)
8907         {
8908           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8909         }
8910         else
8911         {
8912           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8913         }
8914         aSubPln = aSubPln->ChainNextPlane();
8915       }
8916     }
8917     else if (aChangeArg == "-capping"
8918           || aChangeArg == "capping")
8919     {
8920       if (aNbChangeArgs < 2)
8921       {
8922         std::cout << "Syntax error: need more arguments.\n";
8923         return 1;
8924       }
8925
8926       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8927       {
8928         aClipPlane->SetCapping (toEnable);
8929         anArgIter += 1;
8930       }
8931       else
8932       {
8933         // just skip otherwise (old syntax)
8934       }
8935     }
8936     else if (aChangeArg == "-useobjectmaterial"
8937           || aChangeArg == "-useobjectmat"
8938           || aChangeArg == "-useobjmat"
8939           || aChangeArg == "-useobjmaterial")
8940     {
8941       if (aNbChangeArgs < 2)
8942       {
8943         std::cout << "Syntax error: need more arguments.\n";
8944         return 1;
8945       }
8946
8947       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8948       {
8949         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8950         anArgIter += 1;
8951       }
8952     }
8953     else if (aChangeArg == "-useobjecttexture"
8954           || aChangeArg == "-useobjecttex"
8955           || aChangeArg == "-useobjtexture"
8956           || aChangeArg == "-useobjtex")
8957     {
8958       if (aNbChangeArgs < 2)
8959       {
8960         std::cout << "Syntax error: need more arguments.\n";
8961         return 1;
8962       }
8963
8964       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8965       {
8966         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8967         anArgIter += 1;
8968       }
8969     }
8970     else if (aChangeArg == "-useobjectshader"
8971           || aChangeArg == "-useobjshader")
8972     {
8973       if (aNbChangeArgs < 2)
8974       {
8975         std::cout << "Syntax error: need more arguments.\n";
8976         return 1;
8977       }
8978
8979       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8980       {
8981         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8982         anArgIter += 1;
8983       }
8984     }
8985     else if (aChangeArg == "-color"
8986           || aChangeArg == "color")
8987     {
8988       Quantity_Color aColor;
8989       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8990                                                            aChangeArgs + 1,
8991                                                            aColor);
8992       if (aNbParsed == 0)
8993       {
8994         std::cout << "Syntax error: need more arguments.\n";
8995         return 1;
8996       }
8997
8998       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8999       aMat.SetAmbientColor (aColor);
9000       aMat.SetDiffuseColor (aColor);
9001       aClipPlane->SetCappingMaterial (aMat);
9002       anArgIter += aNbParsed;
9003     }
9004     else if ((aChangeArg == "-transparency"
9005            || aChangeArg == "-transp")
9006           && aNbChangeArgs >= 2)
9007     {
9008       TCollection_AsciiString aValStr (aChangeArgs[1]);
9009       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9010       if (aValStr.IsRealValue())
9011       {
9012         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9013         aMat.SetTransparency ((float )aValStr.RealValue());
9014         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9015         aClipPlane->SetCappingMaterial (aMat);
9016       }
9017       else
9018       {
9019         aValStr.LowerCase();
9020         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9021         if (aValStr == "opaque")
9022         {
9023           aMode = Graphic3d_AlphaMode_Opaque;
9024         }
9025         else if (aValStr == "mask")
9026         {
9027           aMode = Graphic3d_AlphaMode_Mask;
9028         }
9029         else if (aValStr == "blend")
9030         {
9031           aMode = Graphic3d_AlphaMode_Blend;
9032         }
9033         else if (aValStr == "blendauto")
9034         {
9035           aMode = Graphic3d_AlphaMode_BlendAuto;
9036         }
9037         else
9038         {
9039           std::cout << "Syntax error at '" << aValStr << "'\n";
9040           return 1;
9041         }
9042         anAspect->SetAlphaMode (aMode);
9043         aClipPlane->SetCappingAspect (anAspect);
9044       }
9045       anArgIter += 1;
9046     }
9047     else if (aChangeArg == "-texname"
9048           || aChangeArg == "texname")
9049     {
9050       if (aNbChangeArgs < 2)
9051       {
9052         std::cout << "Syntax error: need more arguments.\n";
9053         return 1;
9054       }
9055
9056       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9057       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9058       if (!aTexture->IsDone())
9059       {
9060         aClipPlane->SetCappingTexture (NULL);
9061       }
9062       else
9063       {
9064         aTexture->EnableModulate();
9065         aTexture->EnableRepeat();
9066         aClipPlane->SetCappingTexture (aTexture);
9067       }
9068       anArgIter += 1;
9069     }
9070     else if (aChangeArg == "-texscale"
9071           || aChangeArg == "texscale")
9072     {
9073       if (aClipPlane->CappingTexture().IsNull())
9074       {
9075         std::cout << "Error: no texture is set.\n";
9076         return 1;
9077       }
9078
9079       if (aNbChangeArgs < 3)
9080       {
9081         std::cout << "Syntax error: need more arguments.\n";
9082         return 1;
9083       }
9084
9085       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9086       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9087       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9088       anArgIter += 2;
9089     }
9090     else if (aChangeArg == "-texorigin"
9091           || aChangeArg == "texorigin") // texture origin
9092     {
9093       if (aClipPlane->CappingTexture().IsNull())
9094       {
9095         std::cout << "Error: no texture is set.\n";
9096         return 1;
9097       }
9098
9099       if (aNbChangeArgs < 3)
9100       {
9101         std::cout << "Syntax error: need more arguments.\n";
9102         return 1;
9103       }
9104
9105       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9106       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9107
9108       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9109       anArgIter += 2;
9110     }
9111     else if (aChangeArg == "-texrotate"
9112           || aChangeArg == "texrotate") // texture rotation
9113     {
9114       if (aClipPlane->CappingTexture().IsNull())
9115       {
9116         std::cout << "Error: no texture is set.\n";
9117         return 1;
9118       }
9119
9120       if (aNbChangeArgs < 2)
9121       {
9122         std::cout << "Syntax error: need more arguments.\n";
9123         return 1;
9124       }
9125
9126       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9127       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9128       anArgIter += 1;
9129     }
9130     else if (aChangeArg == "-hatch"
9131           || aChangeArg == "hatch")
9132     {
9133       if (aNbChangeArgs < 2)
9134       {
9135         std::cout << "Syntax error: need more arguments.\n";
9136         return 1;
9137       }
9138
9139       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9140       aHatchStr.LowerCase();
9141       if (aHatchStr == "on")
9142       {
9143         aClipPlane->SetCappingHatchOn();
9144       }
9145       else if (aHatchStr == "off")
9146       {
9147         aClipPlane->SetCappingHatchOff();
9148       }
9149       else
9150       {
9151         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9152       }
9153       anArgIter += 1;
9154     }
9155     else if (aChangeArg == "-delete"
9156           || aChangeArg == "delete")
9157     {
9158       removePlane (aRegPlanes, aPlaneName);
9159       return 0;
9160     }
9161     else if (aChangeArg == "-set"
9162           || aChangeArg == "-unset"
9163           || aChangeArg == "-setoverrideglobal")
9164     {
9165       // set / unset plane command
9166       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9167       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9168       Standard_Integer anIt = 1;
9169       for (; anIt < aNbChangeArgs; ++anIt)
9170       {
9171         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9172         if (anEntityName.IsEmpty()
9173          || anEntityName.Value (1) == '-')
9174         {
9175           break;
9176         }
9177         else if (!toOverrideGlobal
9178                && ViewerTest_myViews.IsBound1 (anEntityName))
9179         {
9180           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9181           if (toSet)
9182           {
9183             aView->AddClipPlane (aClipPlane);
9184           }
9185           else
9186           {
9187             aView->RemoveClipPlane (aClipPlane);
9188           }
9189           continue;
9190         }
9191         else if (GetMapOfAIS().IsBound2 (anEntityName))
9192         {
9193           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9194           if (toSet)
9195           {
9196             aIObj->AddClipPlane (aClipPlane);
9197           }
9198           else
9199           {
9200             aIObj->RemoveClipPlane (aClipPlane);
9201           }
9202           if (!aIObj->ClipPlanes().IsNull())
9203           {
9204             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9205           }
9206         }
9207         else
9208         {
9209           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9210           return 1;
9211         }
9212       }
9213
9214       if (anIt == 1)
9215       {
9216         // apply to active view
9217         if (toSet)
9218         {
9219           anActiveView->AddClipPlane (aClipPlane);
9220         }
9221         else
9222         {
9223           anActiveView->RemoveClipPlane (aClipPlane);
9224         }
9225       }
9226       else
9227       {
9228         anArgIter = anArgIter + anIt - 1;
9229       }
9230     }
9231     else
9232     {
9233       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9234       return 1;
9235     }
9236   }
9237
9238   ViewerTest::RedrawAllViews();
9239   return 0;
9240 }
9241
9242 //===============================================================================================
9243 //function : VZRange
9244 //purpose  :
9245 //===============================================================================================
9246 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9247 {
9248   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9249
9250   if (aCurrentView.IsNull())
9251   {
9252     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9253     return 1;
9254   }
9255
9256   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9257
9258   if (theArgsNb < 2)
9259   {
9260     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9261     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9262     return 0;
9263   }
9264
9265   if (theArgsNb == 3)
9266   {
9267     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9268     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9269
9270     if (aNewZNear >= aNewZFar)
9271     {
9272       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9273       return 1;
9274     }
9275
9276     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9277     {
9278       std::cout << theArgVec[0] << ": invalid arguments: ";
9279       std::cout << "znear, zfar should be positive for perspective camera.\n";
9280       return 1;
9281     }
9282
9283     aCamera->SetZRange (aNewZNear, aNewZFar);
9284   }
9285   else
9286   {
9287     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9288     return 1;
9289   }
9290
9291   aCurrentView->Redraw();
9292
9293   return 0;
9294 }
9295
9296 //===============================================================================================
9297 //function : VAutoZFit
9298 //purpose  :
9299 //===============================================================================================
9300 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9301 {
9302   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9303
9304   if (aCurrentView.IsNull())
9305   {
9306     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9307     return 1;
9308   }
9309
9310   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9311
9312   if (theArgsNb > 3)
9313   {
9314     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9315     return 1;
9316   }
9317
9318   if (theArgsNb < 2)
9319   {
9320     theDi << "Auto z-fit mode: \n"
9321           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9322           << "Scale: " << aScale << "\n";
9323     return 0;
9324   }
9325
9326   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9327
9328   if (theArgsNb >= 3)
9329   {
9330     aScale = Draw::Atoi (theArgVec[2]);
9331   }
9332
9333   aCurrentView->SetAutoZFitMode (isOn, aScale);
9334   aCurrentView->AutoZFit();
9335   aCurrentView->Redraw();
9336
9337   return 0;
9338 }
9339
9340 //! Auxiliary function to print projection type
9341 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9342 {
9343   switch (theProjType)
9344   {
9345     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9346     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9347     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9348     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9349     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9350   }
9351   return "UNKNOWN";
9352 }
9353
9354 //===============================================================================================
9355 //function : VCamera
9356 //purpose  :
9357 //===============================================================================================
9358 static int VCamera (Draw_Interpretor& theDI,
9359                     Standard_Integer  theArgsNb,
9360                     const char**      theArgVec)
9361 {
9362   Handle(V3d_View) aView = ViewerTest::CurrentView();
9363   if (aView.IsNull())
9364   {
9365     std::cout << "Error: no active view.\n";
9366     return 1;
9367   }
9368
9369   Handle(Graphic3d_Camera) aCamera = aView->Camera();
9370   if (theArgsNb < 2)
9371   {
9372     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
9373     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
9374     theDI << "Distance:   " << aCamera->Distance() << "\n";
9375     theDI << "IOD:        " << aCamera->IOD() << "\n";
9376     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
9377     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
9378     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
9379     return 0;
9380   }
9381
9382   TCollection_AsciiString aPrsName;
9383   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9384   {
9385     Standard_CString        anArg = theArgVec[anArgIter];
9386     TCollection_AsciiString anArgCase (anArg);
9387     anArgCase.LowerCase();
9388     if (anArgCase == "-proj"
9389      || anArgCase == "-projection"
9390      || anArgCase == "-projtype"
9391      || anArgCase == "-projectiontype")
9392     {
9393       theDI << projTypeName (aCamera->ProjectionType()) << " ";
9394     }
9395     else if (anArgCase == "-ortho"
9396           || anArgCase == "-orthographic")
9397     {
9398       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
9399     }
9400     else if (anArgCase == "-persp"
9401           || anArgCase == "-perspective"
9402           || anArgCase == "-perspmono"
9403           || anArgCase == "-perspectivemono"
9404           || anArgCase == "-mono")
9405     {
9406       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9407     }
9408     else if (anArgCase == "-stereo"
9409           || anArgCase == "-stereoscopic"
9410           || anArgCase == "-perspstereo"
9411           || anArgCase == "-perspectivestereo")
9412     {
9413       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9414     }
9415     else if (anArgCase == "-left"
9416           || anArgCase == "-lefteye"
9417           || anArgCase == "-monoleft"
9418           || anArgCase == "-monolefteye"
9419           || anArgCase == "-perpsleft"
9420           || anArgCase == "-perpslefteye")
9421     {
9422       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
9423     }
9424     else if (anArgCase == "-right"
9425           || anArgCase == "-righteye"
9426           || anArgCase == "-monoright"
9427           || anArgCase == "-monorighteye"
9428           || anArgCase == "-perpsright")
9429     {
9430       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
9431     }
9432     else if (anArgCase == "-dist"
9433           || anArgCase == "-distance")
9434     {
9435       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9436       if (anArgValue != NULL
9437       && *anArgValue != '-')
9438       {
9439         ++anArgIter;
9440         aCamera->SetDistance (Draw::Atof (anArgValue));
9441         continue;
9442       }
9443       theDI << aCamera->Distance() << " ";
9444     }
9445     else if (anArgCase == "-iod")
9446     {
9447       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9448       if (anArgValue != NULL
9449       && *anArgValue != '-')
9450       {
9451         ++anArgIter;
9452         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
9453         continue;
9454       }
9455       theDI << aCamera->IOD() << " ";
9456     }
9457     else if (anArgCase == "-iodtype")
9458     {
9459       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9460       TCollection_AsciiString anValueCase (anArgValue);
9461       anValueCase.LowerCase();
9462       if (anValueCase == "abs"
9463        || anValueCase == "absolute")
9464       {
9465         ++anArgIter;
9466         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
9467         continue;
9468       }
9469       else if (anValueCase == "rel"
9470             || anValueCase == "relative")
9471       {
9472         ++anArgIter;
9473         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
9474         continue;
9475       }
9476       else if (*anArgValue != '-')
9477       {
9478         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
9479         return 1;
9480       }
9481       switch (aCamera->GetIODType())
9482       {
9483         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
9484         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
9485       }
9486     }
9487     else if (anArgCase == "-zfocus")
9488     {
9489       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9490       if (anArgValue != NULL
9491       && *anArgValue != '-')
9492       {
9493         ++anArgIter;
9494         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
9495         continue;
9496       }
9497       theDI << aCamera->ZFocus() << " ";
9498     }
9499     else if (anArgCase == "-zfocustype")
9500     {
9501       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9502       TCollection_AsciiString anValueCase (anArgValue);
9503       anValueCase.LowerCase();
9504       if (anValueCase == "abs"
9505        || anValueCase == "absolute")
9506       {
9507         ++anArgIter;
9508         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
9509         continue;
9510       }
9511       else if (anValueCase == "rel"
9512             || anValueCase == "relative")
9513       {
9514         ++anArgIter;
9515         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
9516         continue;
9517       }
9518       else if (*anArgValue != '-')
9519       {
9520         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
9521         return 1;
9522       }
9523       switch (aCamera->ZFocusType())
9524       {
9525         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
9526         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
9527       }
9528     }
9529     else if (anArgCase == "-fov"
9530           || anArgCase == "-fovy")
9531     {
9532       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9533       if (anArgValue != NULL
9534       && *anArgValue != '-')
9535       {
9536         ++anArgIter;
9537         aCamera->SetFOVy (Draw::Atof (anArgValue));
9538         continue;
9539       }
9540       theDI << aCamera->FOVy() << " ";
9541     }
9542     else if (aPrsName.IsEmpty()
9543          && !anArgCase.StartsWith ("-"))
9544     {
9545       aPrsName = anArg;
9546     }
9547     else
9548     {
9549       std::cout << "Error: unknown argument '" << anArg << "'\n";
9550       return 1;
9551     }
9552   }
9553
9554   if (aPrsName.IsEmpty()
9555    || theArgsNb > 2)
9556   {
9557     aView->AutoZFit();
9558     aView->Redraw();
9559   }
9560
9561   if (!aPrsName.IsEmpty())
9562   {
9563     Handle(AIS_CameraFrustum) aCameraFrustum;
9564     if (GetMapOfAIS().IsBound2 (aPrsName))
9565     {
9566       // find existing object
9567       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
9568       if (aCameraFrustum.IsNull())
9569       {
9570         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
9571         return 1;
9572       }
9573     }
9574
9575     if (aCameraFrustum.IsNull())
9576     {
9577       aCameraFrustum = new AIS_CameraFrustum();
9578     }
9579     else
9580     {
9581       // not include displayed object of old camera frustum in the new one.
9582       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
9583       aView->ZFitAll();
9584     }
9585     aCameraFrustum->SetCameraFrustum (aView->Camera());
9586
9587     ViewerTest::Display (aPrsName, aCameraFrustum);
9588   }
9589
9590   return 0;
9591 }
9592
9593 //! Parse stereo output mode
9594 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
9595                                          Graphic3d_StereoMode& theMode)
9596 {
9597   TCollection_AsciiString aFlag (theArg);
9598   aFlag.LowerCase();
9599   if (aFlag == "quadbuffer")
9600   {
9601     theMode = Graphic3d_StereoMode_QuadBuffer;
9602   }
9603   else if (aFlag == "anaglyph")
9604   {
9605     theMode = Graphic3d_StereoMode_Anaglyph;
9606   }
9607   else if (aFlag == "row"
9608         || aFlag == "rowinterlaced")
9609   {
9610     theMode = Graphic3d_StereoMode_RowInterlaced;
9611   }
9612   else if (aFlag == "col"
9613         || aFlag == "colinterlaced"
9614         || aFlag == "columninterlaced")
9615   {
9616     theMode = Graphic3d_StereoMode_ColumnInterlaced;
9617   }
9618   else if (aFlag == "chess"
9619         || aFlag == "chessboard")
9620   {
9621     theMode = Graphic3d_StereoMode_ChessBoard;
9622   }
9623   else if (aFlag == "sbs"
9624         || aFlag == "sidebyside")
9625   {
9626     theMode = Graphic3d_StereoMode_SideBySide;
9627   }
9628   else if (aFlag == "ou"
9629         || aFlag == "overunder")
9630   {
9631     theMode = Graphic3d_StereoMode_OverUnder;
9632   }
9633   else if (aFlag == "pageflip"
9634         || aFlag == "softpageflip")
9635   {
9636     theMode = Graphic3d_StereoMode_SoftPageFlip;
9637   }
9638   else
9639   {
9640     return Standard_False;
9641   }
9642   return Standard_True;
9643 }
9644
9645 //! Parse anaglyph filter
9646 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
9647                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
9648 {
9649   TCollection_AsciiString aFlag (theArg);
9650   aFlag.LowerCase();
9651   if (aFlag == "redcyansimple")
9652   {
9653     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9654   }
9655   else if (aFlag == "redcyan"
9656         || aFlag == "redcyanoptimized")
9657   {
9658     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
9659   }
9660   else if (aFlag == "yellowbluesimple")
9661   {
9662     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
9663   }
9664   else if (aFlag == "yellowblue"
9665         || aFlag == "yellowblueoptimized")
9666   {
9667     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
9668   }
9669   else if (aFlag == "greenmagenta"
9670         || aFlag == "greenmagentasimple")
9671   {
9672     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
9673   }
9674   else
9675   {
9676     return Standard_False;
9677   }
9678   return Standard_True;
9679 }
9680
9681 //==============================================================================
9682 //function : VStereo
9683 //purpose  :
9684 //==============================================================================
9685
9686 static int VStereo (Draw_Interpretor& theDI,
9687                     Standard_Integer  theArgNb,
9688                     const char**      theArgVec)
9689 {
9690   Handle(V3d_View) aView = ViewerTest::CurrentView();
9691   if (theArgNb < 2)
9692   {
9693     if (aView.IsNull())
9694     {
9695       std::cout << "Error: no active viewer!\n";
9696       return 0;
9697     }
9698
9699     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
9700     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
9701     if (isActive)
9702     {
9703       TCollection_AsciiString aMode;
9704       switch (aView->RenderingParams().StereoMode)
9705       {
9706         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
9707         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
9708         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
9709         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
9710         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
9711         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
9712         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
9713         case Graphic3d_StereoMode_Anaglyph  :
9714           aMode = "anaglyph";
9715           switch (aView->RenderingParams().AnaglyphFilter)
9716           {
9717             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
9718             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
9719             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
9720             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
9721             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
9722             default: break;
9723           }
9724         default: break;
9725       }
9726       theDI << "Mode " << aMode << "\n";
9727     }
9728     return 0;
9729   }
9730
9731   Handle(Graphic3d_Camera) aCamera;
9732   Graphic3d_RenderingParams*   aParams   = NULL;
9733   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
9734   if (!aView.IsNull())
9735   {
9736     aParams   = &aView->ChangeRenderingParams();
9737     aMode     = aParams->StereoMode;
9738     aCamera   = aView->Camera();
9739   }
9740
9741   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9742   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9743   {
9744     Standard_CString        anArg = theArgVec[anArgIter];
9745     TCollection_AsciiString aFlag (anArg);
9746     aFlag.LowerCase();
9747     if (anUpdateTool.parseRedrawMode (aFlag))
9748     {
9749       continue;
9750     }
9751     else if (aFlag == "0"
9752           || aFlag == "off")
9753     {
9754       if (++anArgIter < theArgNb)
9755       {
9756         std::cout << "Error: wrong number of arguments!\n";
9757         return 1;
9758       }
9759
9760       if (!aCamera.IsNull()
9761        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
9762       {
9763         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9764       }
9765       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
9766       return 0;
9767     }
9768     else if (aFlag == "1"
9769           || aFlag == "on")
9770     {
9771       if (++anArgIter < theArgNb)
9772       {
9773         std::cout << "Error: wrong number of arguments!\n";
9774         return 1;
9775       }
9776
9777       if (!aCamera.IsNull())
9778       {
9779         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9780       }
9781       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9782       return 0;
9783     }
9784     else if (aFlag == "-reverse"
9785           || aFlag == "-reversed"
9786           || aFlag == "-swap")
9787     {
9788       Standard_Boolean toEnable = Standard_True;
9789       if (++anArgIter < theArgNb
9790       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9791       {
9792         --anArgIter;
9793       }
9794       aParams->ToReverseStereo = toEnable;
9795     }
9796     else if (aFlag == "-noreverse"
9797           || aFlag == "-noswap")
9798     {
9799       Standard_Boolean toDisable = Standard_True;
9800       if (++anArgIter < theArgNb
9801       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9802       {
9803         --anArgIter;
9804       }
9805       aParams->ToReverseStereo = !toDisable;
9806     }
9807     else if (aFlag == "-mode"
9808           || aFlag == "-stereomode")
9809     {
9810       if (++anArgIter >= theArgNb
9811       || !parseStereoMode (theArgVec[anArgIter], aMode))
9812       {
9813         std::cout << "Error: syntax error at '" << anArg << "'\n";
9814         return 1;
9815       }
9816
9817       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9818       {
9819         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9820       }
9821     }
9822     else if (aFlag == "-anaglyph"
9823           || aFlag == "-anaglyphfilter")
9824     {
9825       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9826       if (++anArgIter >= theArgNb
9827       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9828       {
9829         std::cout << "Error: syntax error at '" << anArg << "'\n";
9830         return 1;
9831       }
9832
9833       aMode = Graphic3d_StereoMode_Anaglyph;
9834       aParams->AnaglyphFilter = aFilter;
9835     }
9836     else if (parseStereoMode (anArg, aMode)) // short syntax
9837     {
9838       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9839       {
9840         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9841       }
9842     }
9843     else
9844     {
9845       std::cout << "Error: syntax error at '" << anArg << "'\n";
9846       return 1;
9847     }
9848   }
9849
9850   if (!aView.IsNull())
9851   {
9852     aParams->StereoMode = aMode;
9853     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9854   }
9855   return 0;
9856 }
9857
9858 //===============================================================================================
9859 //function : VDefaults
9860 //purpose  :
9861 //===============================================================================================
9862 static int VDefaults (Draw_Interpretor& theDi,
9863                       Standard_Integer  theArgsNb,
9864                       const char**      theArgVec)
9865 {
9866   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9867   if (aCtx.IsNull())
9868   {
9869     std::cerr << "No active viewer!\n";
9870     return 1;
9871   }
9872
9873   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9874   if (theArgsNb < 2)
9875   {
9876     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9877     {
9878       theDi << "DeflType:           relative\n"
9879             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9880     }
9881     else
9882     {
9883       theDi << "DeflType:           absolute\n"
9884             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9885     }
9886     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9887     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9888     return 0;
9889   }
9890
9891   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9892   {
9893     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9894     anArg.UpperCase();
9895     if (anArg == "-ABSDEFL"
9896      || anArg == "-ABSOLUTEDEFLECTION"
9897      || anArg == "-DEFL"
9898      || anArg == "-DEFLECTION")
9899     {
9900       if (++anArgIter >= theArgsNb)
9901       {
9902         std::cout << "Error: wrong syntax at " << anArg << "\n";
9903         return 1;
9904       }
9905       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9906       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9907     }
9908     else if (anArg == "-RELDEFL"
9909           || anArg == "-RELATIVEDEFLECTION"
9910           || anArg == "-DEVCOEFF"
9911           || anArg == "-DEVIATIONCOEFF"
9912           || anArg == "-DEVIATIONCOEFFICIENT")
9913     {
9914       if (++anArgIter >= theArgsNb)
9915       {
9916         std::cout << "Error: wrong syntax at " << anArg << "\n";
9917         return 1;
9918       }
9919       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9920       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9921     }
9922     else if (anArg == "-ANGDEFL"
9923           || anArg == "-ANGULARDEFL"
9924           || anArg == "-ANGULARDEFLECTION")
9925     {
9926       if (++anArgIter >= theArgsNb)
9927       {
9928         std::cout << "Error: wrong syntax at " << anArg << "\n";
9929         return 1;
9930       }
9931       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9932       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9933     }
9934     else if (anArg == "-AUTOTR"
9935           || anArg == "-AUTOTRIANG"
9936           || anArg == "-AUTOTRIANGULATION")
9937     {
9938       if (++anArgIter >= theArgsNb)
9939       {
9940         std::cout << "Error: wrong syntax at " << anArg << "\n";
9941         return 1;
9942       }
9943       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9944       aValue.LowerCase();
9945       if (aValue == "on"
9946        || aValue == "1")
9947       {
9948         aDefParams->SetAutoTriangulation (Standard_True);
9949       }
9950       else if (aValue == "off"
9951             || aValue == "0")
9952       {
9953         aDefParams->SetAutoTriangulation (Standard_False);
9954       }
9955     }
9956     else
9957     {
9958       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9959     }
9960   }
9961
9962   return 0;
9963 }
9964
9965 //! Auxiliary method
9966 inline void addLight (const Handle(V3d_Light)& theLightNew,
9967                       const Graphic3d_ZLayerId theLayer,
9968                       const Standard_Boolean   theIsGlobal)
9969 {
9970   if (theLightNew.IsNull())
9971   {
9972     return;
9973   }
9974
9975   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9976   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
9977   {
9978     aViewer->AddLight (theLightNew);
9979     if (theIsGlobal)
9980     {
9981       aViewer->SetLightOn (theLightNew);
9982     }
9983     else
9984     {
9985       ViewerTest::CurrentView()->SetLightOn (theLightNew);
9986     }
9987   }
9988   else
9989   {
9990     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
9991     if (aSettings.Lights().IsNull())
9992     {
9993       aSettings.SetLights (new Graphic3d_LightSet());
9994     }
9995     aSettings.Lights()->Add (theLightNew);
9996     aViewer->SetZLayerSettings (theLayer, aSettings);
9997   }
9998 }
9999
10000 //! Auxiliary method
10001 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10002 {
10003   TCollection_AsciiString anArgNextCase (theArgNext);
10004   anArgNextCase.UpperCase();
10005   if (anArgNextCase.Length() > 5
10006    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10007   {
10008     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10009   }
10010   else
10011   {
10012     return theArgNext.IntegerValue();
10013   }
10014 }
10015
10016 //===============================================================================================
10017 //function : VLight
10018 //purpose  :
10019 //===============================================================================================
10020 static int VLight (Draw_Interpretor& theDi,
10021                    Standard_Integer  theArgsNb,
10022                    const char**      theArgVec)
10023 {
10024   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10025   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10026   if (aView.IsNull()
10027    || aViewer.IsNull())
10028   {
10029     std::cerr << "No active viewer!\n";
10030     return 1;
10031   }
10032
10033   Standard_Real anXYZ[3]   = {};
10034   Standard_Real anAtten[2] = {};
10035   if (theArgsNb < 2)
10036   {
10037     // print lights info
10038     Standard_Integer aLightId = 0;
10039     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10040     {
10041       Handle(V3d_Light) aLight = aLightIter.Value();
10042       const Quantity_Color aColor = aLight->Color();
10043       theDi << "Light #" << aLightId
10044             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10045             << " [" << aLight->GetId() << "]" << "\n";
10046       switch (aLight->Type())
10047       {
10048         case V3d_AMBIENT:
10049         {
10050           theDi << "  Type:       Ambient\n";
10051           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10052           break;
10053         }
10054         case V3d_DIRECTIONAL:
10055         {
10056           theDi << "  Type:       Directional\n";
10057           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10058           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10059           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10060           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10061           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10062           break;
10063         }
10064         case V3d_POSITIONAL:
10065         {
10066           theDi << "  Type:       Positional\n";
10067           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10068           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10069           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10070           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10071           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10072           aLight->Attenuation (anAtten[0], anAtten[1]);
10073           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10074           break;
10075         }
10076         case V3d_SPOT:
10077         {
10078           theDi << "  Type:       Spot\n";
10079           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10080           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10081           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10082           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10083           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10084           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10085           aLight->Attenuation (anAtten[0], anAtten[1]);
10086           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10087           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
10088           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
10089           break;
10090         }
10091         default:
10092         {
10093           theDi << "  Type:       UNKNOWN\n";
10094           break;
10095         }
10096       }
10097       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10098     }
10099   }
10100
10101   Handle(V3d_Light) aLightNew;
10102   Handle(V3d_Light) aLightOld;
10103   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10104   Standard_Boolean  isGlobal = Standard_True;
10105   Standard_Boolean  toCreate = Standard_False;
10106   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10107   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10108   {
10109     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10110
10111     TCollection_AsciiString aName, aValue;
10112     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10113     TCollection_AsciiString anArgCase (anArg);
10114     anArgCase.UpperCase();
10115     if (anUpdateTool.parseRedrawMode (anArg))
10116     {
10117       continue;
10118     }
10119
10120     if (anArgCase.IsEqual ("NEW")
10121      || anArgCase.IsEqual ("ADD")
10122      || anArgCase.IsEqual ("CREATE")
10123      || anArgCase.IsEqual ("-NEW")
10124      || anArgCase.IsEqual ("-ADD")
10125      || anArgCase.IsEqual ("-CREATE"))
10126     {
10127       toCreate = Standard_True;
10128     }
10129     else if (anArgCase.IsEqual ("-LAYER")
10130           || anArgCase.IsEqual ("-ZLAYER"))
10131     {
10132       if (++anArgIt >= theArgsNb)
10133       {
10134         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10135         return 1;
10136       }
10137
10138       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10139       aValStr.LowerCase();
10140       if (aValStr == "default"
10141        || aValStr == "def")
10142       {
10143         aLayer = Graphic3d_ZLayerId_Default;
10144       }
10145       else if (aValStr == "top")
10146       {
10147         aLayer = Graphic3d_ZLayerId_Top;
10148       }
10149       else if (aValStr == "topmost")
10150       {
10151         aLayer = Graphic3d_ZLayerId_Topmost;
10152       }
10153       else if (aValStr == "toposd"
10154             || aValStr == "osd")
10155       {
10156         aLayer = Graphic3d_ZLayerId_TopOSD;
10157       }
10158       else if (aValStr == "botosd"
10159             || aValStr == "bottom")
10160       {
10161         aLayer = Graphic3d_ZLayerId_BotOSD;
10162       }
10163       else if (aValStr.IsIntegerValue())
10164       {
10165         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10166       }
10167       else
10168       {
10169         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10170         return 1;
10171       }
10172     }
10173     else if (anArgCase.IsEqual ("GLOB")
10174           || anArgCase.IsEqual ("GLOBAL")
10175           || anArgCase.IsEqual ("-GLOB")
10176           || anArgCase.IsEqual ("-GLOBAL"))
10177     {
10178       isGlobal = Standard_True;
10179     }
10180     else if (anArgCase.IsEqual ("LOC")
10181           || anArgCase.IsEqual ("LOCAL")
10182           || anArgCase.IsEqual ("-LOC")
10183           || anArgCase.IsEqual ("-LOCAL"))
10184     {
10185       isGlobal = Standard_False;
10186     }
10187     else if (anArgCase.IsEqual ("DEF")
10188           || anArgCase.IsEqual ("DEFAULTS")
10189           || anArgCase.IsEqual ("-DEF")
10190           || anArgCase.IsEqual ("-DEFAULTS"))
10191     {
10192       toCreate = Standard_False;
10193       aViewer->SetDefaultLights();
10194     }
10195     else if (anArgCase.IsEqual ("CLR")
10196           || anArgCase.IsEqual ("CLEAR")
10197           || anArgCase.IsEqual ("-CLR")
10198           || anArgCase.IsEqual ("-CLEAR"))
10199     {
10200       toCreate = Standard_False;
10201
10202       TColStd_SequenceOfInteger aLayers;
10203       aViewer->GetAllZLayers (aLayers);
10204       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10205       {
10206         if (aLayeriter.Value() == aLayer
10207          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10208         {
10209           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10210           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10211           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10212           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10213           {
10214             break;
10215           }
10216         }
10217       }
10218
10219       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10220       {
10221         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10222         {
10223           Handle(V3d_Light) aLight = aLightIter.Value();
10224           aViewer->DelLight (aLight);
10225           aLightIter = aView->ActiveLightIterator();
10226         }
10227       }
10228     }
10229     else if (anArgCase.IsEqual ("AMB")
10230           || anArgCase.IsEqual ("AMBIENT")
10231           || anArgCase.IsEqual ("AMBLIGHT"))
10232     {
10233       if (!toCreate)
10234       {
10235         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10236         return 1;
10237       }
10238
10239       addLight (aLightNew, aLayer, isGlobal);
10240       toCreate  = Standard_False;
10241       aLightNew = new V3d_AmbientLight();
10242     }
10243     else if (anArgCase.IsEqual ("DIRECTIONAL")
10244           || anArgCase.IsEqual ("DIRLIGHT"))
10245     {
10246       if (!toCreate)
10247       {
10248         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10249         return 1;
10250       }
10251
10252       addLight (aLightNew, aLayer, isGlobal);
10253       toCreate  = Standard_False;
10254       aLightNew = new V3d_DirectionalLight();
10255     }
10256     else if (anArgCase.IsEqual ("SPOT")
10257           || anArgCase.IsEqual ("SPOTLIGHT"))
10258     {
10259       if (!toCreate)
10260       {
10261         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10262         return 1;
10263       }
10264
10265       addLight (aLightNew, aLayer, isGlobal);
10266       toCreate  = Standard_False;
10267       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10268     }
10269     else if (anArgCase.IsEqual ("POSLIGHT")
10270           || anArgCase.IsEqual ("POSITIONAL"))
10271     {
10272       if (!toCreate)
10273       {
10274         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10275         return 1;
10276       }
10277
10278       addLight (aLightNew, aLayer, isGlobal);
10279       toCreate  = Standard_False;
10280       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10281     }
10282     else if (anArgCase.IsEqual ("CHANGE")
10283           || anArgCase.IsEqual ("-CHANGE"))
10284     {
10285       if (++anArgIt >= theArgsNb)
10286       {
10287         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10288         return 1;
10289       }
10290
10291       addLight (aLightNew, aLayer, isGlobal);
10292       aLightNew.Nullify();
10293       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10294       Standard_Integer aLightIt = 0;
10295       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10296       {
10297         if (aLightIt == aLightId)
10298         {
10299           aLightOld = aLightIter.Value();
10300           break;
10301         }
10302       }
10303
10304       if (aLightOld.IsNull())
10305       {
10306         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10307         return 1;
10308       }
10309     }
10310     else if (anArgCase.IsEqual ("DEL")
10311           || anArgCase.IsEqual ("DELETE")
10312           || anArgCase.IsEqual ("-DEL")
10313           || anArgCase.IsEqual ("-DELETE"))
10314     {
10315       Handle(V3d_Light) aLightDel;
10316       if (++anArgIt >= theArgsNb)
10317       {
10318         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10319         return 1;
10320       }
10321
10322       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10323       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10324       Standard_Integer aLightIt = 0;
10325       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10326       {
10327         aLightDel = aLightIter.Value();
10328         if (aLightIt == aLightDelId)
10329         {
10330           break;
10331         }
10332       }
10333       if (aLightDel.IsNull())
10334       {
10335         continue;
10336       }
10337
10338       TColStd_SequenceOfInteger aLayers;
10339       aViewer->GetAllZLayers (aLayers);
10340       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10341       {
10342         if (aLayeriter.Value() == aLayer
10343          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10344         {
10345           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10346           if (!aSettings.Lights().IsNull())
10347           {
10348             aSettings.Lights()->Remove (aLightDel);
10349             if (aSettings.Lights()->IsEmpty())
10350             {
10351               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10352             }
10353           }
10354           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10355           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10356           {
10357             break;
10358           }
10359         }
10360       }
10361
10362       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10363       {
10364         aViewer->DelLight (aLightDel);
10365       }
10366     }
10367     else if (anArgCase.IsEqual ("COLOR")
10368           || anArgCase.IsEqual ("COLOUR")
10369           || anArgCase.IsEqual ("-COLOR")
10370           || anArgCase.IsEqual ("-COLOUR"))
10371     {
10372       if (++anArgIt >= theArgsNb
10373        || aLightCurr.IsNull())
10374       {
10375         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10376         return 1;
10377       }
10378
10379       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10380       anArgNext.UpperCase();
10381       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
10382       aLightCurr->SetColor (aColor);
10383     }
10384     else if (anArgCase.IsEqual ("POS")
10385           || anArgCase.IsEqual ("POSITION")
10386           || anArgCase.IsEqual ("-POS")
10387           || anArgCase.IsEqual ("-POSITION"))
10388     {
10389       if ((anArgIt + 3) >= theArgsNb
10390        || aLightCurr.IsNull()
10391        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10392         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10393       {
10394         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10395         return 1;
10396       }
10397
10398       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10399       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10400       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10401       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
10402     }
10403     else if (anArgCase.IsEqual ("DIR")
10404           || anArgCase.IsEqual ("DIRECTION")
10405           || anArgCase.IsEqual ("-DIR")
10406           || anArgCase.IsEqual ("-DIRECTION"))
10407     {
10408       if ((anArgIt + 3) >= theArgsNb
10409        || aLightCurr.IsNull()
10410        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
10411         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10412       {
10413         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10414         return 1;
10415       }
10416
10417       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10418       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10419       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10420       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
10421     }
10422     else if (anArgCase.IsEqual ("SM")
10423           || anArgCase.IsEqual ("SMOOTHNESS")
10424           || anArgCase.IsEqual ("-SM")
10425           || anArgCase.IsEqual ("-SMOOTHNESS"))
10426     {
10427       if (++anArgIt >= theArgsNb
10428        || aLightCurr.IsNull())
10429       {
10430         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10431         return 1;
10432       }
10433
10434       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10435       if (Abs (aSmoothness) <= ShortRealEpsilon())
10436       {
10437         aLightCurr->SetIntensity (1.f);
10438       }
10439       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
10440       {
10441         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
10442       }
10443       else
10444       {
10445         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
10446         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
10447       }
10448
10449       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
10450       {
10451         aLightCurr->SetSmoothRadius (aSmoothness);
10452       }
10453       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
10454       {
10455         aLightCurr->SetSmoothAngle (aSmoothness);
10456       }
10457     }
10458     else if (anArgCase.IsEqual ("INT")
10459           || anArgCase.IsEqual ("INTENSITY")
10460           || anArgCase.IsEqual ("-INT")
10461           || anArgCase.IsEqual ("-INTENSITY"))
10462     {
10463       if (++anArgIt >= theArgsNb
10464        || aLightCurr.IsNull())
10465       {
10466         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10467         return 1;
10468       }
10469
10470       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10471       aLightCurr->SetIntensity (aIntensity);
10472     }
10473     else if (anArgCase.IsEqual ("ANG")
10474           || anArgCase.IsEqual ("ANGLE")
10475           || anArgCase.IsEqual ("-ANG")
10476           || anArgCase.IsEqual ("-ANGLE"))
10477     {
10478       if (++anArgIt >= theArgsNb
10479        || aLightCurr.IsNull()
10480        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10481       {
10482         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10483         return 1;
10484       }
10485
10486       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10487       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
10488     }
10489     else if (anArgCase.IsEqual ("CONSTATTEN")
10490           || anArgCase.IsEqual ("CONSTATTENUATION")
10491           || anArgCase.IsEqual ("-CONSTATTEN")
10492           || anArgCase.IsEqual ("-CONSTATTENUATION"))
10493     {
10494       if (++anArgIt >= theArgsNb
10495        || aLightCurr.IsNull()
10496        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10497         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10498       {
10499         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10500         return 1;
10501       }
10502
10503       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10504       anAtten[0] = Atof (theArgVec[anArgIt]);
10505       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10506     }
10507     else if (anArgCase.IsEqual ("LINATTEN")
10508           || anArgCase.IsEqual ("LINEARATTEN")
10509           || anArgCase.IsEqual ("LINEARATTENUATION")
10510           || anArgCase.IsEqual ("-LINATTEN")
10511           || anArgCase.IsEqual ("-LINEARATTEN")
10512           || anArgCase.IsEqual ("-LINEARATTENUATION"))
10513     {
10514       if (++anArgIt >= theArgsNb
10515        || aLightCurr.IsNull()
10516        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10517         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10518       {
10519         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10520         return 1;
10521       }
10522
10523       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10524       anAtten[1] = Atof (theArgVec[anArgIt]);
10525       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10526     }
10527     else if (anArgCase.IsEqual ("EXP")
10528           || anArgCase.IsEqual ("EXPONENT")
10529           || anArgCase.IsEqual ("SPOTEXP")
10530           || anArgCase.IsEqual ("SPOTEXPONENT")
10531           || anArgCase.IsEqual ("-EXP")
10532           || anArgCase.IsEqual ("-EXPONENT")
10533           || anArgCase.IsEqual ("-SPOTEXP")
10534           || anArgCase.IsEqual ("-SPOTEXPONENT"))
10535     {
10536       if (++anArgIt >= theArgsNb
10537        || aLightCurr.IsNull()
10538        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10539       {
10540         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10541         return 1;
10542       }
10543
10544       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
10545     }
10546     else if (anArgCase.IsEqual ("HEAD")
10547           || anArgCase.IsEqual ("HEADLIGHT")
10548           || anArgCase.IsEqual ("-HEAD")
10549           || anArgCase.IsEqual ("-HEADLIGHT"))
10550     {
10551       if (aLightCurr.IsNull()
10552        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
10553       {
10554         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10555         return 1;
10556       }
10557
10558       Standard_Boolean isHeadLight = Standard_True;
10559       if (anArgIt + 1 < theArgsNb
10560        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
10561       {
10562         ++anArgIt;
10563       }
10564       aLightCurr->SetHeadlight (isHeadLight);
10565     }
10566     else
10567     {
10568       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
10569     }
10570   }
10571
10572   addLight (aLightNew, aLayer, isGlobal);
10573   return 0;
10574 }
10575
10576 //! Read Graphic3d_RenderingParams::PerfCounters flag.
10577 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10578                                             Standard_Boolean& theToReset,
10579                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10580                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10581 {
10582   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10583   TCollection_AsciiString aVal = theValue;
10584   Standard_Boolean toReverse = Standard_False;
10585   if (aVal == "none")
10586   {
10587     theToReset = Standard_True;
10588     return Standard_True;
10589   }
10590   else if (aVal.StartsWith ("-"))
10591   {
10592     toReverse = Standard_True;
10593     aVal = aVal.SubString (2, aVal.Length());
10594   }
10595   else if (aVal.StartsWith ("no"))
10596   {
10597     toReverse = Standard_True;
10598     aVal = aVal.SubString (3, aVal.Length());
10599   }
10600   else if (aVal.StartsWith ("+"))
10601   {
10602     aVal = aVal.SubString (2, aVal.Length());
10603   }
10604   else
10605   {
10606     theToReset = Standard_True;
10607   }
10608
10609   if (     aVal == "fps"
10610         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
10611   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
10612   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
10613   else if (aVal == "structs"
10614         || aVal == "structures"
10615         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
10616   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
10617   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
10618   else if (aVal == "tris"
10619         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
10620   else if (aVal == "pnts"
10621         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
10622   else if (aVal == "mem"
10623         || aVal == "gpumem"
10624         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
10625   else if (aVal == "skipimmediate"
10626         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
10627   else if (aVal == "frametime"
10628         || aVal == "frametimers"
10629         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
10630   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
10631   else if (aVal == "extended"
10632         || aVal == "verbose"
10633         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
10634   else if (aVal == "full"
10635         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
10636   else
10637   {
10638     return Standard_False;
10639   }
10640
10641   if (toReverse)
10642   {
10643     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
10644   }
10645   else
10646   {
10647     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
10648   }
10649   return Standard_True;
10650 }
10651
10652 //! Read Graphic3d_RenderingParams::PerfCounters flags.
10653 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
10654                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
10655 {
10656   TCollection_AsciiString aValue = theValue;
10657   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
10658   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
10659   Standard_Boolean toReset = Standard_False;
10660   for (;;)
10661   {
10662     Standard_Integer aSplitPos = aValue.Search ("|");
10663     if (aSplitPos <= 0)
10664     {
10665       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
10666       {
10667         return Standard_False;
10668       }
10669       if (toReset)
10670       {
10671         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
10672       }
10673       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
10674       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
10675       return Standard_True;
10676     }
10677
10678     if (aSplitPos > 1)
10679     {
10680       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
10681       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
10682       {
10683         return Standard_False;
10684       }
10685     }
10686     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
10687   }
10688 }
10689
10690 //=======================================================================
10691 //function : VRenderParams
10692 //purpose  : Enables/disables rendering features
10693 //=======================================================================
10694
10695 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
10696                                        Standard_Integer  theArgNb,
10697                                        const char**      theArgVec)
10698 {
10699   Handle(V3d_View) aView = ViewerTest::CurrentView();
10700   if (aView.IsNull())
10701   {
10702     std::cerr << "Error: no active viewer!\n";
10703     return 1;
10704   }
10705
10706   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
10707   TCollection_AsciiString aCmdName (theArgVec[0]);
10708   aCmdName.LowerCase();
10709   if (aCmdName == "vraytrace")
10710   {
10711     if (theArgNb == 1)
10712     {
10713       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
10714       return 0;
10715     }
10716     else if (theArgNb == 2)
10717     {
10718       TCollection_AsciiString aValue (theArgVec[1]);
10719       aValue.LowerCase();
10720       if (aValue == "on"
10721        || aValue == "1")
10722       {
10723         aParams.Method = Graphic3d_RM_RAYTRACING;
10724         aView->Redraw();
10725         return 0;
10726       }
10727       else if (aValue == "off"
10728             || aValue == "0")
10729       {
10730         aParams.Method = Graphic3d_RM_RASTERIZATION;
10731         aView->Redraw();
10732         return 0;
10733       }
10734       else
10735       {
10736         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
10737         return 1;
10738       }
10739     }
10740     else
10741     {
10742       std::cout << "Error: wrong number of arguments\n";
10743       return 1;
10744     }
10745   }
10746
10747   if (theArgNb < 2)
10748   {
10749     theDI << "renderMode:  ";
10750     switch (aParams.Method)
10751     {
10752       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10753       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
10754     }
10755     theDI << "\n";
10756     theDI << "transparency:  ";
10757     switch (aParams.TransparencyMethod)
10758     {
10759       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
10760       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
10761                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
10762     }
10763     theDI << "\n";
10764     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
10765     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
10766     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
10767     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
10768     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
10769     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
10770     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
10771     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
10772     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
10773     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
10774     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
10775     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
10776     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
10777     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
10778     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
10779     theDI << "shadingModel: ";
10780     switch (aView->ShadingModel())
10781     {
10782       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
10783       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
10784       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
10785       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
10786       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
10787     }
10788     {
10789       theDI << "perfCounters:";
10790       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
10791       {
10792         theDI << " fps";
10793       }
10794       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
10795       {
10796         theDI << " cpu";
10797       }
10798       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
10799       {
10800         theDI << " structs";
10801       }
10802       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
10803       {
10804         theDI << " groups";
10805       }
10806       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
10807       {
10808         theDI << " arrays";
10809       }
10810       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
10811       {
10812         theDI << " tris";
10813       }
10814       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
10815       {
10816         theDI << " pnts";
10817       }
10818       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
10819       {
10820         theDI << " gpumem";
10821       }
10822       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
10823       {
10824         theDI << " frameTime";
10825       }
10826       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
10827       {
10828         theDI << " skipimmediate";
10829       }
10830       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
10831       {
10832         theDI << " none";
10833       }
10834       theDI << "\n";
10835     }
10836     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
10837     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
10838     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
10839                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
10840                                                                                                                     "noUpdate") << "\n";
10841     theDI << "\n";
10842     return 0;
10843   }
10844
10845   Standard_Boolean toPrint = Standard_False;
10846   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10847   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10848   {
10849     Standard_CString        anArg (theArgVec[anArgIter]);
10850     TCollection_AsciiString aFlag (anArg);
10851     aFlag.LowerCase();
10852     if (anUpdateTool.parseRedrawMode (aFlag))
10853     {
10854       continue;
10855     }
10856     else if (aFlag == "-echo"
10857           || aFlag == "-print")
10858     {
10859       toPrint = Standard_True;
10860       anUpdateTool.Invalidate();
10861     }
10862     else if (aFlag == "-mode"
10863           || aFlag == "-rendermode"
10864           || aFlag == "-render_mode")
10865     {
10866       if (toPrint)
10867       {
10868         switch (aParams.Method)
10869         {
10870           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10871           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
10872         }
10873         continue;
10874       }
10875       else
10876       {
10877         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10878         return 1;
10879       }
10880     }
10881     else if (aFlag == "-ray"
10882           || aFlag == "-raytrace")
10883     {
10884       if (toPrint)
10885       {
10886         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
10887         continue;
10888       }
10889
10890       aParams.Method = Graphic3d_RM_RAYTRACING;
10891     }
10892     else if (aFlag == "-rast"
10893           || aFlag == "-raster"
10894           || aFlag == "-rasterization")
10895     {
10896       if (toPrint)
10897       {
10898         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
10899         continue;
10900       }
10901
10902       aParams.Method = Graphic3d_RM_RASTERIZATION;
10903     }
10904     else if (aFlag == "-msaa")
10905     {
10906       if (toPrint)
10907       {
10908         theDI << aParams.NbMsaaSamples << " ";
10909         continue;
10910       }
10911       else if (++anArgIter >= theArgNb)
10912       {
10913         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10914         return 1;
10915       }
10916
10917       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
10918       if (aNbSamples < 0)
10919       {
10920         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
10921         return 1;
10922       }
10923       else
10924       {
10925         aParams.NbMsaaSamples = aNbSamples;
10926       }
10927     }
10928     else if (aFlag == "-linefeather"
10929           || aFlag == "-edgefeather"
10930           || aFlag == "-feather")
10931     {
10932       if (toPrint)
10933       {
10934         theDI << " " << aParams.LineFeather << " ";
10935         continue;
10936       }
10937       else if (++anArgIter >= theArgNb)
10938       {
10939         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10940         return 1;
10941       }
10942
10943       TCollection_AsciiString aParam = theArgVec[anArgIter];
10944       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10945       if (aFeather <= 0.0f)
10946       {
10947         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
10948         return 1;
10949       }
10950       aParams.LineFeather = aFeather;
10951     }
10952     else if (aFlag == "-oit")
10953     {
10954       if (toPrint)
10955       {
10956         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
10957         {
10958           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
10959         }
10960         else
10961         {
10962           theDI << "off" << " ";
10963         }
10964         continue;
10965       }
10966       else if (++anArgIter >= theArgNb)
10967       {
10968         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10969         return 1;
10970       }
10971
10972       TCollection_AsciiString aParam = theArgVec[anArgIter];
10973       aParam.LowerCase();
10974       if (aParam.IsRealValue())
10975       {
10976         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10977         if (aWeight < 0.f || aWeight > 1.f)
10978         {
10979           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
10980           return 1;
10981         }
10982
10983         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
10984         aParams.OitDepthFactor     = aWeight;
10985       }
10986       else if (aParam == "off")
10987       {
10988         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
10989       }
10990       else
10991       {
10992         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10993         return 1;
10994       }
10995     }
10996     else if (aFlag == "-depthprepass")
10997     {
10998       if (toPrint)
10999       {
11000         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11001         continue;
11002       }
11003       aParams.ToEnableDepthPrepass = Standard_True;
11004       if (anArgIter + 1 < theArgNb
11005        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11006       {
11007         ++anArgIter;
11008       }
11009     }
11010     else if (aFlag == "-samplealphatocoverage"
11011           || aFlag == "-alphatocoverage")
11012     {
11013       if (toPrint)
11014       {
11015         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11016         continue;
11017       }
11018       aParams.ToEnableAlphaToCoverage = Standard_True;
11019       if (anArgIter + 1 < theArgNb
11020        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11021       {
11022         ++anArgIter;
11023       }
11024     }
11025     else if (aFlag == "-rendscale"
11026           || aFlag == "-renderscale"
11027           || aFlag == "-renderresolutionscale")
11028     {
11029       if (toPrint)
11030       {
11031         theDI << aParams.RenderResolutionScale << " ";
11032         continue;
11033       }
11034       else if (++anArgIter >= theArgNb)
11035       {
11036         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11037         return 1;
11038       }
11039
11040       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11041       if (aScale < 0.01)
11042       {
11043         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11044         return 1;
11045       }
11046       else
11047       {
11048         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11049       }
11050     }
11051     else if (aFlag == "-raydepth"
11052           || aFlag == "-ray_depth")
11053     {
11054       if (toPrint)
11055       {
11056         theDI << aParams.RaytracingDepth << " ";
11057         continue;
11058       }
11059       else if (++anArgIter >= theArgNb)
11060       {
11061         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11062         return 1;
11063       }
11064
11065       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11066
11067       // We allow RaytracingDepth be more than 10 in case of GI enabled
11068       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11069       {
11070         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11071         return 1;
11072       }
11073       else
11074       {
11075         aParams.RaytracingDepth = aDepth;
11076       }
11077     }
11078     else if (aFlag == "-shad"
11079           || aFlag == "-shadows")
11080     {
11081       if (toPrint)
11082       {
11083         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11084         continue;
11085       }
11086
11087       Standard_Boolean toEnable = Standard_True;
11088       if (++anArgIter < theArgNb
11089       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11090       {
11091         --anArgIter;
11092       }
11093       aParams.IsShadowEnabled = toEnable;
11094     }
11095     else if (aFlag == "-refl"
11096           || aFlag == "-reflections")
11097     {
11098       if (toPrint)
11099       {
11100         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11101         continue;
11102       }
11103
11104       Standard_Boolean toEnable = Standard_True;
11105       if (++anArgIter < theArgNb
11106       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11107       {
11108         --anArgIter;
11109       }
11110       aParams.IsReflectionEnabled = toEnable;
11111     }
11112     else if (aFlag == "-fsaa")
11113     {
11114       if (toPrint)
11115       {
11116         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11117         continue;
11118       }
11119
11120       Standard_Boolean toEnable = Standard_True;
11121       if (++anArgIter < theArgNb
11122       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11123       {
11124         --anArgIter;
11125       }
11126       aParams.IsAntialiasingEnabled = toEnable;
11127     }
11128     else if (aFlag == "-gleam")
11129     {
11130       if (toPrint)
11131       {
11132         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11133         continue;
11134       }
11135
11136       Standard_Boolean toEnable = Standard_True;
11137       if (++anArgIter < theArgNb
11138       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11139       {
11140         --anArgIter;
11141       }
11142       aParams.IsTransparentShadowEnabled = toEnable;
11143     }
11144     else if (aFlag == "-gi")
11145     {
11146       if (toPrint)
11147       {
11148         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11149         continue;
11150       }
11151
11152       Standard_Boolean toEnable = Standard_True;
11153       if (++anArgIter < theArgNb
11154       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11155       {
11156         --anArgIter;
11157       }
11158       aParams.IsGlobalIlluminationEnabled = toEnable;
11159       if (!toEnable)
11160       {
11161         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11162       }
11163     }
11164     else if (aFlag == "-blockedrng"
11165           || aFlag == "-brng")
11166     {
11167       if (toPrint)
11168       {
11169         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11170         continue;
11171       }
11172
11173       Standard_Boolean toEnable = Standard_True;
11174       if (++anArgIter < theArgNb
11175         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11176       {
11177         --anArgIter;
11178       }
11179       aParams.CoherentPathTracingMode = toEnable;
11180     }
11181     else if (aFlag == "-maxrad")
11182     {
11183       if (toPrint)
11184       {
11185         theDI << aParams.RadianceClampingValue << " ";
11186         continue;
11187       }
11188       else if (++anArgIter >= theArgNb)
11189       {
11190         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11191         return 1;
11192       }
11193
11194       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11195       if (!aMaxRadStr.IsRealValue())
11196       {
11197         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11198         return 1;
11199       }
11200
11201       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11202       if (aMaxRadiance <= 0.0)
11203       {
11204         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11205         return 1;
11206       }
11207       else
11208       {
11209         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11210       }
11211     }
11212     else if (aFlag == "-iss")
11213     {
11214       if (toPrint)
11215       {
11216         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11217         continue;
11218       }
11219
11220       Standard_Boolean toEnable = Standard_True;
11221       if (++anArgIter < theArgNb
11222         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11223       {
11224         --anArgIter;
11225       }
11226       aParams.AdaptiveScreenSampling = toEnable;
11227     }
11228     else if (aFlag == "-issatomic")
11229     {
11230       if (toPrint)
11231       {
11232         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11233         continue;
11234       }
11235
11236       Standard_Boolean toEnable = Standard_True;
11237       if (++anArgIter < theArgNb
11238       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11239       {
11240         --anArgIter;
11241       }
11242       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11243     }
11244     else if (aFlag == "-issd")
11245     {
11246       if (toPrint)
11247       {
11248         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11249         continue;
11250       }
11251
11252       Standard_Boolean toEnable = Standard_True;
11253       if (++anArgIter < theArgNb
11254         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11255       {
11256         --anArgIter;
11257       }
11258       aParams.ShowSamplingTiles = toEnable;
11259     }
11260     else if (aFlag == "-tilesize")
11261     {
11262       if (toPrint)
11263       {
11264         theDI << aParams.RayTracingTileSize << " ";
11265         continue;
11266       }
11267       else if (++anArgIter >= theArgNb)
11268       {
11269         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11270         return 1;
11271       }
11272
11273       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11274       if (aTileSize < 1)
11275       {
11276         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11277         return 1;
11278       }
11279       aParams.RayTracingTileSize = aTileSize;
11280     }
11281     else if (aFlag == "-nbtiles")
11282     {
11283       if (toPrint)
11284       {
11285         theDI << aParams.NbRayTracingTiles << " ";
11286         continue;
11287       }
11288       else if (++anArgIter >= theArgNb)
11289       {
11290         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11291         return 1;
11292       }
11293
11294       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11295       if (aNbTiles < -1)
11296       {
11297         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11298         return 1;
11299       }
11300       else if (aNbTiles > 0
11301             && (aNbTiles < 64
11302              || aNbTiles > 1024))
11303       {
11304         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
11305       }
11306       aParams.NbRayTracingTiles = aNbTiles;
11307     }
11308     else if (aFlag == "-env")
11309     {
11310       if (toPrint)
11311       {
11312         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11313         continue;
11314       }
11315
11316       Standard_Boolean toEnable = Standard_True;
11317       if (++anArgIter < theArgNb
11318         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11319       {
11320         --anArgIter;
11321       }
11322       aParams.UseEnvironmentMapBackground = toEnable;
11323     }
11324     else if (aFlag == "-twoside")
11325     {
11326       if (toPrint)
11327       {
11328         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
11329         continue;
11330       }
11331
11332       Standard_Boolean toEnable = Standard_True;
11333       if (++anArgIter < theArgNb
11334         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11335       {
11336         --anArgIter;
11337       }
11338       aParams.TwoSidedBsdfModels = toEnable;
11339     }
11340     else if (aFlag == "-shademodel"
11341           || aFlag == "-shadingmodel"
11342           || aFlag == "-shading")
11343     {
11344       if (toPrint)
11345       {
11346         switch (aView->ShadingModel())
11347         {
11348           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
11349           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
11350           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
11351           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
11352           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
11353         }
11354         continue;
11355       }
11356
11357       if (++anArgIter >= theArgNb)
11358       {
11359         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11360       }
11361
11362       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
11363       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
11364        && aModel != Graphic3d_TOSM_DEFAULT)
11365       {
11366         aView->SetShadingModel (aModel);
11367       }
11368       else
11369       {
11370         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
11371         return 1;
11372       }
11373     }
11374     else if (aFlag == "-resolution")
11375     {
11376       if (++anArgIter >= theArgNb)
11377       {
11378         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11379         return 1;
11380       }
11381
11382       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
11383       if (aResolution.IsIntegerValue())
11384       {
11385         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
11386       }
11387       else
11388       {
11389         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11390         return 1;
11391       }
11392     }
11393     else if (aFlag == "-rebuildglsl"
11394           || aFlag == "-rebuild")
11395     {
11396       if (toPrint)
11397       {
11398         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
11399         continue;
11400       }
11401
11402       Standard_Boolean toEnable = Standard_True;
11403       if (++anArgIter < theArgNb
11404           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11405       {
11406         --anArgIter;
11407       }
11408       aParams.RebuildRayTracingShaders = toEnable;
11409     }
11410     else if (aFlag == "-focal")
11411     {
11412       if (++anArgIter >= theArgNb)
11413       {
11414         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11415         return 1;
11416       }
11417
11418       TCollection_AsciiString aParam (theArgVec[anArgIter]);
11419       if (aParam.IsRealValue())
11420       {
11421         float aFocalDist = static_cast<float> (aParam.RealValue());
11422         if (aFocalDist < 0)
11423         {
11424           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11425           return 1;
11426         }
11427         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
11428       }
11429       else
11430       {
11431         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11432         return 1;
11433       }
11434     }
11435     else if (aFlag == "-aperture")
11436     {
11437       if (++anArgIter >= theArgNb)
11438       {
11439         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11440         return 1;
11441       }
11442
11443       TCollection_AsciiString aParam(theArgVec[anArgIter]);
11444       if (aParam.IsRealValue())
11445       {
11446         float aApertureSize = static_cast<float> (aParam.RealValue());
11447         if (aApertureSize < 0)
11448         {
11449           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11450           return 1;
11451         }
11452         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
11453       }
11454       else
11455       {
11456         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11457         return 1;
11458       }
11459     }
11460     else if (aFlag == "-exposure")
11461     {
11462       if (++anArgIter >= theArgNb)
11463       {
11464         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11465         return 1;
11466       }
11467
11468       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
11469       if (anExposure.IsRealValue())
11470       {
11471         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
11472       }
11473       else
11474       {
11475         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11476         return 1;
11477       }
11478     }
11479     else if (aFlag == "-whitepoint")
11480     {
11481       if (++anArgIter >= theArgNb)
11482       {
11483         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11484         return 1;
11485       }
11486
11487       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
11488       if (aWhitePoint.IsRealValue())
11489       {
11490         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
11491       }
11492       else
11493       {
11494         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11495         return 1;
11496       }
11497     }
11498     else if (aFlag == "-tonemapping")
11499     {
11500       if (++anArgIter >= theArgNb)
11501       {
11502         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11503         return 1;
11504       }
11505
11506       TCollection_AsciiString aMode (theArgVec[anArgIter]);
11507       aMode.LowerCase();
11508
11509       if (aMode == "disabled")
11510       {
11511         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
11512       }
11513       else if (aMode == "filmic")
11514       {
11515         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
11516       }
11517       else
11518       {
11519         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11520         return 1;
11521       }
11522     }
11523     else if (aFlag == "-performancestats"
11524           || aFlag == "-performancecounters"
11525           || aFlag == "-perfstats"
11526           || aFlag == "-perfcounters"
11527           || aFlag == "-stats")
11528     {
11529       if (++anArgIter >= theArgNb)
11530       {
11531         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11532         return 1;
11533       }
11534
11535       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
11536       aFlagsStr.LowerCase();
11537       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
11538       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
11539       {
11540         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11541         return 1;
11542       }
11543       aView->ChangeRenderingParams().CollectedStats = aFlags;
11544       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
11545     }
11546     else if (aFlag == "-perfupdateinterval"
11547           || aFlag == "-statsupdateinterval")
11548     {
11549       if (++anArgIter >= theArgNb)
11550       {
11551         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11552         return 1;
11553       }
11554       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11555     }
11556     else if (aFlag == "-perfchart"
11557           || aFlag == "-statschart")
11558     {
11559       if (++anArgIter >= theArgNb)
11560       {
11561         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11562         return 1;
11563       }
11564       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
11565     }
11566     else if (aFlag == "-perfchartmax"
11567           || aFlag == "-statschartmax")
11568     {
11569       if (++anArgIter >= theArgNb)
11570       {
11571         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11572         return 1;
11573       }
11574       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11575     }
11576     else if (aFlag == "-frustumculling"
11577           || aFlag == "-culling")
11578     {
11579       if (toPrint)
11580       {
11581         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
11582                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
11583                                                                                                    "noUpdate") << " ";
11584         continue;
11585       }
11586
11587       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
11588       if (++anArgIter < theArgNb)
11589       {
11590         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
11591         aStateStr.LowerCase();
11592         bool toEnable = true;
11593         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
11594         {
11595           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
11596         }
11597         else if (aStateStr == "noupdate"
11598               || aStateStr == "freeze")
11599         {
11600           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
11601         }
11602         else
11603         {
11604           --anArgIter;
11605         }
11606       }
11607       aParams.FrustumCullingState = aState;
11608     }
11609     else
11610     {
11611       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
11612       return 1;
11613     }
11614   }
11615
11616   return 0;
11617 }
11618
11619 //=======================================================================
11620 //function : searchInfo
11621 //purpose  :
11622 //=======================================================================
11623 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
11624                                            const TCollection_AsciiString&              theKey)
11625 {
11626   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
11627   {
11628     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
11629     {
11630       return anIter.Value();
11631     }
11632   }
11633   return TCollection_AsciiString();
11634 }
11635
11636 //=======================================================================
11637 //function : VStatProfiler
11638 //purpose  :
11639 //=======================================================================
11640 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
11641                                        Standard_Integer  theArgNb,
11642                                        const char**      theArgVec)
11643 {
11644   Handle(V3d_View) aView = ViewerTest::CurrentView();
11645   if (aView.IsNull())
11646   {
11647     std::cerr << "Error: no active viewer!\n";
11648     return 1;
11649   }
11650
11651   Standard_Boolean toRedraw = Standard_True;
11652   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
11653   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
11654   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
11655   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11656   {
11657     Standard_CString        anArg (theArgVec[anArgIter]);
11658     TCollection_AsciiString aFlag (anArg);
11659     aFlag.LowerCase();
11660     if (aFlag == "-noredraw")
11661     {
11662       toRedraw = Standard_False;
11663     }
11664     else
11665     {
11666       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
11667       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11668       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
11669       else if (aFlag == "alllayers"
11670             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
11671       else if (aFlag == "allstructs"
11672             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
11673       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
11674       else if (aFlag == "allarrays"
11675             || aFlag == "fillarrays"
11676             || aFlag == "linearrays"
11677             || aFlag == "pointarrays"
11678             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11679       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
11680       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
11681       else if (aFlag == "geommem"
11682             || aFlag == "texturemem"
11683             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11684       else if (aFlag == "elapsedframe"
11685             || aFlag == "cpuframeaverage"
11686             || aFlag == "cpupickingaverage"
11687             || aFlag == "cpucullingaverage"
11688             || aFlag == "cpudynaverage"
11689             || aFlag == "cpuframemax"
11690             || aFlag == "cpupickingmax"
11691             || aFlag == "cpucullingmax"
11692             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11693       else
11694       {
11695         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
11696         continue;
11697       }
11698
11699       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
11700     }
11701   }
11702
11703   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
11704   {
11705     aView->ChangeRenderingParams().CollectedStats =
11706       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
11707
11708     if (toRedraw)
11709     {
11710       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
11711       aView->Redraw();
11712       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
11713     }
11714
11715     TColStd_IndexedDataMapOfStringString aDict;
11716     aView->StatisticInformation (aDict);
11717
11718     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
11719
11720     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11721     {
11722       Standard_CString        anArg(theArgVec[anArgIter]);
11723       TCollection_AsciiString aFlag(anArg);
11724       aFlag.LowerCase();
11725       if (aFlag == "fps")
11726       {
11727         theDI << searchInfo (aDict, "FPS") << " ";
11728       }
11729       else if (aFlag == "cpu")
11730       {
11731         theDI << searchInfo (aDict, "CPU FPS") << " ";
11732       }
11733       else if (aFlag == "alllayers")
11734       {
11735         theDI << searchInfo (aDict, "Layers") << " ";
11736       }
11737       else if (aFlag == "layers")
11738       {
11739         theDI << searchInfo (aDict, "Rendered layers") << " ";
11740       }
11741       else if (aFlag == "allstructs")
11742       {
11743         theDI << searchInfo (aDict, "Structs") << " ";
11744       }
11745       else if (aFlag == "structs")
11746       {
11747         theDI << searchInfo (aDict, "Rendered structs") << " ";
11748       }
11749       else if (aFlag == "groups")
11750       {
11751         theDI << searchInfo (aDict, "Rendered groups") << " ";
11752       }
11753       else if (aFlag == "allarrays")
11754       {
11755         theDI << searchInfo (aDict, "Rendered arrays") << " ";
11756       }
11757       else if (aFlag == "fillarrays")
11758       {
11759         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
11760       }
11761       else if (aFlag == "linearrays")
11762       {
11763         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
11764       }
11765       else if (aFlag == "pointarrays")
11766       {
11767         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
11768       }
11769       else if (aFlag == "textarrays")
11770       {
11771         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
11772       }
11773       else if (aFlag == "triangles")
11774       {
11775         theDI << searchInfo (aDict, "Rendered triangles") << " ";
11776       }
11777       else if (aFlag == "points")
11778       {
11779         theDI << searchInfo (aDict, "Rendered points") << " ";
11780       }
11781       else if (aFlag == "geommem")
11782       {
11783         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
11784       }
11785       else if (aFlag == "texturemem")
11786       {
11787         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
11788       }
11789       else if (aFlag == "framemem")
11790       {
11791         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
11792       }
11793       else if (aFlag == "elapsedframe")
11794       {
11795         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
11796       }
11797       else if (aFlag == "cpuframe_average")
11798       {
11799         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
11800       }
11801       else if (aFlag == "cpupicking_average")
11802       {
11803         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
11804       }
11805       else if (aFlag == "cpuculling_average")
11806       {
11807         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
11808       }
11809       else if (aFlag == "cpudyn_average")
11810       {
11811         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
11812       }
11813       else if (aFlag == "cpuframe_max")
11814       {
11815         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
11816       }
11817       else if (aFlag == "cpupicking_max")
11818       {
11819         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
11820       }
11821       else if (aFlag == "cpuculling_max")
11822       {
11823         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
11824       }
11825       else if (aFlag == "cpudyn_max")
11826       {
11827         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
11828       }
11829     }
11830   }
11831   else
11832   {
11833     if (toRedraw)
11834     {
11835       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
11836       aView->Redraw();
11837       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
11838     }
11839     theDI << "Statistic info:\n" << aView->StatisticInformation();
11840   }
11841   return 0;
11842 }
11843
11844 //=======================================================================
11845 //function : VProgressiveMode
11846 //purpose  :
11847 //=======================================================================
11848 #if defined(_WIN32)
11849 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
11850                                           Standard_Integer  /*theNbArgs*/,
11851                                           const char**      /*theArgs*/)
11852 {
11853   Handle(V3d_View) aView = ViewerTest::CurrentView();
11854   if (aView.IsNull())
11855   {
11856     std::cerr << "Error: no active viewer!\n";
11857     return 1;
11858   }
11859
11860   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
11861
11862   for (;;)
11863   {
11864     aView->Redraw();
11865
11866     Standard_Boolean toExit = Standard_False;
11867
11868     MSG aMsg;
11869     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
11870     {
11871       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
11872       {
11873         toExit = Standard_True;
11874       }
11875
11876       TranslateMessage (&aMsg);
11877       DispatchMessageW (&aMsg);
11878     }
11879
11880     if (toExit)
11881     {
11882       break;
11883     }
11884   }
11885
11886   return 0;
11887 }
11888 #endif
11889
11890 //=======================================================================
11891 //function : VXRotate
11892 //purpose  :
11893 //=======================================================================
11894 static Standard_Integer VXRotate (Draw_Interpretor& di,
11895                                    Standard_Integer argc,
11896                                    const char ** argv)
11897 {
11898   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
11899   if (aContext.IsNull())
11900   {
11901     di << argv[0] << "ERROR : use 'vinit' command before \n";
11902     return 1;
11903   }
11904
11905   if (argc != 3)
11906   {
11907     di << "ERROR : Usage : " << argv[0] << " name angle\n";
11908     return 1;
11909   }
11910
11911   TCollection_AsciiString aName (argv[1]);
11912   Standard_Real anAngle = Draw::Atof (argv[2]);
11913
11914   // find object
11915   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
11916   Handle(AIS_InteractiveObject) anIObj;
11917   if (!aMap.Find2 (aName, anIObj))
11918   {
11919     di << "Use 'vdisplay' before\n";
11920     return 1;
11921   }
11922
11923   gp_Trsf aTransform;
11924   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
11925   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
11926
11927   aContext->SetLocation (anIObj, aTransform);
11928   aContext->UpdateCurrentViewer();
11929   return 0;
11930 }
11931
11932 //===============================================================================================
11933 //class   : ViewerTest_AISManipulator
11934 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
11935 //===============================================================================================
11936 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11937
11938 class ViewerTest_AISManipulator : public AIS_Manipulator
11939 {
11940 public:
11941
11942   ViewerTest_AISManipulator() : AIS_Manipulator()
11943   {
11944     GetMapOfAISManipulators().Add (this);
11945   }
11946
11947   virtual ~ViewerTest_AISManipulator()
11948   {
11949     GetMapOfAISManipulators().Remove (this);
11950   }
11951
11952   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11953 };
11954
11955 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11956 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11957
11958 //===============================================================================================
11959 //function : VManipulator
11960 //purpose  :
11961 //===============================================================================================
11962 static int VManipulator (Draw_Interpretor& theDi,
11963                          Standard_Integer  theArgsNb,
11964                          const char**      theArgVec)
11965 {
11966   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
11967   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
11968   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
11969   if (aView.IsNull()
11970    || aViewer.IsNull())
11971   {
11972     std::cerr << "No active viewer!\n";
11973     return 1;
11974   }
11975
11976   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
11977   Standard_Integer anArgIter = 1;
11978   for (; anArgIter < theArgsNb; ++anArgIter)
11979   {
11980     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
11981   }
11982
11983   ViewerTest_CmdParser aCmd;
11984   aCmd.AddDescription ("Manages manipulator for interactive objects:");
11985   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
11986   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
11987   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
11988   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
11989   aCmd.AddOption ("detach",         "...       - detach manipulator");
11990
11991   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
11992   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
11993   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
11994
11995   aCmd.AddOption ("move",   "... x y z - move object");
11996   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
11997   aCmd.AddOption ("scale",  "... factor - scale object");
11998
11999   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12000   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12001   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12002   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12003   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12004   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12005   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12006   aCmd.AddOption ("size",              "... size - set size of manipulator");
12007   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12008
12009   aCmd.Parse (theArgsNb, theArgVec);
12010
12011   if (aCmd.HasOption ("help"))
12012   {
12013     theDi.PrintHelp (theArgVec[0]);
12014     return 0;
12015   }
12016
12017   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12018
12019   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
12020
12021   if (aName.IsEmpty())
12022   {
12023     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12024     return 1;
12025   }
12026
12027   // ----------------------------------
12028   // detach existing manipulator object
12029   // ----------------------------------
12030
12031   if (aCmd.HasOption ("detach"))
12032   {
12033     if (!aMapAIS.IsBound2 (aName))
12034     {
12035       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12036       return 1;
12037     }
12038
12039     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12040     if (aManipulator.IsNull())
12041     {
12042       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12043       return 1;
12044     }
12045
12046     aManipulator->Detach();
12047     aMapAIS.UnBind2 (aName);
12048     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12049
12050     return 0;
12051   }
12052
12053   // -----------------------------------------------
12054   // find or create manipulator if it does not exist
12055   // -----------------------------------------------
12056
12057   Handle(AIS_Manipulator) aManipulator;
12058   if (!aMapAIS.IsBound2 (aName))
12059   {
12060     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12061
12062     aManipulator = new ViewerTest_AISManipulator();
12063     aMapAIS.Bind (aManipulator, aName);
12064   }
12065   else
12066   {
12067     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12068     if (aManipulator.IsNull())
12069     {
12070       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12071       return 1;
12072     }
12073   }
12074
12075   // -----------------------------------------
12076   // change properties of manipulator instance
12077   // -----------------------------------------
12078
12079   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12080   {
12081     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12082   }
12083   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12084   {
12085     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12086   }
12087   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12088   {
12089     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12090   }
12091   if (aCmd.HasOption("followDragging", 1, Standard_True))
12092   {
12093     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12094   }
12095   if (aCmd.HasOption ("gap", 1, Standard_True))
12096   {
12097     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12098   }
12099   if (aCmd.HasOption ("part", 3, Standard_True))
12100   {
12101     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12102     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12103     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12104     if (aMode < 1 || aMode > 4)
12105     {
12106       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12107       return 1;
12108     }
12109
12110     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12111   }
12112   if (aCmd.HasOption ("pos", 3, Standard_True))
12113   {
12114     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12115     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12116     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12117
12118     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12119   }
12120   if (aCmd.HasOption ("size", 1, Standard_True))
12121   {
12122     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12123   }
12124   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12125   {
12126     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12127
12128     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12129     {
12130       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12131       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12132     }
12133   }
12134
12135   // ---------------------------------------------------
12136   // attach, detach or access manipulator from an object
12137   // ---------------------------------------------------
12138
12139   if (aCmd.HasOption ("attach"))
12140   {
12141     // Find an object and attach manipulator to it
12142     if (!aCmd.HasOption ("attach", 1, Standard_True))
12143     {
12144       return 1;
12145     }
12146
12147     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12148     Handle(AIS_InteractiveObject) anObject;
12149     if (!aMapAIS.Find2 (anObjName, anObject))
12150     {
12151       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12152       return 1;
12153     }
12154
12155     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
12156     {
12157       if (anIt.Value()->IsAttached()
12158        && anIt.Value()->Object() == anObject)
12159       {
12160         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12161         return 1;
12162       }
12163     }
12164
12165     AIS_Manipulator::OptionsForAttach anOptions;
12166     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12167     {
12168       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12169     }
12170     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12171     {
12172       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12173     }
12174     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12175     {
12176       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12177     }
12178
12179     aManipulator->Attach (anObject, anOptions);
12180   }
12181
12182   // --------------------------------------
12183   // apply transformation using manipulator
12184   // --------------------------------------
12185
12186   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12187   {
12188     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12189   }
12190   if (aCmd.HasOption ("transform", 2, Standard_True))
12191   {
12192     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
12193   }
12194   if (aCmd.HasOption ("stopTransform"))
12195   {
12196     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
12197
12198     aManipulator->StopTransform (toApply);
12199   }
12200
12201   gp_Trsf aT;
12202   if (aCmd.HasOption ("move", 3, Standard_True))
12203   {
12204     aT.SetTranslationPart (aCmd.ArgVec ("move"));
12205   }
12206   if (aCmd.HasOption ("rotate", 7, Standard_True))
12207   {
12208     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
12209   }
12210   if (aCmd.HasOption ("scale", 1))
12211   {
12212     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
12213   }
12214
12215   if (aT.Form() != gp_Identity)
12216   {
12217     aManipulator->Transform (aT);
12218   }
12219
12220   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
12221
12222   return 0;
12223 }
12224
12225 //===============================================================================================
12226 //function : VSelectionProperties
12227 //purpose  :
12228 //===============================================================================================
12229 static int VSelectionProperties (Draw_Interpretor& theDi,
12230                                  Standard_Integer  theArgsNb,
12231                                  const char**      theArgVec)
12232 {
12233   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12234   if (aCtx.IsNull())
12235   {
12236     std::cerr << "No active viewer!\n";
12237     return 1;
12238   }
12239
12240   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
12241   {
12242     // handle obsolete alias
12243     bool toEnable = true;
12244     if (theArgsNb < 2)
12245     {
12246       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
12247       return 0;
12248     }
12249     else if (theArgsNb != 2
12250          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
12251     {
12252       std::cout << "Syntax error: wrong number of parameters.";
12253       return 1;
12254     }
12255     if (toEnable != aCtx->ToHilightSelected())
12256     {
12257       aCtx->ClearDetected();
12258       aCtx->SetToHilightSelected (toEnable);
12259     }
12260     return 0;
12261   }
12262
12263   Standard_Boolean toPrint  = theArgsNb == 1;
12264   Standard_Boolean toRedraw = Standard_False;
12265   Standard_Integer anArgIter = 1;
12266   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
12267   if (anArgIter < theArgsNb)
12268   {
12269     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
12270     anArgFirst.LowerCase();
12271     ++anArgIter;
12272     if (anArgFirst == "dynhighlight"
12273      || anArgFirst == "dynhilight"
12274      || anArgFirst == "dynamichighlight"
12275      || anArgFirst == "dynamichilight")
12276     {
12277       aType = Prs3d_TypeOfHighlight_Dynamic;
12278     }
12279     else if (anArgFirst == "localdynhighlight"
12280           || anArgFirst == "localdynhilight"
12281           || anArgFirst == "localdynamichighlight"
12282           || anArgFirst == "localdynamichilight")
12283     {
12284       aType = Prs3d_TypeOfHighlight_LocalDynamic;
12285     }
12286     else if (anArgFirst == "selhighlight"
12287           || anArgFirst == "selhilight"
12288           || anArgFirst == "selectedhighlight"
12289           || anArgFirst == "selectedhilight")
12290     {
12291       aType = Prs3d_TypeOfHighlight_Selected;
12292     }
12293     else if (anArgFirst == "localselhighlight"
12294           || anArgFirst == "localselhilight"
12295           || anArgFirst == "localselectedhighlight"
12296           || anArgFirst == "localselectedhilight")
12297     {
12298       aType = Prs3d_TypeOfHighlight_LocalSelected;
12299     }
12300     else
12301     {
12302       --anArgIter;
12303     }
12304   }
12305   for (; anArgIter < theArgsNb; ++anArgIter)
12306   {
12307     TCollection_AsciiString anArg (theArgVec[anArgIter]);
12308     anArg.LowerCase();
12309     if (anArg == "-help")
12310     {
12311       theDi.PrintHelp (theArgVec[0]);
12312       return 0;
12313     }
12314     else if (anArg == "-print")
12315     {
12316       toPrint = Standard_True;
12317     }
12318     else if (anArg == "-autoactivate")
12319     {
12320       Standard_Boolean toEnable = Standard_True;
12321       if (anArgIter + 1 < theArgsNb
12322        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12323       {
12324         ++anArgIter;
12325       }
12326       aCtx->SetAutoActivateSelection (toEnable);
12327     }
12328     else if (anArg == "-automatichighlight"
12329           || anArg == "-automatichilight"
12330           || anArg == "-autohighlight"
12331           || anArg == "-autohilight")
12332     {
12333       Standard_Boolean toEnable = Standard_True;
12334       if (anArgIter + 1 < theArgsNb
12335        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12336       {
12337         ++anArgIter;
12338       }
12339       aCtx->ClearSelected (false);
12340       aCtx->ClearDetected();
12341       aCtx->SetAutomaticHilight (toEnable);
12342       toRedraw = true;
12343     }
12344     else if (anArg == "-highlightselected"
12345           || anArg == "-hilightselected")
12346     {
12347       Standard_Boolean toEnable = Standard_True;
12348       if (anArgIter + 1 < theArgsNb
12349        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12350       {
12351         ++anArgIter;
12352       }
12353       aCtx->ClearDetected();
12354       aCtx->SetToHilightSelected (toEnable);
12355       toRedraw = true;
12356     }
12357     else if (anArg == "-pickstrategy"
12358           || anArg == "-pickingstrategy")
12359     {
12360       if (++anArgIter >= theArgsNb)
12361       {
12362         std::cout << "Syntax error: type of highlighting is undefined\n";
12363         return 1;
12364       }
12365
12366       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12367       TCollection_AsciiString aVal (theArgVec[anArgIter]);
12368       aVal.LowerCase();
12369       if (aVal == "first"
12370        || aVal == "firstaccepted"
12371        || aVal == "firstacceptable")
12372       {
12373         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12374       }
12375       else if (aVal == "topmost"
12376             || aVal == "onlyTopmost")
12377       {
12378         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
12379       }
12380       else
12381       {
12382         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
12383         return 1;
12384       }
12385
12386       aCtx->SetPickingStrategy (aStrategy);
12387     }
12388     else if (anArg == "-pixtol"
12389           && anArgIter + 1 < theArgsNb)
12390     {
12391       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
12392     }
12393     else if ((anArg == "-mode"
12394            || anArg == "-dispmode")
12395           && anArgIter + 1 < theArgsNb)
12396     {
12397       if (aType == Prs3d_TypeOfHighlight_None)
12398       {
12399         std::cout << "Syntax error: type of highlighting is undefined\n";
12400         return 1;
12401       }
12402
12403       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
12404       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12405       aStyle->SetDisplayMode (aDispMode);
12406       toRedraw = Standard_True;
12407     }
12408     else if (anArg == "-layer"
12409           && anArgIter + 1 < theArgsNb)
12410     {
12411       if (aType == Prs3d_TypeOfHighlight_None)
12412       {
12413         std::cout << "Syntax error: type of highlighting is undefined\n";
12414         return 1;
12415       }
12416
12417       ++anArgIter;
12418       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
12419       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
12420       {
12421         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
12422         return 1;
12423       }
12424
12425       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12426       aStyle->SetZLayer (aNewLayer);
12427       toRedraw = Standard_True;
12428     }
12429     else if (anArg == "-hicolor"
12430           || anArg == "-selcolor"
12431           || anArg == "-color")
12432     {
12433       if (anArg.StartsWith ("-hi"))
12434       {
12435         aType = Prs3d_TypeOfHighlight_Dynamic;
12436       }
12437       else if (anArg.StartsWith ("-sel"))
12438       {
12439         aType = Prs3d_TypeOfHighlight_Selected;
12440       }
12441       else if (aType == Prs3d_TypeOfHighlight_None)
12442       {
12443         std::cout << "Syntax error: type of highlighting is undefined\n";
12444         return 1;
12445       }
12446
12447       Quantity_Color aColor;
12448       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
12449                                                            theArgVec + anArgIter + 1,
12450                                                            aColor);
12451       if (aNbParsed == 0)
12452       {
12453         std::cout << "Syntax error: need more arguments.\n";
12454         return 1;
12455       }
12456       anArgIter += aNbParsed;
12457
12458       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12459       aStyle->SetColor (aColor);
12460       toRedraw = Standard_True;
12461     }
12462     else if ((anArg == "-transp"
12463            || anArg == "-transparency"
12464            || anArg == "-hitransp"
12465            || anArg == "-seltransp"
12466            || anArg == "-hitransplocal"
12467            || anArg == "-seltransplocal")
12468           && anArgIter + 1 < theArgsNb)
12469     {
12470       if (anArg.StartsWith ("-hi"))
12471       {
12472         aType = Prs3d_TypeOfHighlight_Dynamic;
12473       }
12474       else if (anArg.StartsWith ("-sel"))
12475       {
12476         aType = Prs3d_TypeOfHighlight_Selected;
12477       }
12478       else if (aType == Prs3d_TypeOfHighlight_None)
12479       {
12480         std::cout << "Syntax error: type of highlighting is undefined\n";
12481         return 1;
12482       }
12483
12484       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
12485       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12486       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
12487       toRedraw = Standard_True;
12488     }
12489     else if ((anArg == "-mat"
12490            || anArg == "-material")
12491           && anArgIter + 1 < theArgsNb)
12492     {
12493       if (aType == Prs3d_TypeOfHighlight_None)
12494       {
12495         std::cout << "Syntax error: type of highlighting is undefined\n";
12496         return 1;
12497       }
12498
12499       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12500       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
12501       if (aMatName != Graphic3d_NOM_DEFAULT)
12502       {
12503         ++anArgIter;
12504         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
12505         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
12506         Graphic3d_MaterialAspect aMat (aMatName);
12507         aMat.SetColor (aStyle->Color());
12508         aMat.SetTransparency (aStyle->Transparency());
12509         anAspect->SetFrontMaterial (aMat);
12510         anAspect->SetInteriorColor (aStyle->Color());
12511         aStyle->SetBasicFillAreaAspect (anAspect);
12512       }
12513       else
12514       {
12515         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
12516       }
12517       toRedraw = Standard_True;
12518     }
12519     else
12520     {
12521       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
12522     }
12523   }
12524
12525   if (toPrint)
12526   {
12527     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
12528     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
12529     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
12530     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
12531     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
12532     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
12533     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
12534     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
12535     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
12536     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
12537     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
12538     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
12539     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
12540     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
12541   }
12542
12543   if (aCtx->NbSelected() != 0 && toRedraw)
12544   {
12545     aCtx->HilightSelected (Standard_True);
12546   }
12547
12548   return 0;
12549 }
12550
12551 //===============================================================================================
12552 //function : VDumpSelectionImage
12553 //purpose  :
12554 //===============================================================================================
12555 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
12556                                 Standard_Integer  theArgsNb,
12557                                 const char**      theArgVec)
12558 {
12559   if (theArgsNb < 2)
12560   {
12561     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
12562     return 1;
12563   }
12564
12565   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
12566   if (aContext.IsNull())
12567   {
12568     std::cout << "Error: no active view.\n";
12569     return 1;
12570   }
12571
12572   TCollection_AsciiString aFile;
12573   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12574   Image_Format anImgFormat = Image_Format_BGR;
12575   Standard_Integer aPickedIndex = 1;
12576   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
12577   {
12578     TCollection_AsciiString aParam (theArgVec[anArgIter]);
12579     aParam.LowerCase();
12580     if (aParam == "-type")
12581     {
12582       if (++anArgIter >= theArgsNb)
12583       {
12584         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
12585         return 1;
12586       }
12587
12588       TCollection_AsciiString aValue (theArgVec[anArgIter]);
12589       aValue.LowerCase();
12590       if (aValue == "depth"
12591        || aValue == "normdepth"
12592        || aValue == "normalizeddepth")
12593       {
12594         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12595         anImgFormat = Image_Format_GrayF;
12596       }
12597       if (aValue == "depthinverted"
12598        || aValue == "normdepthinverted"
12599        || aValue == "normalizeddepthinverted"
12600        || aValue == "inverted")
12601       {
12602         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
12603         anImgFormat = Image_Format_GrayF;
12604       }
12605       else if (aValue == "unnormdepth"
12606             || aValue == "unnormalizeddepth")
12607       {
12608         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
12609         anImgFormat = Image_Format_GrayF;
12610       }
12611       else if (aValue == "objectcolor"
12612             || aValue == "object"
12613             || aValue == "color")
12614       {
12615         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
12616       }
12617       else if (aValue == "entitycolor"
12618             || aValue == "entity")
12619       {
12620         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
12621       }
12622       else if (aValue == "ownercolor"
12623             || aValue == "owner")
12624       {
12625         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
12626       }
12627       else if (aValue == "selectionmodecolor"
12628             || aValue == "selectionmode"
12629             || aValue == "selmodecolor"
12630             || aValue == "selmode")
12631       {
12632         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
12633       }
12634     }
12635     else if (aParam == "-picked"
12636           || aParam == "-pickeddepth"
12637           || aParam == "-pickedindex")
12638     {
12639       if (++anArgIter >= theArgsNb)
12640       {
12641         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
12642         return 1;
12643       }
12644
12645       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
12646     }
12647     else if (aFile.IsEmpty())
12648     {
12649       aFile = theArgVec[anArgIter];
12650     }
12651     else
12652     {
12653       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
12654       return 1;
12655     }
12656   }
12657   if (aFile.IsEmpty())
12658   {
12659     std::cout << "Syntax error: image file name is missing.\n";
12660     return 1;
12661   }
12662
12663   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
12664   Standard_Integer aWidth = 0, aHeight = 0;
12665   aView->Window()->Size (aWidth, aHeight);
12666
12667   Image_AlienPixMap aPixMap;
12668   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
12669   {
12670     std::cout << "Error: can't allocate image.\n";
12671     return 1;
12672   }
12673   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
12674   {
12675     std::cout << "Error: can't generate selection image.\n";
12676     return 1;
12677   }
12678   if (!aPixMap.Save (aFile))
12679   {
12680     std::cout << "Error: can't save selection image.\n";
12681     return 0;
12682   }
12683   return 0;
12684 }
12685
12686 //=======================================================================
12687 //function : ViewerCommands
12688 //purpose  :
12689 //=======================================================================
12690
12691 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
12692 {
12693
12694   const char *group = "ZeViewer";
12695   theCommands.Add("vinit",
12696           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
12697     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
12698   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
12699     "\n\t\t:     [-display displayName]"
12700   #endif
12701     "\n\t\t: Creates new View window with specified name viewName."
12702     "\n\t\t: By default the new view is created in the viewer and in"
12703     "\n\t\t: graphic driver shared with active view."
12704     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
12705     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
12706     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
12707 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
12708     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
12709     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
12710 #endif
12711     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
12712     "\n\t\t:  -width, -height width and heigth of window respectively."
12713     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
12714     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
12715     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
12716     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
12717     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
12718     __FILE__,VInit,group);
12719   theCommands.Add("vclose" ,
12720     "[view_id [keep_context=0|1]]\n"
12721     "or vclose ALL - to remove all created views\n"
12722     " - removes view(viewer window) defined by its view_id.\n"
12723     " - keep_context: by default 0; if 1 and the last view is deleted"
12724     " the current context is not removed.",
12725     __FILE__,VClose,group);
12726   theCommands.Add("vactivate" ,
12727     "vactivate view_id [-noUpdate]"
12728     " - activates view(viewer window) defined by its view_id",
12729     __FILE__,VActivate,group);
12730   theCommands.Add("vviewlist",
12731     "vviewlist [format={tree, long}]"
12732     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
12733     " - format: format of result output, if tree the output is a tree view;"
12734     "otherwise it's a list of full view names. By default format = tree",
12735     __FILE__,VViewList,group);
12736   theCommands.Add("vhelp" ,
12737     "vhelp            : display help on the viewer commands",
12738     __FILE__,VHelp,group);
12739   theCommands.Add("vtop" ,
12740     "vtop or <T>      : Top view. Orientation +X+Y" ,
12741     __FILE__,VTop,group);
12742   theCommands.Add("vbottom" ,
12743     "vbottom          : Bottom view. Orientation +X-Y" ,
12744     __FILE__,VBottom,group);
12745   theCommands.Add("vleft" ,
12746     "vleft            : Left view. Orientation -Y+Z" ,
12747     __FILE__,VLeft,group);
12748   theCommands.Add("vright" ,
12749     "vright           : Right view. Orientation +Y+Z" ,
12750     __FILE__,VRight,group);
12751   theCommands.Add("vaxo" ,
12752     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
12753     __FILE__,VAxo,group);
12754   theCommands.Add("vfront" ,
12755     "vfront           : Front view. Orientation +X+Z" ,
12756     __FILE__,VFront,group);
12757   theCommands.Add("vback" ,
12758     "vback            : Back view. Orientation -X+Z" ,
12759     __FILE__,VBack,group);
12760   theCommands.Add("vpick" ,
12761     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
12762     VPick,group);
12763   theCommands.Add("vfit",
12764     "vfit or <F> [-selected] [-noupdate]"
12765     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
12766     __FILE__,VFit,group);
12767   theCommands.Add ("vfitarea",
12768     "vfitarea x1 y1 x2 y2"
12769     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
12770     "\n\t\t: Fit view to show area located between two points"
12771     "\n\t\t: given in world 2D or 3D corrdinates.",
12772     __FILE__, VFitArea, group);
12773   theCommands.Add ("vzfit", "vzfit [scale]\n"
12774     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
12775     "   \"scale\" - specifies factor to scale computed z range.\n",
12776     __FILE__, VZFit, group);
12777   theCommands.Add("vrepaint",
12778             "vrepaint [-immediate] [-continuous FPS]"
12779     "\n\t\t: force redraw of active View"
12780     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
12781     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
12782     "\n\t\t:                0 means no continuous rendering,"
12783     "\n\t\t:               -1 means non-stop redraws,"
12784     "\n\t\t:               >0 specifies target framerate,",
12785     __FILE__,VRepaint,group);
12786   theCommands.Add("vclear",
12787     "vclear          : vclear"
12788     "\n\t\t: remove all the object from the viewer",
12789     __FILE__,VClear,group);
12790   theCommands.Add("vsetbg",
12791     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
12792     __FILE__,VSetBg,group);
12793   theCommands.Add("vsetbgmode",
12794     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
12795     __FILE__,VSetBgMode,group);
12796   theCommands.Add("vsetgradientbg",
12797     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
12798     __FILE__,VSetGradientBg,group);
12799   theCommands.Add("vsetgrbgmode",
12800     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
12801     __FILE__,VSetGradientBgMode,group);
12802   theCommands.Add("vsetcolorbg",
12803     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
12804     __FILE__,VSetColorBg,group);
12805   theCommands.Add("vsetdefaultbg",
12806     "vsetdefaultbg r g b\n"
12807     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
12808     "\n\t\t: Set default viewer background fill color (flat/gradient).",
12809     __FILE__,VSetDefaultBg,group);
12810   theCommands.Add("vscale",
12811     "vscale          : vscale X Y Z",
12812     __FILE__,VScale,group);
12813   theCommands.Add("vzbufftrihedron",
12814             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
12815     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
12816     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
12817     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
12818     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
12819     "\n\t\t: Displays a trihedron",
12820     __FILE__,VZBuffTrihedron,group);
12821   theCommands.Add("vrotate",
12822     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
12823     "\n                : Option -mouseStart starts rotation according to the mouse position"
12824     "\n                : Option -mouseMove continues rotation with angle computed"
12825     "\n                : from last and new mouse position."
12826     "\n                : vrotate AX AY AZ [X Y Z]",
12827     __FILE__,VRotate,group);
12828   theCommands.Add("vzoom",
12829     "vzoom           : vzoom coef",
12830     __FILE__,VZoom,group);
12831   theCommands.Add("vpan",
12832     "vpan            : vpan dx dy",
12833     __FILE__,VPan,group);
12834   theCommands.Add("vcolorscale",
12835     "vcolorscale name [-noupdate|-update] [-demo]"
12836     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
12837     "\n\t\t:       [-font HeightFont=20]"
12838     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
12839     "\n\t\t:       [-smoothTransition {on|off}=off]"
12840     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
12841     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
12842     "\n\t\t:       [-textpos {left|right|center|none}=right]"
12843     "\n\t\t:       [-labelAtBorder {on|off}=on]"
12844     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
12845     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
12846     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
12847     "\n\t\t:       [-xy Left=0 Bottom=0]"
12848     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
12849     "\n\t\t:  -colors   - set colors for all intervals"
12850     "\n\t\t:  -color    - set color for specific interval"
12851     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
12852     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
12853     "\n\t\t:              at border means the value inbetween neighbor intervals,"
12854     "\n\t\t:              at center means the center value within current interval"
12855     "\n\t\t:  -labels   - set labels for all intervals"
12856     "\n\t\t:  -freeLabels - same as -labels but does not require"
12857     "\n\t\t:              matching the number of intervals"
12858     "\n\t\t:  -label    - set label for specific interval"
12859     "\n\t\t:  -title    - set title"
12860     "\n\t\t:  -reversed - setup smooth color transition between intervals"
12861     "\n\t\t:  -smoothTransition - swap colorscale direction"
12862     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
12863     __FILE__, VColorScale, group);
12864   theCommands.Add("vgraduatedtrihedron",
12865     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
12866     "\t[-namefont Name] [-valuesfont Name]\n"
12867     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
12868     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
12869     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
12870     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
12871     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
12872     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
12873     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
12874     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
12875     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
12876     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
12877     " - Displays or erases graduated trihedron"
12878     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
12879     " - namefont - font of axes names. Default: Arial\n"
12880     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
12881     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
12882     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
12883     " - valuesfont - font of axes values. Default: Arial\n"
12884     " - xcolor, ycolor, zcolor - color of axis and values\n"
12885     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
12886     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
12887     __FILE__,VGraduatedTrihedron,group);
12888   theCommands.Add("vtile" ,
12889             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
12890     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
12891     "\n\t\t:  -totalSize the size of virtual bigger viewport"
12892     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
12893     "\n\t\t:  -lowerLeft tile offset as lower left corner"
12894     "\n\t\t:  -upperLeft tile offset as upper left corner",
12895     __FILE__, VTile, group);
12896   theCommands.Add("vzlayer",
12897               "vzlayer [layerId]"
12898       "\n\t\t:         [-add|-delete|-get|-settings]"
12899       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
12900       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
12901       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
12902       "\n\t\t: ZLayer list management:"
12903       "\n\t\t:   -add      add new z layer to viewer and print its id"
12904       "\n\t\t:   -delete   delete z layer"
12905       "\n\t\t:   -get      print sequence of z layers"
12906       "\n\t\t:   -settings print status of z layer settings"
12907       "\n\t\t:   -disable  disables given setting"
12908       "\n\t\t:   -enable   enables  given setting",
12909     __FILE__,VZLayer,group);
12910   theCommands.Add("vlayerline",
12911     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
12912     __FILE__,VLayerLine,group);
12913   theCommands.Add("vgrid",
12914               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
12915       "\n\t\t:       [-step X Y] [-size DX DY]"
12916       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
12917     __FILE__, VGrid, group);
12918   theCommands.Add ("vpriviledgedplane",
12919     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
12920     "\n\t\t:   Ox, Oy, Oz - plane origin"
12921     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
12922     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
12923     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
12924     __FILE__, VPriviledgedPlane, group);
12925   theCommands.Add ("vconvert",
12926     "vconvert v [Mode={window|view}]"
12927     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
12928     "\n\t\t: vconvert x y z [Mode={window|grid}]"
12929     "\n\t\t:   window - convert to window coordinates, pixels"
12930     "\n\t\t:   view   - convert to view projection plane"
12931     "\n\t\t:   grid   - convert to model coordinates, given on grid"
12932     "\n\t\t:   ray    - convert projection ray to model coordiantes"
12933     "\n\t\t: - vconvert v window : convert view to window;"
12934     "\n\t\t: - vconvert v view   : convert window to view;"
12935     "\n\t\t: - vconvert x y window : convert view to window;"
12936     "\n\t\t: - vconvert x y view : convert window to view;"
12937     "\n\t\t: - vconvert x y : convert window to model;"
12938     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
12939     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
12940     "\n\t\t: - vconvert x y z window : convert model to window;"
12941     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
12942     "\n\t\t: Converts the given coordinates to window/view/model space.",
12943     __FILE__, VConvert, group);
12944   theCommands.Add ("vfps",
12945     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
12946     __FILE__, VFps, group);
12947   theCommands.Add ("vgldebug",
12948             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
12949     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
12950     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
12951     "\n\t\t: Debug context can be requested only on Windows"
12952     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
12953     "\n\t\t:  -sync     - request synchronized debug GL context"
12954     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
12955     "\n\t\t:              which are suppressed by default,"
12956     "\n\t\t:  -glslCode - log GLSL program source code,"
12957     "\n\t\t:              which are suppressed by default,"
12958     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
12959     "\n\t\t:              which are suppressed by default",
12960     __FILE__, VGlDebug, group);
12961   theCommands.Add ("vvbo",
12962     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
12963     __FILE__, VVbo, group);
12964   theCommands.Add ("vstereo",
12965             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
12966     "\n\t\t:         [-anaglyph Filter]"
12967     "\n\t\t: Control stereo output mode. Available modes for -mode:"
12968     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
12969     "\n\t\t:                     requires driver support."
12970     "\n\t\t:                     Should be called BEFORE vinit!"
12971     "\n\t\t:  anaglyph         - Anaglyph glasses"
12972     "\n\t\t:  rowInterlaced    - row-interlaced display"
12973     "\n\t\t:  columnInterlaced - column-interlaced display"
12974     "\n\t\t:  chessBoard       - chess-board output"
12975     "\n\t\t:  sideBySide       - horizontal pair"
12976     "\n\t\t:  overUnder        - vertical   pair"
12977     "\n\t\t: Available Anaglyph filters for -anaglyph:"
12978     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
12979     "\n\t\t:  greenMagentaSimple",
12980     __FILE__, VStereo, group);
12981   theCommands.Add ("vcaps",
12982             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
12983     "\n\t\t:       [-compatibleProfile {0|1}]"
12984     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
12985     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
12986     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
12987     "\n\t\t: Modify particular graphic driver options:"
12988     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
12989     "\n\t\t:             built-in GLSL programs"
12990     "\n\t\t:            (requires compatible profile)"
12991     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
12992     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
12993     "\n\t\t:             arrays to GPU memory)"
12994     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
12995     "\n\t\t:  vsync    - switch VSync on or off"
12996     "\n\t\t:  winBuffer - allow using window buffer for rendering"
12997     "\n\t\t: Context creation options:"
12998     "\n\t\t:  softMode          - software OpenGL implementation"
12999     "\n\t\t:  compatibleProfile - backward-compatible profile"
13000     "\n\t\t:  quadbuffer        - QuadBuffer"
13001     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
13002     "\n\t\t: rendering paths producing the same visual result when"
13003     "\n\t\t: possible."
13004     "\n\t\t: Command is intended for testing old hardware compatibility.",
13005     __FILE__, VCaps, group);
13006   theCommands.Add ("vmemgpu",
13007     "vmemgpu [f]: print system-dependent GPU memory information if available;"
13008     " with f option returns free memory in bytes",
13009     __FILE__, VMemGpu, group);
13010   theCommands.Add ("vreadpixel",
13011     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
13012     " : Read pixel value for active view",
13013     __FILE__, VReadPixel, group);
13014   theCommands.Add("diffimage",
13015             "diffimage imageFile1 imageFile2 [diffImageFile]"
13016     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
13017     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
13018     "\n\t\t: Compare two images by content and generate difference image."
13019     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
13020     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
13021     __FILE__, VDiffImage, group);
13022   theCommands.Add ("vselect",
13023     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
13024     "- emulates different types of selection:\n"
13025     "- 1) single click selection\n"
13026     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
13027     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
13028     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
13029     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
13030     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
13031     " (partial inclusion - overlap - is not allowed by default)\n"
13032     "- 5) any of these selections with shift button pressed",
13033     __FILE__, VSelect, group);
13034   theCommands.Add ("vmoveto",
13035     "vmoveto [x y] [-reset]"
13036     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
13037     "\n\t\t:   -reset resets current highlighting",
13038     __FILE__, VMoveTo, group);
13039   theCommands.Add ("vviewparams",
13040               "vviewparams [-args] [-scale [s]]"
13041       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
13042       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
13043       "\n\t\t: Manage current view parameters or prints all"
13044       "\n\t\t: current values when called without argument."
13045       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
13046       "\n\t\t:   -eye  [x y z] prints or sets eye location"
13047       "\n\t\t:   -at   [x y z] prints or sets center of look"
13048       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
13049       "\n\t\t:   -proj [x y z] prints or sets direction of look"
13050       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
13051       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
13052       "\n\t\t:                 or changes the size of its maximum dimension"
13053       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
13054     __FILE__, VViewParams, group);
13055
13056   theCommands.Add("v2dmode",
13057     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
13058     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
13059     "\n\t\t:   mode   - switches On/Off rotation mode"
13060     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
13061     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
13062     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
13063     "\n\t\t: View camera position might be changed only by commands.",
13064     __FILE__, V2DMode, group);
13065
13066   theCommands.Add("vanimation", "Alias for vanim",
13067     __FILE__, VAnimation, group);
13068
13069   theCommands.Add("vanim",
13070             "List existing animations:"
13071     "\n\t\t:  vanim"
13072     "\n\t\t: Animation playback:"
13073     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
13074     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
13075     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
13076     "\n\t\t:   -freeLook skip camera animations"
13077     "\n\t\t:   -lockLoop disable any interactions"
13078     "\n\t\t:"
13079     "\n\t\t: Animation definition:"
13080     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
13081     "\n\t\t:        [start TimeSec] [duration TimeSec]"
13082     "\n\t\t:"
13083     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
13084     "\n\t\t: specifies nested animations."
13085     "\n\t\t: There is no syntax to explicitly add new animation,"
13086     "\n\t\t: and all non-existing animations within the name will be"
13087     "\n\t\t: implicitly created on first use (including parents)."
13088     "\n\t\t:"
13089     "\n\t\t: Each animation might define the SINGLE action (see below),"
13090     "\n\t\t: like camera transition, object transformation or custom callback."
13091     "\n\t\t: Child animations can be used for defining concurrent actions."
13092     "\n\t\t:"
13093     "\n\t\t: Camera animation:"
13094     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
13095     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
13096     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
13097     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
13098     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
13099     "\n\t\t:   -atX    camera Center positions pair"
13100     "\n\t\t:   -upX    camera Up directions pair"
13101     "\n\t\t:   -scaleX camera Scale factors pair"
13102     "\n\t\t: Object animation:"
13103     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
13104     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
13105     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
13106     "\n\t\t:   -locX   object Location points pair (translation)"
13107     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
13108     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
13109     "\n\t\t: Custom callback:"
13110     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
13111     "\n\t\t:   %Pts        overall animation presentation timestamp"
13112     "\n\t\t:   %LocalPts   local animation timestamp"
13113     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
13114     "\n\t\t:"
13115     "\n\t\t: Video recording:"
13116     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
13117     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
13118     "\n\t\t:             [-crf Value] [-preset Preset]"
13119     "\n\t\t:   -fps     video framerate"
13120     "\n\t\t:   -format  file format, container (matroska, etc.)"
13121     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
13122     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
13123     "\n\t\t:   -crf     constant rate factor (specific to codec)"
13124     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
13125     __FILE__, VAnimation, group);
13126
13127   theCommands.Add("vchangeselected",
13128     "vchangeselected shape"
13129     "- adds to shape to selection or remove one from it",
13130                 __FILE__, VChangeSelected, group);
13131   theCommands.Add ("vnbselected",
13132     "vnbselected"
13133     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
13134   theCommands.Add ("vcamera",
13135               "vcamera [PrsName] [-ortho] [-projtype]"
13136       "\n\t\t:         [-persp]"
13137       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
13138       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
13139       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
13140       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
13141       "\n\t\t: Manages camera parameters."
13142       "\n\t\t: Displays frustum when presntation name PrsName is specified."
13143       "\n\t\t: Prints current value when option called without argument."
13144       "\n\t\t: Orthographic camera:"
13145       "\n\t\t:   -ortho      activate orthographic projection"
13146       "\n\t\t: Perspective camera:"
13147       "\n\t\t:   -persp      activate perspective  projection (mono)"
13148       "\n\t\t:   -fovy       field of view in y axis, in degrees"
13149       "\n\t\t:   -distance   distance of eye from camera center"
13150       "\n\t\t: Stereoscopic camera:"
13151       "\n\t\t:   -stereo     perspective  projection (stereo)"
13152       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
13153       "\n\t\t:   -rightEye   perspective  projection (right eye)"
13154       "\n\t\t:   -iod        intraocular distance value"
13155       "\n\t\t:   -iodType    distance type, absolute or relative"
13156       "\n\t\t:   -zfocus     stereographic focus value"
13157       "\n\t\t:   -zfocusType focus type, absolute or relative",
13158     __FILE__, VCamera, group);
13159   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
13160     "- vautozfit [on={1|0}] [scale]\n"
13161     "    Prints or changes parameters of automatic z-fit mode:\n"
13162     "   \"on\" - turns automatic z-fit on or off\n"
13163     "   \"scale\" - specifies factor to scale computed z range.\n",
13164     __FILE__, VAutoZFit, group);
13165   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
13166     "   vzrange                - without parameters shows current values\n"
13167     "   vzrange [znear] [zfar] - applies provided values to view",
13168     __FILE__,VZRange, group);
13169   theCommands.Add ("vpurgedisplay",
13170     "vpurgedisplay"
13171     "- removes structures which don't belong to objects displayed in neutral point",
13172     __FILE__, VPurgeDisplay, group);
13173   theCommands.Add("vsetviewsize",
13174     "vsetviewsize size",
13175     __FILE__,VSetViewSize,group);
13176   theCommands.Add("vmoveview",
13177     "vmoveview Dx Dy Dz [Start = 1|0]",
13178     __FILE__,VMoveView,group);
13179   theCommands.Add("vtranslateview",
13180     "vtranslateview Dx Dy Dz [Start = 1|0)]",
13181     __FILE__,VTranslateView,group);
13182   theCommands.Add("vturnview",
13183     "vturnview Ax Ay Az [Start = 1|0]",
13184     __FILE__,VTurnView,group);
13185   theCommands.Add("vtextureenv",
13186     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
13187     "or user-defined file and optionally applying texture mapping parameters\n"
13188     "                  Usage:\n"
13189     "                  vtextureenv off - disables environment mapping\n"
13190     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
13191     "                              std_texture = (0..7)\n"
13192     "                              rep         = {clamp|repeat}\n"
13193     "                              mod         = {decal|modulate}\n"
13194     "                              flt         = {nearest|bilinear|trilinear}\n"
13195     "                              ss, st      - scale factors for s and t texture coordinates\n"
13196     "                              ts, tt      - translation for s and t texture coordinates\n"
13197     "                              rot         - texture rotation angle in degrees",
13198     __FILE__, VTextureEnv, group);
13199   theCommands.Add("vhlr",
13200             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
13201       "\n\t\t: Hidden Line Removal algorithm."
13202       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
13203       "\n\t\t:   -algoType   type of HLR algorithm.\n",
13204     __FILE__,VHLR,group);
13205   theCommands.Add("vhlrtype",
13206               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
13207       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
13208       "\n\t\t:   'algo' - exact HLR algorithm is applied"
13209       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
13210       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
13211     __FILE__,VHLRType,group);
13212   theCommands.Add("vclipplane",
13213               "vclipplane planeName [{0|1}]"
13214       "\n\t\t:   [-equation1 A B C D]"
13215       "\n\t\t:   [-equation2 A B C D]"
13216       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
13217       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
13218       "\n\t\t:   [-maxPlanes]"
13219       "\n\t\t:   [-capping {0|1}]"
13220       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
13221       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
13222       "\n\t\t:       [-texRotate Angle]"
13223       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
13224       "\n\t\t:       [-useObjShader {0|1}]"
13225       "\n\t\t: Clipping planes management:"
13226       "\n\t\t:   -maxPlanes   print plane limit for view"
13227       "\n\t\t:   -delete      delete plane with given name"
13228       "\n\t\t:   {off|on|0|1} turn clipping on/off"
13229       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
13230       "\n\t\t:                applied to active View when list is omitted"
13231       "\n\t\t:   -equation A B C D change plane equation"
13232       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
13233       "\n\t\t: Capping options:"
13234       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
13235       "\n\t\t:   -color R G B          set capping color"
13236       "\n\t\t:   -transparency Value   set capping transparency 0..1"
13237       "\n\t\t:   -texName Texture      set capping texture"
13238       "\n\t\t:   -texScale SX SY       set capping tex scale"
13239       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
13240       "\n\t\t:   -texRotate Angle      set capping tex rotation"
13241       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
13242       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
13243       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
13244       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
13245       __FILE__, VClipPlane, group);
13246   theCommands.Add("vdefaults",
13247                "vdefaults [-absDefl value]"
13248        "\n\t\t:           [-devCoeff value]"
13249        "\n\t\t:           [-angDefl value]"
13250        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
13251     , __FILE__, VDefaults, group);
13252   theCommands.Add("vlight",
13253     "tool to manage light sources, without arguments shows list of lights."
13254     "\n    Main commands: "
13255     "\n      '-clear' to clear lights"
13256     "\n      '-{def}aults' to load deafault lights"
13257     "\n      '-add' <type> to add any light source"
13258     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
13259     "\n      'change' <lightId> to edit light source with specified lightId"
13260     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
13261     "\n        -layer Id"
13262     "\n        -{pos}ition X Y Z"
13263     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
13264     "\n        -color colorName"
13265     "\n        -{head}light 0|1"
13266     "\n        -{sm}oothness value"
13267     "\n        -{int}ensity value"
13268     "\n        -{constAtten}uation value"
13269     "\n        -{linearAtten}uation value"
13270     "\n        -angle angleDeg"
13271     "\n        -{spotexp}onent value"
13272     "\n        -local|-global"
13273     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
13274     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
13275     __FILE__, VLight, group);
13276   theCommands.Add("vraytrace",
13277             "vraytrace [0|1]"
13278     "\n\t\t: Turns on/off ray-tracing renderer."
13279     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
13280     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
13281     __FILE__, VRenderParams, group);
13282   theCommands.Add("vrenderparams",
13283     "\n    Manages rendering parameters: "
13284     "\n      '-raster'                   Disables GPU ray-tracing"
13285     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
13286     "\n      '-lineFeather  > 0'         Sets line feather factor"
13287     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
13288     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
13289     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
13290     "\n      '-rendScale    value        Rendering resolution scale factor"
13291     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
13292     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
13293     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
13294     "\n      '-reflections  on|off'      Enables/disables specular reflections"
13295     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
13296     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
13297     "\n      '-gi           on|off'      Enables/disables global illumination effects"
13298     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
13299     "\n      '-env          on|off'      Enables/disables environment map background"
13300     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
13301     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
13302     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
13303     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
13304     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
13305     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
13306     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
13307     "\n      '-shadingModel model'       Controls shading model from enumeration"
13308     "\n                                  color, flat, gouraud, phong"
13309     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
13310     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
13311     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
13312     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
13313     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
13314     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
13315     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
13316     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
13317     "\n                                  Show/hide performance counters (flags can be combined)"
13318     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
13319     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
13320     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
13321     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
13322     "\n                                        set state to check structures culled previously."
13323     "\n    Unlike vcaps, these parameters dramatically change visual properties."
13324     "\n    Command is intended to control presentation quality depending on"
13325     "\n    hardware capabilities and performance.",
13326     __FILE__, VRenderParams, group);
13327   theCommands.Add("vstatprofiler",
13328     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
13329     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
13330     "\n                |triagles|points|geomMem|textureMem|frameMem"
13331     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
13332     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
13333     "\n                [-noredraw]"
13334     "\n\t\t: Prints rendering statistics."
13335     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
13336     "\n\t\t:   else - print all performance counters set previously."
13337     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
13338     __FILE__, VStatProfiler, group);
13339   theCommands.Add ("vplace",
13340             "vplace dx dy"
13341     "\n\t\t: Places the point (in pixels) at the center of the window",
13342     __FILE__, VPlace, group);
13343   theCommands.Add("vxrotate",
13344     "vxrotate",
13345     __FILE__,VXRotate,group);
13346
13347     theCommands.Add("vmanipulator",
13348       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
13349       "\n    tool to create and manage AIS manipulators."
13350       "\n    Options: "
13351       "\n      '-attach AISObject'                 attach manipulator to AISObject"
13352       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
13353       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
13354       "\n      '-enableModes    {0|1}'             enable modes when attaching"
13355       "\n      '-detach'                           detach manipulator"
13356       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
13357       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
13358       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
13359       "\n      '-move x y z'                     - move attached object"
13360       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
13361       "\n      '-scale factor'                   - scale attached object"
13362       "\n      '-autoActivate      {0|1}'        - set activation on detection"
13363       "\n      '-followTranslation {0|1}'        - set following translation transform"
13364       "\n      '-followRotation    {0|1}'        - set following rotation transform"
13365       "\n      '-followDragging    {0|1}'        - set following dragging transform"
13366       "\n      '-gap value'                      - set gap between sub-parts"
13367       "\n      '-part axis mode    {0|1}'        - set visual part"
13368       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
13369       "\n      '-size value'                     - set size of manipulator"
13370       "\n      '-zoomable {0|1}'                 - set zoom persistence",
13371     __FILE__, VManipulator, group);
13372
13373   theCommands.Add("vselprops",
13374     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
13375     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
13376     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
13377     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
13378     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
13379     "\n    -pickStrategy {first|topmost} : defines picking strategy"
13380     "\n                            'first'   to pick first acceptable (default)"
13381     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
13382     "\n    -pixTol    value        : sets up pixel tolerance"
13383     "\n    -dispMode  dispMode     : sets display mode for highlighting"
13384     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
13385     "\n    -color     {name|r g b} : sets highlight color"
13386     "\n    -transp    value        : sets transparency coefficient for highlight"
13387     "\n    -material  material     : sets highlight material"
13388     "\n    -print                  : prints current state of all mentioned parameters",
13389     __FILE__, VSelectionProperties, group);
13390   theCommands.Add ("vhighlightselected",
13391                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
13392                    __FILE__, VSelectionProperties, group);
13393
13394   theCommands.Add ("vseldump",
13395                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
13396                    "\n\t\t: Generate an image based on detection results:"
13397                    "\n\t\t:   depth       normalized depth values"
13398                    "\n\t\t:   unnormDepth unnormalized depth values"
13399                    "\n\t\t:   object      color of detected object"
13400                    "\n\t\t:   owner       color of detected owner"
13401                    "\n\t\t:   selMode     color of selection mode"
13402                    "\n\t\t:   entity      color of etected entity",
13403                    __FILE__, VDumpSelectionImage, group);
13404
13405 #if defined(_WIN32)
13406   theCommands.Add("vprogressive",
13407     "vprogressive",
13408     __FILE__, VProgressiveMode, group);
13409 #endif
13410 }