0030523: Visualization - Highlighting does not work anymore
[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_Timer.hxx>
63 #include <TColStd_HSequenceOfAsciiString.hxx>
64 #include <TColStd_SequenceOfInteger.hxx>
65 #include <TColStd_HSequenceOfReal.hxx>
66 #include <TColgp_Array1OfPnt2d.hxx>
67 #include <TColStd_MapOfAsciiString.hxx>
68 #include <Aspect_TypeOfLine.hxx>
69 #include <Image_Diff.hxx>
70 #include <Aspect_DisplayConnection.hxx>
71 #include <gp_Pnt.hxx>
72 #include <gp_Dir.hxx>
73 #include <gp_Pln.hxx>
74 #include <PrsMgr_PresentableObject.hxx>
75 #include <Graphic3d_ClipPlane.hxx>
76 #include <NCollection_DataMap.hxx>
77 #include <Graphic3d_Texture2Dmanual.hxx>
78 #include <Prs3d_ShadingAspect.hxx>
79 #include <Prs3d_Drawer.hxx>
80 #include <Prs3d_LineAspect.hxx>
81 #include <Prs3d_Root.hxx>
82 #include <Prs3d_Text.hxx>
83 #include <Select3D_SensitivePrimitiveArray.hxx>
84
85 #ifdef _WIN32
86 #undef DrawText
87 #endif
88
89 #include <cstdlib>
90
91 #if defined(_WIN32)
92   #include <WNT_WClass.hxx>
93   #include <WNT_Window.hxx>
94 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
95   #include <Cocoa_Window.hxx>
96 #else
97   #include <Xw_Window.hxx>
98   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
99   #include <X11/Xutil.h>
100   #include <tk.h>
101 #endif
102
103 // Auxiliary definitions
104 static const char THE_KEY_DELETE = 127;
105 static const char THE_KEY_ESCAPE = 27;
106
107 //==============================================================================
108 //  VIEWER GLOBAL VARIABLES
109 //==============================================================================
110
111 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
112 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
113
114 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
115 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
116
117 extern int VErase (Draw_Interpretor& theDI,
118                    Standard_Integer  theArgNb,
119                    const char**      theArgVec);
120
121 #if defined(_WIN32)
122 static Handle(WNT_Window)& VT_GetWindow() {
123   static Handle(WNT_Window) WNTWin;
124   return WNTWin;
125 }
126 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
127 static Handle(Cocoa_Window)& VT_GetWindow()
128 {
129   static Handle(Cocoa_Window) aWindow;
130   return aWindow;
131 }
132 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
133 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
134 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
135
136 #else
137 static Handle(Xw_Window)& VT_GetWindow(){
138   static Handle(Xw_Window) XWWin;
139   return XWWin;
140 }
141
142 static void VProcessEvents(ClientData,int);
143 #endif
144
145 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
146 {
147   static Handle(Aspect_DisplayConnection) aDisplayConnection;
148   return aDisplayConnection;
149 }
150
151 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
152 {
153   GetDisplayConnection() = theDisplayConnection;
154 }
155
156 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
157 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
158 {
159   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
160 #if defined(_WIN32)
161   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
162   if (!aWindow.IsNull())
163     return aWindow->HWindow();
164 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
165   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
166   if (!aWindow.IsNull())
167   return aWindow->XWindow();
168 #endif
169   return aWindowHandle;
170 }
171 #endif
172
173 //! Setting additional flag to store 2D mode of the View to avoid scene rotation by mouse/key events
174 class ViewerTest_V3dView : public V3d_View
175 {
176   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_V3dView, V3d_View)
177 public:
178   //! Initializes the view.
179   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType = V3d_ORTHOGRAPHIC,
180                       bool theIs2dMode = false)
181   : V3d_View (theViewer, theType), myIs2dMode (theIs2dMode) {}
182
183   //! Initializes the view by copying.
184   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
185   : V3d_View (theViewer, theView), myIs2dMode (false)
186   {
187     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (theView))
188     {
189       myIs2dMode = aV3dView->IsViewIn2DMode();
190     }
191   }
192
193   //! Returns true if 2D mode is set for the view
194   bool IsViewIn2DMode() const { return myIs2dMode; }
195
196   //! Sets 2D mode for the view
197   void SetView2DMode (bool the2dMode) { myIs2dMode = the2dMode; }
198
199 public:
200
201   //! Returns true if active view in 2D mode.
202   static bool IsCurrentViewIn2DMode()
203   {
204     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
205     {
206       return aV3dView->IsViewIn2DMode();
207     }
208     return false;
209   }
210
211   //! Set if active view in 2D mode.
212   static void SetCurrentView2DMode (bool theIs2d)
213   {
214     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
215     {
216       aV3dView->SetView2DMode (theIs2d);
217     }
218   }
219
220 private:
221
222   Standard_Boolean myIs2dMode; //!< 2D mode flag
223
224 };
225
226 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
227 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
228 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
229 static OpenGl_Caps ViewerTest_myDefaultCaps;
230
231 static void OSWindowSetup();
232
233 static struct
234 {
235   Quantity_Color FlatColor;
236   Quantity_Color GradientColor1;
237   Quantity_Color GradientColor2;
238   Aspect_GradientFillMethod FillMethod;
239 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
240
241 //==============================================================================
242 //  EVENT GLOBAL VARIABLES
243 //==============================================================================
244
245 static int Start_Rot = 0;
246 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
247 int X_Motion = 0; // Current cursor position
248 int Y_Motion = 0;
249 int X_ButtonPress = 0; // Last ButtonPress position
250 int Y_ButtonPress = 0;
251 Standard_Boolean IsDragged = Standard_False;
252 Standard_Boolean DragFirst = Standard_False;
253 Standard_Boolean TheIsAnimating = Standard_False;
254 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
255 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
256
257
258 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
259 {
260   static Handle(AIS_RubberBand) aBand;
261   if (aBand.IsNull())
262   {
263     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
264     aBand->SetDisplayMode (0);
265   }
266   return aBand;
267 }
268
269 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
270
271 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
272 {
273   static ViewerTest_MapOfAISManipulators aMap;
274   return aMap;
275 }
276
277 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
278 {
279   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
280   for (; anIt.More(); anIt.Next())
281   {
282     if (anIt.Value()->HasActiveMode())
283     {
284       return anIt.Value();
285     }
286   }
287   return NULL;
288 }
289
290 //==============================================================================
291
292 #ifdef _WIN32
293 static LRESULT WINAPI ViewerWindowProc(
294                                        HWND hwnd,
295                                        UINT uMsg,
296                                        WPARAM wParam,
297                                        LPARAM lParam );
298 static LRESULT WINAPI AdvViewerWindowProc(
299   HWND hwnd,
300   UINT uMsg,
301   WPARAM wParam,
302   LPARAM lParam );
303 #endif
304
305
306 //==============================================================================
307 //function : WClass
308 //purpose  :
309 //==============================================================================
310
311 const Handle(Standard_Transient)& ViewerTest::WClass()
312 {
313   static Handle(Standard_Transient) theWClass;
314 #if defined(_WIN32)
315   if (theWClass.IsNull())
316   {
317     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
318                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
319                                 ::LoadCursor (NULL, IDC_ARROW));
320   }
321 #endif
322   return theWClass;
323 }
324
325 //==============================================================================
326 //function : CreateName
327 //purpose  : Create numerical name for new object in theMap
328 //==============================================================================
329 template <typename ObjectType>
330 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
331                                     const TCollection_AsciiString& theDefaultString)
332 {
333   if (theObjectMap.IsEmpty())
334     return theDefaultString + TCollection_AsciiString(1);
335
336   Standard_Integer aNextKey = 1;
337   Standard_Boolean isFound = Standard_False;
338   while (!isFound)
339   {
340     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
341     // Look for objects with default names
342     if (theObjectMap.IsBound1(aStringKey))
343     {
344       aNextKey++;
345     }
346     else
347       isFound = Standard_True;
348   }
349
350   return theDefaultString + TCollection_AsciiString(aNextKey);
351 }
352
353 //==============================================================================
354 //structure : ViewerTest_Names
355 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
356 //==============================================================================
357 struct ViewerTest_Names
358 {
359 private:
360   TCollection_AsciiString myDriverName;
361   TCollection_AsciiString myViewerName;
362   TCollection_AsciiString myViewName;
363
364 public:
365
366   const TCollection_AsciiString& GetDriverName () const
367   {
368     return myDriverName;
369   }
370   void SetDriverName (const TCollection_AsciiString& theDriverName)
371   {
372     myDriverName = theDriverName;
373   }
374   const TCollection_AsciiString& GetViewerName () const
375   {
376     return myViewerName;
377   }
378   void SetViewerName (const TCollection_AsciiString& theViewerName)
379   {
380     myViewerName = theViewerName;
381   }
382   const TCollection_AsciiString& GetViewName () const
383   {
384     return myViewName;
385   }
386   void SetViewName (const TCollection_AsciiString& theViewName)
387   {
388     myViewName = theViewName;
389   }
390
391   //===========================================================================
392   //function : Constructor for ViewerTest_Names
393   //purpose  : Get view, viewer, driver names from custom string
394   //===========================================================================
395
396   ViewerTest_Names (const TCollection_AsciiString& theInputString)
397   {
398     TCollection_AsciiString aName(theInputString);
399     if (theInputString.IsEmpty())
400     {
401       // Get current configuration
402       if (ViewerTest_myDrivers.IsEmpty())
403         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
404           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
405       else
406         myDriverName = ViewerTest_myDrivers.Find2
407         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
408
409       if(ViewerTest_myContexts.IsEmpty())
410       {
411         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
412           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
413       }
414       else
415       {
416         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
417       }
418
419       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
420     }
421     else
422     {
423       // There is at least view name
424       Standard_Integer aParserNumber = 0;
425       for (Standard_Integer i = 0; i < 3; ++i)
426       {
427         Standard_Integer aParserPos = aName.SearchFromEnd("/");
428         if(aParserPos != -1)
429         {
430           aParserNumber++;
431           aName.Split(aParserPos-1);
432         }
433         else
434           break;
435       }
436       if (aParserNumber == 0)
437       {
438         // Only view name
439         if (!ViewerTest::GetAISContext().IsNull())
440         {
441           myDriverName = ViewerTest_myDrivers.Find2
442           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
443           myViewerName = ViewerTest_myContexts.Find2
444           (ViewerTest::GetAISContext());
445         }
446         else
447         {
448           // There is no opened contexts here, need to create names for viewer and driver
449           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
450             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
451
452           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
453             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
454         }
455         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
456       }
457       else if (aParserNumber == 1)
458       {
459         // Here is viewerName/viewName
460         if (!ViewerTest::GetAISContext().IsNull())
461           myDriverName = ViewerTest_myDrivers.Find2
462           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
463         else
464         {
465           // There is no opened contexts here, need to create name for driver
466           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
467             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
468         }
469         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
470
471         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
472       }
473       else
474       {
475         //Here is driverName/viewerName/viewName
476         myDriverName = TCollection_AsciiString(aName);
477
478         TCollection_AsciiString aViewerName(theInputString);
479         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
480         myViewerName = TCollection_AsciiString(aViewerName);
481
482         myViewName = TCollection_AsciiString(theInputString);
483       }
484     }
485   }
486 };
487
488 //==============================================================================
489 //function : FindContextByView
490 //purpose  : Find AIS_InteractiveContext by View
491 //==============================================================================
492
493 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
494 {
495   Handle(AIS_InteractiveContext) anAISContext;
496
497   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
498        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
499   {
500     if (anIter.Value()->CurrentViewer() == theView->Viewer())
501        return anIter.Key2();
502   }
503   return anAISContext;
504 }
505
506
507 //==============================================================================
508 //function : SetWindowTitle
509 //purpose  : Set window title
510 //==============================================================================
511
512 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
513                      Standard_CString theTitle)
514 {
515 #if defined(_WIN32)
516   const TCollection_ExtendedString theTitleW (theTitle);
517   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
518 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
519   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
520 #else
521   if(GetDisplayConnection()->GetDisplay())
522   {
523     Window aWindow =
524       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
525     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
526   }
527 #endif
528 }
529
530 //==============================================================================
531 //function : IsWindowOverlapped
532 //purpose  : Check if theWindow overlapp another view
533 //==============================================================================
534
535 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
536                                      const Standard_Integer thePxTop,
537                                      const Standard_Integer thePxRight,
538                                      const Standard_Integer thePxBottom,
539                                      TCollection_AsciiString& theViewId)
540 {
541   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
542       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
543   {
544     Standard_Integer aTop = 0,
545       aLeft = 0,
546       aRight = 0,
547       aBottom = 0;
548     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
549     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
550         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
551         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
552         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
553     {
554       theViewId = anIter.Key1();
555       return Standard_True;
556     }
557   }
558   return Standard_False;
559 }
560
561 // Workaround: to create and delete non-orthographic views outside ViewerTest
562 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
563 {
564   ViewerTest_myViews.UnBind1 (theName);
565 }
566
567 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
568                                const Handle(V3d_View)& theView)
569 {
570   ViewerTest_myViews.Bind (theName, theView);
571 }
572
573 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
574 {
575   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
576 }
577 //==============================================================================
578 //function : ViewerInit
579 //purpose  : Create the window viewer and initialize all the global variable
580 //==============================================================================
581
582 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
583                                                 const Standard_Integer thePxTop,
584                                                 const Standard_Integer thePxWidth,
585                                                 const Standard_Integer thePxHeight,
586                                                 const TCollection_AsciiString& theViewName,
587                                                 const TCollection_AsciiString& theDisplayName,
588                                                 const Handle(V3d_View)& theViewToClone)
589 {
590   // Default position and dimension of the viewer window.
591   // Note that left top corner is set to be sufficiently small to have
592   // window fit in the small screens (actual for remote desktops, see #23003).
593   // The position corresponds to the window's client area, thus some
594   // gap is added for window frame to be visible.
595   Standard_Integer aPxLeft   = 20;
596   Standard_Integer aPxTop    = 40;
597   Standard_Integer aPxWidth  = 409;
598   Standard_Integer aPxHeight = 409;
599   Standard_Boolean toCreateViewer = Standard_False;
600   if (!theViewToClone.IsNull())
601   {
602     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
603   }
604
605   Handle(OpenGl_GraphicDriver) aGraphicDriver;
606   ViewerTest_Names aViewNames(theViewName);
607   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
608     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
609
610   if (thePxLeft != 0)
611     aPxLeft = thePxLeft;
612   if (thePxTop != 0)
613     aPxTop = thePxTop;
614   if (thePxWidth != 0)
615     aPxWidth = thePxWidth;
616   if (thePxHeight != 0)
617     aPxHeight = thePxHeight;
618
619   // Get graphic driver (create it or get from another view)
620   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
621   {
622     // Get connection string
623   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
624     TCollection_AsciiString aDisplayName(theDisplayName);
625     if (!aDisplayName.IsEmpty())
626       SetDisplayConnection (new Aspect_DisplayConnection ());
627     else
628       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
629   #else
630     (void)theDisplayName; // avoid warning on unused argument
631     SetDisplayConnection (new Aspect_DisplayConnection ());
632   #endif
633
634     if (Draw_VirtualWindows)
635     {
636       // don't waste the time waiting for VSync when window is not displayed on the screen
637       ViewerTest_myDefaultCaps.swapInterval = 0;
638       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
639       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
640     }
641     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
642     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
643
644     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
645     toCreateViewer = Standard_True;
646   }
647   else
648   {
649     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
650   }
651
652   //Dispose the window if input parameters are default
653   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
654   {
655     Standard_Integer aTop = 0,
656                      aLeft = 0,
657                      aRight = 0,
658                      aBottom = 0,
659                      aScreenWidth = 0,
660                      aScreenHeight = 0;
661
662     // Get screen resolution
663 #if defined(_WIN32) || defined(__WIN32__)
664     RECT aWindowSize;
665     GetClientRect(GetDesktopWindow(), &aWindowSize);
666     aScreenHeight = aWindowSize.bottom;
667     aScreenWidth = aWindowSize.right;
668 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
669     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
670 #else
671     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
672     aScreenWidth = WidthOfScreen(aScreen);
673     aScreenHeight = HeightOfScreen(aScreen);
674 #endif
675
676     TCollection_AsciiString anOverlappedViewId("");
677
678     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
679     {
680       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
681
682       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
683         && aRight + 2*aPxWidth + 40 > aScreenWidth)
684       {
685         if (aBottom + aPxHeight + 40 > aScreenHeight)
686         {
687           aPxLeft = 20;
688           aPxTop = 40;
689           break;
690         }
691         aPxLeft = 20;
692         aPxTop = aBottom + 40;
693       }
694       else
695         aPxLeft = aRight + 20;
696     }
697   }
698
699   // Get viewer name
700   TCollection_AsciiString aTitle("3D View - ");
701   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
702
703   // Change name of current active window
704   if (!ViewerTest::CurrentView().IsNull())
705   {
706     TCollection_AsciiString anActiveWindowTitle("3D View - ");
707     anActiveWindowTitle = anActiveWindowTitle
708       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
709     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
710   }
711
712   // Create viewer
713   Handle(V3d_Viewer) a3DViewer;
714   // If it's the single view, we first look for empty context
715   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
716   {
717     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
718       anIter(ViewerTest_myContexts);
719     if (anIter.More())
720       ViewerTest::SetAISContext (anIter.Value());
721     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
722   }
723   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
724   {
725     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
726     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
727   }
728   else if (a3DViewer.IsNull())
729   {
730     toCreateViewer = Standard_True;
731     a3DViewer = new V3d_Viewer(aGraphicDriver);
732     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
733     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
734                                            ViewerTest_DefaultBackground.GradientColor2,
735                                            ViewerTest_DefaultBackground.FillMethod);
736   }
737
738   // AIS context setup
739   if (ViewerTest::GetAISContext().IsNull() ||
740       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
741   {
742     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
743     ViewerTest::SetAISContext (aContext);
744     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
745   }
746   else
747   {
748     ViewerTest::ResetEventManager();
749   }
750
751   // Create window
752 #if defined(_WIN32)
753   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
754                                     Handle(WNT_WClass)::DownCast (WClass()),
755                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
756                                     aPxLeft, aPxTop,
757                                     aPxWidth, aPxHeight,
758                                     Quantity_NOC_BLACK);
759 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
760   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
761                                      aPxLeft, aPxTop,
762                                      aPxWidth, aPxHeight);
763   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
764 #else
765   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
766                                   aTitle.ToCString(),
767                                   aPxLeft, aPxTop,
768                                   aPxWidth, aPxHeight);
769 #endif
770   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
771
772   // View setup
773   Handle(V3d_View) aView;
774   if (!theViewToClone.IsNull())
775   {
776     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
777   }
778   else
779   {
780     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
781   }
782
783   aView->SetWindow (VT_GetWindow());
784   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
785
786   ViewerTest::CurrentView(aView);
787   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
788
789   // Setup for X11 or NT
790   OSWindowSetup();
791
792   // Set parameters for V3d_View and V3d_Viewer
793   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
794   aV3dView->SetComputedMode(Standard_False);
795
796   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
797   if (toCreateViewer)
798   {
799     a3DViewer->SetDefaultLights();
800     a3DViewer->SetLightOn();
801   }
802
803   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
804   #if TCL_MAJOR_VERSION  < 8
805   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
806       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
807   #else
808   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
809       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
810   #endif
811   #endif
812
813   VT_GetWindow()->Map();
814
815   // Set the handle of created view in the event manager
816   ViewerTest::ResetEventManager();
817
818   ViewerTest::CurrentView()->Redraw();
819
820   aView.Nullify();
821   a3DViewer.Nullify();
822
823   return aViewNames.GetViewName();
824 }
825
826 //==============================================================================
827 //function : RedrawAllViews
828 //purpose  : Redraw all created views
829 //==============================================================================
830 void ViewerTest::RedrawAllViews()
831 {
832   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
833   for (; aViewIt.More(); aViewIt.Next())
834   {
835     const Handle(V3d_View)& aView = aViewIt.Key2();
836     aView->Redraw();
837   }
838 }
839
840 //==============================================================================
841 //function : Vinit
842 //purpose  : Create the window viewer and initialize all the global variable
843 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
844 //==============================================================================
845
846 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
847 {
848   TCollection_AsciiString aViewName, aDisplayName;
849   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
850   Handle(V3d_View) aCopyFrom;
851   TCollection_AsciiString aName, aValue;
852   int is2dMode = -1;
853   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
854   {
855     const TCollection_AsciiString anArg = theArgVec[anArgIt];
856     TCollection_AsciiString anArgCase = anArg;
857     anArgCase.LowerCase();
858     if (anArgIt + 1 < theArgsNb
859      && anArgCase == "-name")
860     {
861       aViewName = theArgVec[++anArgIt];
862     }
863     else if (anArgIt + 1 < theArgsNb
864           && (anArgCase == "-left"
865            || anArgCase == "-l"))
866     {
867       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
868     }
869     else if (anArgIt + 1 < theArgsNb
870           && (anArgCase == "-top"
871            || anArgCase == "-t"))
872     {
873       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
874     }
875     else if (anArgIt + 1 < theArgsNb
876           && (anArgCase == "-width"
877            || anArgCase == "-w"))
878     {
879       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
880     }
881     else if (anArgIt + 1 < theArgsNb
882           && (anArgCase == "-height"
883            || anArgCase == "-h"))
884     {
885       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
886     }
887     else if (anArgCase == "-exitonclose")
888     {
889       Draw_ToExitOnCloseView = true;
890       if (anArgIt + 1 < theArgsNb
891        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
892       {
893         ++anArgIt;
894       }
895     }
896     else if (anArgCase == "-closeonescape"
897           || anArgCase == "-closeonesc")
898     {
899       Draw_ToCloseViewOnEsc = true;
900       if (anArgIt + 1 < theArgsNb
901        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
902       {
903         ++anArgIt;
904       }
905     }
906     else if (anArgCase == "-2d_mode"
907           || anArgCase == "-2dmode"
908           || anArgCase == "-2d")
909     {
910       bool toEnable = true;
911       if (anArgIt + 1 < theArgsNb
912        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
913       {
914         ++anArgIt;
915       }
916       is2dMode = toEnable ? 1 : 0;
917     }
918     else if (anArgIt + 1 < theArgsNb
919           && (anArgCase == "-disp"
920            || anArgCase == "-display"))
921     {
922       aDisplayName = theArgVec[++anArgIt];
923     }
924     else if (!ViewerTest::CurrentView().IsNull()
925           &&  aCopyFrom.IsNull()
926           && (anArgCase == "-copy"
927            || anArgCase == "-clone"
928            || anArgCase == "-cloneactive"
929            || anArgCase == "-cloneactiveview"))
930     {
931       aCopyFrom = ViewerTest::CurrentView();
932     }
933     // old syntax
934     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
935     {
936       aName.LowerCase();
937       if (aName == "name")
938       {
939         aViewName = aValue;
940       }
941       else if (aName == "l"
942             || aName == "left")
943       {
944         aPxLeft = aValue.IntegerValue();
945       }
946       else if (aName == "t"
947             || aName == "top")
948       {
949         aPxTop = aValue.IntegerValue();
950       }
951       else if (aName == "disp"
952             || aName == "display")
953       {
954         aDisplayName = aValue;
955       }
956       else if (aName == "w"
957             || aName == "width")
958       {
959         aPxWidth = aValue.IntegerValue();
960       }
961       else if (aName == "h"
962             || aName == "height")
963       {
964         aPxHeight = aValue.IntegerValue();
965       }
966       else
967       {
968         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
969         return 1;
970       }
971     }
972     else if (aViewName.IsEmpty())
973     {
974       aViewName = anArg;
975     }
976     else
977     {
978       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
979       return 1;
980     }
981   }
982
983 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
984   if (!aDisplayName.IsEmpty())
985   {
986     aDisplayName.Clear();
987     std::cout << "Warning: display parameter will be ignored.\n";
988   }
989 #endif
990
991   ViewerTest_Names aViewNames (aViewName);
992   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
993   {
994     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
995     theDi.Eval (aCommand.ToCString());
996     if (is2dMode != -1)
997     {
998       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
999     }
1000     return 0;
1001   }
1002
1003   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
1004                                                             aViewName, aDisplayName, aCopyFrom);
1005   if (is2dMode != -1)
1006   {
1007     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1008   }
1009   theDi << aViewId;
1010   return 0;
1011 }
1012
1013 //! Parse HLR algo type.
1014 static Standard_Boolean parseHlrAlgoType (const char* theName,
1015                                           Prs3d_TypeOfHLR& theType)
1016 {
1017   TCollection_AsciiString aName (theName);
1018   aName.LowerCase();
1019   if (aName == "polyalgo")
1020   {
1021     theType = Prs3d_TOH_PolyAlgo;
1022   }
1023   else if (aName == "algo")
1024   {
1025     theType = Prs3d_TOH_Algo;
1026   }
1027   else
1028   {
1029     return Standard_False;
1030   }
1031   return Standard_True;
1032 }
1033
1034 //==============================================================================
1035 //function : VHLR
1036 //purpose  : hidden lines removal algorithm
1037 //==============================================================================
1038
1039 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1040 {
1041   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1042   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1043   if (aView.IsNull())
1044   {
1045     std::cerr << "Error: No opened viewer!\n";
1046     return 1;
1047   }
1048
1049   Standard_Boolean hasHlrOnArg = Standard_False;
1050   Standard_Boolean hasShowHiddenArg = Standard_False;
1051   Standard_Boolean isHLROn = Standard_False;
1052   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
1053   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
1054   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1055   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1056   {
1057     TCollection_AsciiString anArg (argv[anArgIter]);
1058     anArg.LowerCase();
1059     if (anUpdateTool.parseRedrawMode (anArg))
1060     {
1061       continue;
1062     }
1063     else if (anArg == "-showhidden"
1064           && anArgIter + 1 < argc
1065           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
1066     {
1067       ++anArgIter;
1068       hasShowHiddenArg = Standard_True;
1069       continue;
1070     }
1071     else if ((anArg == "-type"
1072            || anArg == "-algo"
1073            || anArg == "-algotype")
1074           && anArgIter + 1 < argc
1075           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1076     {
1077       ++anArgIter;
1078       continue;
1079     }
1080     else if (!hasHlrOnArg
1081           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
1082     {
1083       hasHlrOnArg = Standard_True;
1084       continue;
1085     }
1086     // old syntax
1087     else if (!hasShowHiddenArg
1088           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
1089     {
1090       hasShowHiddenArg = Standard_True;
1091       continue;
1092     }
1093     else
1094     {
1095       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
1096       return 1;
1097     }
1098   }
1099   if (!hasHlrOnArg)
1100   {
1101     di << "HLR:        " << aView->ComputedMode() << "\n";
1102     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1103     di << "HlrAlgo:    ";
1104     switch (aCtx->DefaultDrawer()->TypeOfHLR())
1105     {
1106       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
1107       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1108       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
1109     }
1110     anUpdateTool.Invalidate();
1111     return 0;
1112   }
1113
1114   Standard_Boolean toRecompute = Standard_False;
1115   if (aTypeOfHLR != Prs3d_TOH_NotSet
1116    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
1117   {
1118     toRecompute = Standard_True;
1119     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1120   }
1121   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1122   {
1123     toRecompute = Standard_True;
1124     if (toShowHidden)
1125     {
1126       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
1127     }
1128     else
1129     {
1130       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
1131     }
1132   }
1133
1134   // redisplay shapes
1135   if (aView->ComputedMode() && isHLROn && toRecompute)
1136   {
1137     AIS_ListOfInteractive aListOfShapes;
1138     aCtx->DisplayedObjects (aListOfShapes);
1139     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
1140     {
1141       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
1142       {
1143         aCtx->Redisplay (aShape, Standard_False);
1144       }
1145     }
1146   }
1147
1148   aView->SetComputedMode (isHLROn);
1149   return 0;
1150 }
1151
1152 //==============================================================================
1153 //function : VHLRType
1154 //purpose  : change type of using HLR algorithm
1155 //==============================================================================
1156
1157 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1158 {
1159   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1160   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1161   if (aView.IsNull())
1162   {
1163     std::cerr << "Error: No opened viewer!\n";
1164     return 1;
1165   }
1166
1167   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1168   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1169   AIS_ListOfInteractive aListOfShapes;
1170   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1171   {
1172     TCollection_AsciiString anArg (argv[anArgIter]);
1173     anArg.LowerCase();
1174     if (anUpdateTool.parseRedrawMode (anArg))
1175     {
1176       continue;
1177     }
1178     else if ((anArg == "-type"
1179            || anArg == "-algo"
1180            || anArg == "-algotype")
1181           && anArgIter + 1 < argc
1182           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1183     {
1184       ++anArgIter;
1185       continue;
1186     }
1187     // old syntax
1188     else if (aTypeOfHLR == Prs3d_TOH_NotSet
1189           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1190     {
1191       continue;
1192     }
1193     else
1194     {
1195       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1196       TCollection_AsciiString aName (argv[anArgIter]);
1197       if (!aMap.IsBound2 (aName))
1198       {
1199         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
1200         return 1;
1201       }
1202
1203       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1204       if (aShape.IsNull())
1205       {
1206         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
1207         return 1;
1208       }
1209       aListOfShapes.Append (aShape);
1210       continue;
1211     }
1212   }
1213   if (aTypeOfHLR == Prs3d_TOH_NotSet)
1214   {
1215     std::cout << "Syntax error: wrong number of arguments!\n";
1216     return 1;
1217   }
1218
1219   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1220   if (isGlobal)
1221   {
1222     aCtx->DisplayedObjects (aListOfShapes);
1223     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1224   }
1225
1226   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1227   {
1228     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1229     if (aShape.IsNull())
1230     {
1231       continue;
1232     }
1233
1234     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1235                             && aView->ComputedMode();
1236     if (!isGlobal
1237      || aShape->TypeOfHLR() != aTypeOfHLR)
1238     {
1239       aShape->SetTypeOfHLR (aTypeOfHLR);
1240     }
1241     if (toUpdateShape)
1242     {
1243       aCtx->Redisplay (aShape, Standard_False);
1244     }
1245   }
1246   return 0;
1247 }
1248
1249 //==============================================================================
1250 //function : FindViewIdByWindowHandle
1251 //purpose  : Find theView Id in the map of views by window handle
1252 //==============================================================================
1253 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1254 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1255 {
1256   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1257        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1258   {
1259     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1260     if (aWindowHandle == theWindowHandle)
1261       return anIter.Key1();
1262   }
1263   return TCollection_AsciiString("");
1264 }
1265 #endif
1266
1267 //! Make the view active
1268 void ActivateView (const TCollection_AsciiString& theViewName,
1269                    Standard_Boolean theToUpdate = Standard_True)
1270 {
1271   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1272   if (aView.IsNull())
1273   {
1274     return;
1275   }
1276
1277   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1278   if (!anAISContext.IsNull())
1279   {
1280     if (!ViewerTest::CurrentView().IsNull())
1281     {
1282       TCollection_AsciiString aTitle("3D View - ");
1283       aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1284       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1285     }
1286
1287     ViewerTest::CurrentView (aView);
1288     ViewerTest::SetAISContext (anAISContext);
1289     TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
1290     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1291 #if defined(_WIN32)
1292     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1293 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1294     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1295 #else
1296     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1297 #endif
1298     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1299     if (theToUpdate)
1300     {
1301       ViewerTest::CurrentView()->Redraw();
1302     }
1303   }
1304 }
1305
1306 //==============================================================================
1307 //function : RemoveView
1308 //purpose  :
1309 //==============================================================================
1310 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1311                              const Standard_Boolean  theToRemoveContext)
1312 {
1313   if (!ViewerTest_myViews.IsBound2 (theView))
1314   {
1315     return;
1316   }
1317
1318   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1319   RemoveView (aViewName, theToRemoveContext);
1320 }
1321
1322 //==============================================================================
1323 //function : RemoveView
1324 //purpose  : Close and remove view from display, clear maps if neccessary
1325 //==============================================================================
1326 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1327 {
1328   if (!ViewerTest_myViews.IsBound1(theViewName))
1329   {
1330     cout << "Wrong view name\n";
1331     return;
1332   }
1333
1334   // Activate another view if it's active now
1335   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1336   {
1337     if (ViewerTest_myViews.Extent() > 1)
1338     {
1339       TCollection_AsciiString aNewViewName;
1340       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1341            anIter.More(); anIter.Next())
1342       {
1343         if (anIter.Key1() != theViewName)
1344         {
1345           aNewViewName = anIter.Key1();
1346           break;
1347         }
1348       }
1349       ActivateView (aNewViewName);
1350     }
1351     else
1352     {
1353       VT_GetWindow().Nullify();
1354       ViewerTest::CurrentView (Handle(V3d_View)());
1355       if (isContextRemoved)
1356       {
1357         Handle(AIS_InteractiveContext) anEmptyContext;
1358         ViewerTest::SetAISContext(anEmptyContext);
1359       }
1360     }
1361   }
1362
1363   // Delete view
1364   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1365   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1366
1367   // Remove view resources
1368   ViewerTest_myViews.UnBind1(theViewName);
1369   aView->Window()->Unmap();
1370   aView->Remove();
1371
1372 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1373   XFlush (GetDisplayConnection()->GetDisplay());
1374 #endif
1375
1376   // Keep context opened only if the closed view is last to avoid
1377   // unused empty contexts
1378   if (!aCurrentContext.IsNull())
1379   {
1380     // Check if there are more difined views in the viewer
1381     aCurrentContext->CurrentViewer()->InitDefinedViews();
1382     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1383     {
1384       // Remove driver if there is no viewers that use it
1385       Standard_Boolean isRemoveDriver = Standard_True;
1386       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1387           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1388       {
1389         if (aCurrentContext != anIter.Key2() &&
1390           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1391         {
1392           isRemoveDriver = Standard_False;
1393           break;
1394         }
1395       }
1396
1397       aCurrentContext->RemoveAll (Standard_False);
1398       if(isRemoveDriver)
1399       {
1400         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1401       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1402         #if TCL_MAJOR_VERSION  < 8
1403         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1404         #else
1405         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1406         #endif
1407       #endif
1408       }
1409
1410       ViewerTest_myContexts.UnBind2(aCurrentContext);
1411     }
1412   }
1413   cout << "3D View - " << theViewName << " was deleted.\n";
1414   if (Draw_ToExitOnCloseView)
1415   {
1416     Draw_Interprete ("exit");
1417   }
1418 }
1419
1420 //==============================================================================
1421 //function : VClose
1422 //purpose  : Remove the view defined by its name
1423 //==============================================================================
1424
1425 static int VClose (Draw_Interpretor& /*theDi*/,
1426                    Standard_Integer  theArgsNb,
1427                    const char**      theArgVec)
1428 {
1429   NCollection_List<TCollection_AsciiString> aViewList;
1430   if (theArgsNb > 1)
1431   {
1432     TCollection_AsciiString anArg (theArgVec[1]);
1433     anArg.UpperCase();
1434     if (anArg.IsEqual ("ALL")
1435      || anArg.IsEqual ("*"))
1436     {
1437       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1438            anIter.More(); anIter.Next())
1439       {
1440         aViewList.Append (anIter.Key1());
1441       }
1442       if (aViewList.IsEmpty())
1443       {
1444         std::cout << "No view to close\n";
1445         return 0;
1446       }
1447     }
1448     else
1449     {
1450       ViewerTest_Names aViewName (theArgVec[1]);
1451       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1452       {
1453         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1454         return 1;
1455       }
1456       aViewList.Append (aViewName.GetViewName());
1457     }
1458   }
1459   else
1460   {
1461     // close active view
1462     if (ViewerTest::CurrentView().IsNull())
1463     {
1464       std::cerr << "No active view!\n";
1465       return 1;
1466     }
1467     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1468   }
1469
1470   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1471   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1472        anIter.More(); anIter.Next())
1473   {
1474     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1475   }
1476
1477   return 0;
1478 }
1479
1480 //==============================================================================
1481 //function : VActivate
1482 //purpose  : Activate the view defined by its ID
1483 //==============================================================================
1484
1485 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1486 {
1487   if (theArgsNb == 1)
1488   {
1489     theDi.Eval("vviewlist");
1490     return 0;
1491   }
1492
1493   TCollection_AsciiString aNameString;
1494   Standard_Boolean toUpdate = Standard_True;
1495   Standard_Boolean toActivate = Standard_True;
1496   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
1497   {
1498     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1499     anArg.LowerCase();
1500     if (toUpdate
1501      && anArg == "-noupdate")
1502     {
1503       toUpdate = Standard_False;
1504     }
1505     else if (toActivate
1506           && aNameString.IsEmpty()
1507           && anArg == "none")
1508     {
1509       TCollection_AsciiString aTitle("3D View - ");
1510       aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1511       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1512       VT_GetWindow().Nullify();
1513       ViewerTest::CurrentView (Handle(V3d_View)());
1514       ViewerTest::ResetEventManager();
1515       theDi << theArgVec[0] << ": all views are inactive\n";
1516       toActivate = Standard_False;
1517     }
1518     else if (toActivate
1519           && aNameString.IsEmpty())
1520     {
1521       aNameString = theArgVec[anArgIter];
1522     }
1523     else
1524     {
1525       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
1526       return 1;
1527     }
1528   }
1529
1530   if (!toActivate)
1531   {
1532     return 0;
1533   }
1534   else if (aNameString.IsEmpty())
1535   {
1536     std::cout << "Syntax error: wrong number of arguments\n";
1537     return 1;
1538   }
1539
1540   // Check if this view exists in the viewer with the driver
1541   ViewerTest_Names aViewNames (aNameString);
1542   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1543   {
1544     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
1545     return 1;
1546   }
1547
1548   // Check if it is active already
1549   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1550   {
1551     theDi << theArgVec[0] << ": the view is active already\n";
1552     return 0;
1553   }
1554
1555   ActivateView (aViewNames.GetViewName(), toUpdate);
1556   return 0;
1557 }
1558
1559 //==============================================================================
1560 //function : VViewList
1561 //purpose  : Print current list of views per viewer and graphic driver ID
1562 //           shared between viewers
1563 //==============================================================================
1564
1565 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1566 {
1567   if (theArgsNb > 2)
1568   {
1569     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1570           << "Usage: " << theArgVec[0] << " name";
1571     return 1;
1572   }
1573   if (ViewerTest_myContexts.Size() < 1)
1574     return 0;
1575
1576   Standard_Boolean isTreeView =
1577     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1578
1579   if (isTreeView)
1580   {
1581     theDi << theArgVec[0] <<":\n";
1582   }
1583
1584   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1585        aDriverIter.More(); aDriverIter.Next())
1586   {
1587     if (isTreeView)
1588       theDi << aDriverIter.Key1() << ":\n";
1589
1590     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1591       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1592     {
1593       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1594       {
1595         if (isTreeView)
1596         {
1597           TCollection_AsciiString aContextName(aContextIter.Key1());
1598           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1599         }
1600
1601         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1602              aViewIter.More(); aViewIter.Next())
1603         {
1604           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1605           {
1606             TCollection_AsciiString aViewName(aViewIter.Key1());
1607             if (isTreeView)
1608             {
1609               if (aViewIter.Value() == ViewerTest::CurrentView())
1610                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1611               else
1612                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1613             }
1614             else
1615             {
1616               theDi << aViewName << " ";
1617             }
1618           }
1619         }
1620       }
1621     }
1622   }
1623   return 0;
1624 }
1625
1626 //==============================================================================
1627 //function : VT_ProcessKeyPress
1628 //purpose  : Handle KeyPress event from a CString
1629 //==============================================================================
1630 void VT_ProcessKeyPress (const char* buf_ret)
1631 {
1632   //cout << "KeyPress" << endl;
1633   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1634   // Letter in alphabetic order
1635
1636   if (!strcasecmp (buf_ret, "A")
1637    && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1638   {
1639     // AXO
1640     aView->SetProj(V3d_XposYnegZpos);
1641   }
1642   else if (!strcasecmp (buf_ret, "D")
1643         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1644   {
1645     // Reset
1646     aView->Reset();
1647   }
1648   else if (!strcasecmp (buf_ret, "F"))
1649   {
1650     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1651     {
1652       ViewerTest::GetAISContext()->FitSelected (aView);
1653     }
1654     else
1655     {
1656       // FitAll
1657       aView->FitAll();
1658     }
1659   }
1660   else if (!strcasecmp (buf_ret, "H"))
1661   {
1662     // HLR
1663     std::cout << "HLR" << std::endl;
1664     aView->SetComputedMode (!aView->ComputedMode());
1665     aView->Redraw();
1666   }
1667   else if (!strcasecmp (buf_ret, "P"))
1668   {
1669     // Type of HLR
1670     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1671     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1672       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1673     else
1674       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1675     if (aContext->NbSelected()==0)
1676     {
1677       AIS_ListOfInteractive aListOfShapes;
1678       aContext->DisplayedObjects(aListOfShapes);
1679       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1680         anIter.More(); anIter.Next())
1681       {
1682         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1683         if (aShape.IsNull())
1684           continue;
1685         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1686           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1687         else
1688           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1689         aContext->Redisplay (aShape, Standard_False);
1690       }
1691     }
1692     else
1693     {
1694       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1695       {
1696         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1697         if (aShape.IsNull())
1698           continue;
1699         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1700           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1701         else
1702           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1703         aContext->Redisplay (aShape, Standard_False);
1704       }
1705     }
1706
1707     aContext->UpdateCurrentViewer();
1708
1709   }
1710   else if (!strcasecmp (buf_ret, "S"))
1711   {
1712     std::cout << "setup Shaded display mode" << std::endl;
1713
1714     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1715     if(Ctx->NbSelected()==0)
1716       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1717     else{
1718       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1719         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1720       Ctx->UpdateCurrentViewer();
1721     }
1722   }
1723   else if (!strcasecmp (buf_ret, "U"))
1724   {
1725     // Unset display mode
1726     std::cout << "reset display mode to defaults" << std::endl;
1727
1728     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1729     if(Ctx->NbSelected()==0)
1730       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1731     else{
1732       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1733         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1734       Ctx->UpdateCurrentViewer();
1735     }
1736
1737   }
1738   else if (!strcasecmp (buf_ret, "T")
1739         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1740   {
1741     // Top
1742     aView->SetProj(V3d_Zpos);
1743   }
1744   else if (!strcasecmp (buf_ret, "B")
1745         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1746   {
1747     // Bottom
1748     aView->SetProj(V3d_Zneg);
1749   }
1750   else if (!strcasecmp (buf_ret, "L")
1751         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1752   {
1753     // Left
1754     aView->SetProj(V3d_Xneg);
1755   }
1756   else if (!strcasecmp (buf_ret, "R")
1757         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1758   {
1759     // Right
1760     aView->SetProj(V3d_Xpos);
1761   }
1762   else if (!strcasecmp (buf_ret, "W"))
1763   {
1764     std::cout << "setup WireFrame display mode" << std::endl;
1765     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1766     if(Ctx->NbSelected()==0)
1767       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1768     else{
1769       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1770         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1771       Ctx->UpdateCurrentViewer();
1772     }
1773   }
1774   else if (!strcasecmp (buf_ret, ","))
1775   {
1776     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1777   }
1778   else if (!strcasecmp (buf_ret, "."))
1779   {
1780     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1781   }
1782   else if (!strcasecmp (buf_ret, "/"))
1783   {
1784     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1785     if (aCamera->IsStereo())
1786     {
1787       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1788       aView->Redraw();
1789     }
1790   }
1791   else if (!strcasecmp (buf_ret, "*"))
1792   {
1793     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1794     if (aCamera->IsStereo())
1795     {
1796       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1797       aView->Redraw();
1798     }
1799   }
1800   else if (*buf_ret == THE_KEY_DELETE)
1801   {
1802     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1803     if (!aCtx.IsNull()
1804      && aCtx->NbSelected() > 0)
1805     {
1806       Draw_Interprete ("verase");
1807     }
1808   }
1809   else if (*buf_ret == THE_KEY_ESCAPE)
1810   {
1811     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1812     if (!aCtx.IsNull()
1813      && Draw_ToCloseViewOnEsc)
1814     {
1815       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
1816     }
1817   }
1818   else
1819   {
1820     // Number
1821     const Standard_Integer aSelMode = Draw::Atoi(buf_ret);
1822     if (aSelMode >= 0 && aSelMode <= 7)
1823     {
1824       bool toEnable = true;
1825       if (const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext())
1826       {
1827         AIS_ListOfInteractive aPrsList;
1828         aCtx->DisplayedObjects (aPrsList);
1829         for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
1830         {
1831           TColStd_ListOfInteger aModes;
1832           aCtx->ActivatedModes (aPrsIter.Value(), aModes);
1833           for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
1834           {
1835             if (aModeIter.Value() == aSelMode)
1836             {
1837               toEnable = false;
1838             }
1839           }
1840         }
1841       }
1842       TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
1843       Draw_Interprete (aCmd.ToCString());
1844     }
1845   }
1846 }
1847
1848 //==============================================================================
1849 //function : VT_ProcessExpose
1850 //purpose  : Redraw the View on an Expose Event
1851 //==============================================================================
1852 void VT_ProcessExpose()
1853 {
1854   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1855   if (!aView3d.IsNull())
1856   {
1857     aView3d->Redraw();
1858   }
1859 }
1860
1861 //==============================================================================
1862 //function : VT_ProcessConfigure
1863 //purpose  : Resize the View on an Configure Event
1864 //==============================================================================
1865 void VT_ProcessConfigure()
1866 {
1867   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1868   if (aView3d.IsNull())
1869   {
1870     return;
1871   }
1872
1873   aView3d->MustBeResized();
1874   aView3d->Update();
1875   aView3d->Redraw();
1876 }
1877
1878 //==============================================================================
1879 //function : VT_ProcessButton1Press
1880 //purpose  : Picking
1881 //==============================================================================
1882 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1883                                          const char**     theArgVec,
1884                                          Standard_Boolean theToPick,
1885                                          Standard_Boolean theIsShift)
1886 {
1887   if (TheIsAnimating)
1888   {
1889     TheIsAnimating = Standard_False;
1890     return Standard_False;
1891   }
1892
1893   if (theToPick)
1894   {
1895     Standard_Real X, Y, Z;
1896     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1897
1898     Draw::Set (theArgVec[1], X);
1899     Draw::Set (theArgVec[2], Y);
1900     Draw::Set (theArgVec[3], Z);
1901   }
1902
1903   if (theIsShift)
1904   {
1905     ViewerTest::CurrentEventManager()->ShiftSelect();
1906   }
1907   else
1908   {
1909     ViewerTest::CurrentEventManager()->Select();
1910   }
1911
1912   return Standard_False;
1913 }
1914
1915 //==============================================================================
1916 //function : VT_ProcessButton1Release
1917 //purpose  : End selecting
1918 //==============================================================================
1919 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1920 {
1921   if (IsDragged)
1922   {
1923     IsDragged = Standard_False;
1924     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1925     if (theIsShift)
1926     {
1927       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1928                        X_Motion, Y_Motion);
1929     }
1930     else
1931     {
1932       EM->Select (X_ButtonPress, Y_ButtonPress,
1933                   X_Motion, Y_Motion);
1934     }
1935   }
1936 }
1937
1938 //==============================================================================
1939 //function : VT_ProcessButton3Press
1940 //purpose  : Start Rotation
1941 //==============================================================================
1942 void VT_ProcessButton3Press()
1943 {
1944   if (ViewerTest_V3dView::IsCurrentViewIn2DMode())
1945   {
1946     return;
1947   }
1948
1949   Start_Rot = 1;
1950   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
1951   if (HasHlrOnBeforeRotation)
1952   {
1953     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1954   }
1955   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1956 }
1957
1958 //==============================================================================
1959 //function : VT_ProcessButton3Release
1960 //purpose  : End rotation
1961 //==============================================================================
1962 void VT_ProcessButton3Release()
1963 {
1964   if (Start_Rot)
1965   {
1966     Start_Rot = 0;
1967     if (HasHlrOnBeforeRotation)
1968     {
1969       HasHlrOnBeforeRotation = Standard_False;
1970       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1971       ViewerTest::CurrentView()->Redraw();
1972     }
1973   }
1974 }
1975
1976 //==============================================================================
1977 //function : ProcessControlButton1Motion
1978 //purpose  : Zoom
1979 //==============================================================================
1980
1981 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1982 static void ProcessControlButton1Motion()
1983 {
1984   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1985
1986   X_ButtonPress = X_Motion;
1987   Y_ButtonPress = Y_Motion;
1988 }
1989 #endif
1990
1991 //==============================================================================
1992 //function : VT_ProcessControlButton2Motion
1993 //purpose  : Panning
1994 //==============================================================================
1995 void VT_ProcessControlButton2Motion()
1996 {
1997   Standard_Integer aDx = X_Motion - X_ButtonPress;
1998   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1999
2000   aDy = -aDy; // Xwindow Y axis is from top to Bottom
2001
2002   ViewerTest::CurrentView()->Pan (aDx, aDy);
2003
2004   X_ButtonPress = X_Motion;
2005   Y_ButtonPress = Y_Motion;
2006 }
2007
2008 //==============================================================================
2009 //function : VT_ProcessControlButton3Motion
2010 //purpose  : Rotation
2011 //==============================================================================
2012 void VT_ProcessControlButton3Motion()
2013 {
2014   if (Start_Rot)
2015   {
2016     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
2017   }
2018 }
2019
2020 //==============================================================================
2021 //function : VT_ProcessMotion
2022 //purpose  :
2023 //==============================================================================
2024 void VT_ProcessMotion()
2025 {
2026   //pre-hilights detected objects at mouse position
2027
2028   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
2029   EM->MoveTo(X_Motion, Y_Motion);
2030 }
2031
2032
2033 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
2034 {
2035   Xpix = X_Motion;Ypix=Y_Motion;
2036 }
2037
2038 //==============================================================================
2039 //function : ViewProject: implements VAxo, VTop, VLeft, ...
2040 //purpose  : Switches to an axonometric, top, left and other views
2041 //==============================================================================
2042
2043 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
2044 {
2045   if ( ViewerTest::CurrentView().IsNull() )
2046   {
2047     di<<"Call vinit before this command, please\n";
2048     return 1;
2049   }
2050
2051   ViewerTest::CurrentView()->SetProj(ori);
2052   return 0;
2053 }
2054
2055 //==============================================================================
2056 //function : VAxo
2057 //purpose  : Switch to an Axonometric view
2058 //Draw arg : No args
2059 //==============================================================================
2060
2061 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
2062 {
2063   return ViewProject(di, V3d_XposYnegZpos);
2064 }
2065
2066 //==============================================================================
2067 //function : VTop
2068 //purpose  : Switch to a Top View
2069 //Draw arg : No args
2070 //==============================================================================
2071
2072 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
2073 {
2074   return ViewProject(di, V3d_Zpos);
2075 }
2076
2077 //==============================================================================
2078 //function : VBottom
2079 //purpose  : Switch to a Bottom View
2080 //Draw arg : No args
2081 //==============================================================================
2082
2083 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
2084 {
2085   return ViewProject(di, V3d_Zneg);
2086 }
2087
2088 //==============================================================================
2089 //function : VLeft
2090 //purpose  : Switch to a Left View
2091 //Draw arg : No args
2092 //==============================================================================
2093
2094 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
2095 {
2096   return ViewProject(di, V3d_Xneg);
2097 }
2098
2099 //==============================================================================
2100 //function : VRight
2101 //purpose  : Switch to a Right View
2102 //Draw arg : No args
2103 //==============================================================================
2104
2105 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
2106 {
2107   return ViewProject(di, V3d_Xpos);
2108 }
2109
2110 //==============================================================================
2111 //function : VFront
2112 //purpose  : Switch to a Front View
2113 //Draw arg : No args
2114 //==============================================================================
2115
2116 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
2117 {
2118   return ViewProject(di, V3d_Yneg);
2119 }
2120
2121 //==============================================================================
2122 //function : VBack
2123 //purpose  : Switch to a Back View
2124 //Draw arg : No args
2125 //==============================================================================
2126
2127 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
2128 {
2129   return ViewProject(di, V3d_Ypos);
2130 }
2131
2132 //==============================================================================
2133 //function : VHelp
2134 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
2135 //Draw arg : No args
2136 //==============================================================================
2137
2138 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
2139 {
2140
2141   di << "Q : Quit the application\n";
2142
2143   di << "=========================\n";
2144   di << "F : FitAll\n";
2145   di << "T : TopView\n";
2146   di << "B : BottomView\n";
2147   di << "R : RightView\n";
2148   di << "L : LeftView\n";
2149   di << "A : AxonometricView\n";
2150   di << "D : ResetView\n";
2151
2152   di << "=========================\n";
2153   di << "S : Shading\n";
2154   di << "W : Wireframe\n";
2155   di << "H : HidelLineRemoval\n";
2156   di << "U : Unset display mode\n";
2157   di << "Delete : Remove selection from viewer\n";
2158
2159   di << "=========================\n";
2160   di << "Selection mode \n";
2161   di << "0 : Shape\n";
2162   di << "1 : Vertex\n";
2163   di << "2 : Edge\n";
2164   di << "3 : Wire\n";
2165   di << "4 : Face\n";
2166   di << "5 : Shell\n";
2167   di << "6 : Solid\n";
2168   di << "7 : Compound\n";
2169
2170   di << "=========================\n";
2171   di << "Z : Switch Z clipping On/Off\n";
2172   di << ", : Hilight next detected\n";
2173   di << ". : Hilight previous detected\n";
2174
2175   return 0;
2176 }
2177
2178 #ifdef _WIN32
2179
2180 static Standard_Boolean Ppick = 0;
2181 static Standard_Integer Pargc = 0;
2182 static const char**           Pargv = NULL;
2183
2184
2185 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
2186                                           UINT Msg,
2187                                           WPARAM wParam,
2188                                           LPARAM lParam )
2189 {
2190   if (!ViewerTest_myViews.IsEmpty()) {
2191
2192     WPARAM fwKeys = wParam;
2193
2194     switch( Msg ) {
2195     case WM_CLOSE:
2196        {
2197          // Delete view from map of views
2198          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
2199          return 0;
2200        }
2201        break;
2202     case WM_ACTIVATE:
2203       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
2204         || ViewerTest::CurrentView().IsNull())
2205       {
2206         // Activate inactive window
2207         if(GetWindowHandle(VT_GetWindow()) != hwnd)
2208         {
2209           ActivateView (FindViewIdByWindowHandle(hwnd));
2210         }
2211       }
2212       break;
2213
2214     case WM_LBUTTONUP:
2215       if (IsDragged && !DragFirst)
2216       {
2217         if (!GetActiveAISManipulator().IsNull())
2218         {
2219           GetActiveAISManipulator()->StopTransform();
2220           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2221         }
2222
2223         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2224         {
2225           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2226           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2227         }
2228
2229         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
2230       }
2231       IsDragged = Standard_False;
2232       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2233
2234     case WM_RBUTTONUP:
2235       if (IsDragged && !DragFirst)
2236       {
2237         if (!GetActiveAISManipulator().IsNull())
2238         {
2239           GetActiveAISManipulator()->StopTransform (Standard_False);
2240           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2241         }
2242         IsDragged = Standard_False;
2243       }
2244       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
2245
2246     case WM_LBUTTONDOWN:
2247       if (!GetActiveAISManipulator().IsNull())
2248       {
2249         IsDragged = ( fwKeys == MK_LBUTTON );
2250       }
2251       else
2252       {
2253         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
2254       }
2255
2256       if (IsDragged)
2257       {
2258         DragFirst = Standard_True;
2259         X_ButtonPress = LOWORD(lParam);
2260         Y_ButtonPress = HIWORD(lParam);
2261       }
2262       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2263
2264     case WM_MOUSEMOVE:
2265       if (IsDragged)
2266       {
2267         X_Motion = LOWORD (lParam);
2268         Y_Motion = HIWORD (lParam);
2269         if (!GetActiveAISManipulator().IsNull())
2270         {
2271           if (DragFirst)
2272           {
2273             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
2274           }
2275           else
2276           {
2277             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
2278             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
2279           }
2280         }
2281         else
2282         {
2283           bool toRedraw = false;
2284           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2285           {
2286             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2287             toRedraw = true;
2288           }
2289
2290           RECT aRect;
2291           if (GetClientRect (hwnd, &aRect))
2292           {
2293             int aHeight = aRect.bottom - aRect.top;
2294             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2295             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2296             toRedraw = true;
2297           }
2298           if (toRedraw)
2299           {
2300             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2301           }
2302         }
2303
2304         DragFirst = Standard_False;
2305       }
2306       else
2307         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2308       break;
2309
2310     default:
2311       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2312     }
2313     return 0;
2314   }
2315   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2316 }
2317
2318
2319 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2320                                        UINT Msg,
2321                                        WPARAM wParam,
2322                                        LPARAM lParam )
2323 {
2324   static int Up = 1;
2325   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2326   if (aView.IsNull())
2327   {
2328     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2329   }
2330
2331     PAINTSTRUCT    ps;
2332
2333     switch( Msg ) {
2334     case WM_PAINT:
2335       BeginPaint(hwnd, &ps);
2336       EndPaint(hwnd, &ps);
2337       VT_ProcessExpose();
2338       break;
2339
2340     case WM_SIZE:
2341       VT_ProcessConfigure();
2342       break;
2343     case WM_MOVE:
2344     case WM_MOVING:
2345     case WM_SIZING:
2346       switch (aView->RenderingParams().StereoMode)
2347       {
2348         case Graphic3d_StereoMode_RowInterlaced:
2349         case Graphic3d_StereoMode_ColumnInterlaced:
2350         case Graphic3d_StereoMode_ChessBoard:
2351           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2352           break;
2353         default:
2354           break;
2355       }
2356       break;
2357
2358     case WM_KEYDOWN:
2359       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2360       {
2361         char c[2];
2362         c[0] = (char) wParam;
2363         c[1] = '\0';
2364         if (wParam == VK_DELETE)
2365         {
2366           c[0] = THE_KEY_DELETE;
2367         }
2368         else if (wParam == VK_ESCAPE)
2369         {
2370           c[0] = THE_KEY_ESCAPE;
2371         }
2372         // comma
2373         else if (wParam == VK_OEM_COMMA)
2374         {
2375           c[0] = ',';
2376         }
2377         // dot
2378         else if (wParam == VK_OEM_PERIOD)
2379         {
2380           c[0] = '.';
2381         }
2382         else if (wParam == VK_DIVIDE)
2383         {
2384           c[0] = '/';
2385         }
2386         // dot
2387         else if (wParam == VK_MULTIPLY)
2388         {
2389           c[0] = '*';
2390         }
2391         VT_ProcessKeyPress (c);
2392       }
2393       break;
2394
2395     case WM_LBUTTONUP:
2396     case WM_MBUTTONUP:
2397     case WM_RBUTTONUP:
2398       Up = 1;
2399       VT_ProcessButton3Release();
2400       break;
2401
2402     case WM_LBUTTONDOWN:
2403     case WM_MBUTTONDOWN:
2404     case WM_RBUTTONDOWN:
2405       {
2406         WPARAM fwKeys = wParam;
2407
2408         Up = 0;
2409
2410         X_ButtonPress = LOWORD(lParam);
2411         Y_ButtonPress = HIWORD(lParam);
2412
2413         if (Msg == WM_LBUTTONDOWN)
2414         {
2415           if ((fwKeys & MK_CONTROL) != 0)
2416           {
2417             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2418           }
2419           else
2420           {
2421             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2422           }
2423         }
2424         else if (Msg == WM_RBUTTONDOWN)
2425         {
2426           // Start rotation
2427           VT_ProcessButton3Press();
2428         }
2429       }
2430       break;
2431
2432     case WM_MOUSEWHEEL:
2433     {
2434       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2435       if (wParam & MK_CONTROL)
2436       {
2437         if (aView->Camera()->IsStereo())
2438         {
2439           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2440           if (aFocus > 0.2
2441            && aFocus < 2.0)
2442           {
2443             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2444             aView->Redraw();
2445           }
2446         }
2447       }
2448       else
2449       {
2450         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2451       }
2452       break;
2453     }
2454
2455     case WM_MOUSEMOVE:
2456       {
2457         //cout << "\t WM_MOUSEMOVE" << endl;
2458         WPARAM fwKeys = wParam;
2459         X_Motion = LOWORD(lParam);
2460         Y_Motion = HIWORD(lParam);
2461
2462         if ( Up &&
2463           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2464           {
2465             Up = 0;
2466             X_ButtonPress = LOWORD(lParam);
2467             Y_ButtonPress = HIWORD(lParam);
2468
2469             if ((fwKeys & MK_RBUTTON) != 0) {
2470               // Start rotation
2471               VT_ProcessButton3Press();
2472             }
2473           }
2474
2475           if ((fwKeys & MK_CONTROL) != 0)
2476           {
2477             if ((fwKeys & MK_LBUTTON) != 0)
2478             {
2479               ProcessControlButton1Motion();
2480             }
2481             else if ((fwKeys & MK_MBUTTON) != 0
2482                  || ((fwKeys & MK_LBUTTON) != 0
2483                   && (fwKeys & MK_RBUTTON) != 0))
2484             {
2485               VT_ProcessControlButton2Motion();
2486             }
2487             else if ((fwKeys & MK_RBUTTON) != 0)
2488             {
2489               VT_ProcessControlButton3Motion();
2490             }
2491           }
2492           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2493           {
2494             VT_ProcessMotion();
2495           }
2496       }
2497       break;
2498
2499     default:
2500       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2501     }
2502     return 0L;
2503 }
2504
2505 //==============================================================================
2506 //function : ViewerMainLoop
2507 //purpose  : Get a Event on the view and dispatch it
2508 //==============================================================================
2509
2510
2511 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2512 {
2513   Ppick = (argc > 0)? 1 : 0;
2514   Pargc = argc;
2515   Pargv = argv;
2516
2517   if ( Ppick ) {
2518     MSG msg;
2519     msg.wParam = 1;
2520
2521     cout << "Start picking" << endl;
2522
2523     while ( Ppick == 1 ) {
2524       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2525       if (GetMessageW (&msg, NULL, 0, 0))
2526       {
2527         TranslateMessage (&msg);
2528         DispatchMessageW (&msg);
2529       }
2530     }
2531
2532     cout << "Picking done" << endl;
2533   }
2534
2535   return Ppick;
2536 }
2537
2538 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2539
2540 int min( int a, int b )
2541 {
2542   if( a<b )
2543     return a;
2544   else
2545     return b;
2546 }
2547
2548 int max( int a, int b )
2549 {
2550   if( a>b )
2551     return a;
2552   else
2553     return b;
2554 }
2555
2556 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2557
2558 {
2559   static XEvent aReport;
2560   Standard_Boolean pick = argc > 0;
2561   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2562   XNextEvent (aDisplay, &aReport);
2563
2564   // Handle event for the chosen display connection
2565   switch (aReport.type) {
2566       case ClientMessage:
2567         {
2568           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2569           {
2570             // Close the window
2571             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2572           }
2573         }
2574         return 0;
2575      case FocusIn:
2576       {
2577          // Activate inactive view
2578          Window aWindow = GetWindowHandle(VT_GetWindow());
2579          if(aWindow != aReport.xfocus.window)
2580          {
2581            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2582          }
2583       }
2584       break;
2585       case Expose:
2586         {
2587           VT_ProcessExpose();
2588         }
2589         break;
2590       case ConfigureNotify:
2591         {
2592           VT_ProcessConfigure();
2593         }
2594         break;
2595       case KeyPress:
2596         {
2597
2598           KeySym ks_ret ;
2599           char buf_ret[11] ;
2600           int ret_len ;
2601           XComposeStatus status_in_out;
2602
2603           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2604             (char *) buf_ret , 10 ,
2605             &ks_ret , &status_in_out ) ;
2606
2607
2608           buf_ret[ret_len] = '\0' ;
2609
2610           if (ret_len)
2611           {
2612             VT_ProcessKeyPress (buf_ret);
2613           }
2614         }
2615         break;
2616       case ButtonPress:
2617         {
2618           X_ButtonPress = aReport.xbutton.x;
2619           Y_ButtonPress = aReport.xbutton.y;
2620
2621           if (aReport.xbutton.button == Button1)
2622           {
2623             if (aReport.xbutton.state & ControlMask)
2624             {
2625               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2626             }
2627             else
2628             {
2629               IsDragged = Standard_True;
2630               DragFirst = Standard_True;
2631             }
2632           }
2633           else if (aReport.xbutton.button == Button3)
2634           {
2635             // Start rotation
2636             VT_ProcessButton3Press();
2637           }
2638         }
2639         break;
2640       case ButtonRelease:
2641         {
2642           if( IsDragged )
2643           {
2644             if( !DragFirst )
2645             {
2646               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2647               {
2648                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2649                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2650               }
2651             }
2652
2653             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2654             if( aContext.IsNull() )
2655             {
2656               cout << "The context is null. Please use vinit before createmesh" << endl;
2657               return 0;
2658             }
2659
2660             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2661             if( aReport.xbutton.button==1 )
2662               if( DragFirst )
2663                 if( ShiftPressed )
2664                 {
2665                   aContext->ShiftSelect (Standard_True);
2666                 }
2667                 else
2668                 {
2669                   aContext->Select (Standard_True);
2670                 }
2671               else
2672                 if( ShiftPressed )
2673                 {
2674                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2675                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2676                                         ViewerTest::CurrentView(), Standard_True);
2677                 }
2678                 else
2679                 {
2680                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2681                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2682                                    ViewerTest::CurrentView(), Standard_True);
2683                 }
2684             else
2685               VT_ProcessButton3Release();
2686
2687             IsDragged = Standard_False;
2688           }
2689           else
2690             VT_ProcessButton3Release();
2691         }
2692         break;
2693       case MotionNotify:
2694         {
2695           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2696           {
2697             break;
2698           }
2699           if( IsDragged )
2700           {
2701             if( !DragFirst )
2702             {
2703               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2704               {
2705                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2706               }
2707             }
2708
2709             X_Motion = aReport.xmotion.x;
2710             Y_Motion = aReport.xmotion.y;
2711             DragFirst = Standard_False;
2712
2713             Window aWindow = GetWindowHandle(VT_GetWindow());
2714             Window aRoot;
2715             int anX, anY;
2716             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2717             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2718             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2719             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2720             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2721           }
2722           else
2723           {
2724             X_Motion = aReport.xmotion.x;
2725             Y_Motion = aReport.xmotion.y;
2726
2727             // remove all the ButtonMotionMaskr
2728             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2729
2730             if ( aReport.xmotion.state & ControlMask ) {
2731               if ( aReport.xmotion.state & Button1Mask ) {
2732                 ProcessControlButton1Motion();
2733               }
2734               else if ( aReport.xmotion.state & Button2Mask ) {
2735                 VT_ProcessControlButton2Motion();
2736               }
2737               else if ( aReport.xmotion.state & Button3Mask ) {
2738                 VT_ProcessControlButton3Motion();
2739               }
2740             }
2741             else
2742             {
2743               VT_ProcessMotion();
2744             }
2745           }
2746         }
2747         break;
2748 }
2749 return pick;
2750 }
2751
2752 //==============================================================================
2753 //function : VProcessEvents
2754 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2755 //       event in the Viewer window
2756 //==============================================================================
2757
2758 static void VProcessEvents(ClientData,int)
2759 {
2760   NCollection_Vector<int> anEventNumbers;
2761   // Get number of messages from every display
2762   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2763        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2764   {
2765     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2766   }
2767     // Handle events for every display
2768   int anEventIter = 0;
2769   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2770        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2771   {
2772     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2773          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2774     {
2775       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2776       int anEventResult = ViewerMainLoop( 0, NULL);
2777       // If window is closed or context was not found finish current event processing loop
2778       if (!anEventResult)
2779         return;
2780     }
2781   }
2782
2783   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2784
2785 }
2786 #endif
2787
2788 //==============================================================================
2789 //function : OSWindowSetup
2790 //purpose  : Setup for the X11 window to be able to cath the event
2791 //==============================================================================
2792
2793
2794 static void OSWindowSetup()
2795 {
2796 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2797   // X11
2798
2799   Window  window   = VT_GetWindow()->XWindow();
2800   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2801   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2802   XSynchronize(aDisplay, 1);
2803
2804   // X11 : For keyboard on SUN
2805   XWMHints wmhints;
2806   wmhints.flags = InputHint;
2807   wmhints.input = 1;
2808
2809   XSetWMHints( aDisplay, window, &wmhints);
2810
2811   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2812     ButtonPressMask | ButtonReleaseMask |
2813     StructureNotifyMask |
2814     PointerMotionMask |
2815     Button1MotionMask | Button2MotionMask |
2816     Button3MotionMask | FocusChangeMask
2817     );
2818   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2819   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2820
2821   XSynchronize(aDisplay, 0);
2822
2823 #else
2824   // _WIN32
2825 #endif
2826
2827 }
2828
2829 //==============================================================================
2830 //function : VFit
2831 //purpose  :
2832 //==============================================================================
2833
2834 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2835 {
2836   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2837   if (aView.IsNull())
2838   {
2839     std::cout << "Error: no active viewer!\n";
2840     return 1;
2841   }
2842
2843   Standard_Boolean toFit = Standard_True;
2844   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2845   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2846   {
2847     TCollection_AsciiString anArg (theArgv[anArgIter]);
2848     anArg.LowerCase();
2849     if (anUpdateTool.parseRedrawMode (anArg))
2850     {
2851       continue;
2852     }
2853     else if (anArg == "-selected")
2854     {
2855       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2856       toFit = Standard_False;
2857     }
2858     else
2859     {
2860       std::cout << "Syntax error at '" << anArg << "'\n";
2861     }
2862   }
2863
2864   if (toFit)
2865   {
2866     aView->FitAll (0.01, Standard_False);
2867   }
2868   return 0;
2869 }
2870
2871 //=======================================================================
2872 //function : VFitArea
2873 //purpose  : Fit view to show area located between two points
2874 //         : given in world 2D or 3D coordinates.
2875 //=======================================================================
2876 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2877 {
2878   Handle(V3d_View) aView = ViewerTest::CurrentView();
2879   if (aView.IsNull())
2880   {
2881     std::cerr << theArgVec[0] << "Error: No active view.\n";
2882     return 1;
2883   }
2884
2885   // Parse arguments.
2886   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2887   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2888
2889   if (theArgNb == 5)
2890   {
2891     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2892     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2893     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2894     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2895   }
2896   else if (theArgNb == 7)
2897   {
2898     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2899     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2900     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2901     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2902     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2903     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2904   }
2905   else
2906   {
2907     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2908     theDI.PrintHelp(theArgVec[0]);
2909     return 1;
2910   }
2911
2912   // Convert model coordinates to view space
2913   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2914   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2915   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2916
2917   // Determine fit area
2918   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2919   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2920
2921   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2922
2923   if (aDiagonal < Precision::Confusion())
2924   {
2925     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2926     return 1;
2927   }
2928
2929   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2930   return 0;
2931 }
2932
2933 //==============================================================================
2934 //function : VZFit
2935 //purpose  : ZFitall, no DRAW arguments
2936 //Draw arg : No args
2937 //==============================================================================
2938 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2939 {
2940   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2941
2942   if (aCurrentView.IsNull())
2943   {
2944     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2945     return 1;
2946   }
2947
2948   if (theArgsNb == 1)
2949   {
2950     aCurrentView->ZFitAll();
2951     aCurrentView->Redraw();
2952     return 0;
2953   }
2954
2955   Standard_Real aScale = 1.0;
2956
2957   if (theArgsNb >= 2)
2958   {
2959     aScale = Draw::Atoi (theArgVec[1]);
2960   }
2961
2962   aCurrentView->ZFitAll (aScale);
2963   aCurrentView->Redraw();
2964
2965   return 0;
2966 }
2967
2968 //==============================================================================
2969 //function : VRepaint
2970 //purpose  :
2971 //==============================================================================
2972 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2973 {
2974   Handle(V3d_View) aView = ViewerTest::CurrentView();
2975   if (aView.IsNull())
2976   {
2977     std::cout << "Error: no active viewer!\n";
2978     return 1;
2979   }
2980
2981   Standard_Boolean isImmediateUpdate = Standard_False;
2982   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2983   {
2984     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2985     anArg.LowerCase();
2986     if (anArg == "-immediate")
2987     {
2988       isImmediateUpdate = Standard_True;
2989       if (anArgIter + 1 < theArgNb
2990        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2991       {
2992         ++anArgIter;
2993       }
2994     }
2995     else
2996     {
2997       std::cout << "Syntax error at '" << anArg << "'\n";
2998     }
2999   }
3000
3001   if (isImmediateUpdate)
3002   {
3003     aView->RedrawImmediate();
3004   }
3005   else
3006   {
3007     aView->Redraw();
3008   }
3009   return 0;
3010 }
3011
3012 //==============================================================================
3013 //function : VClear
3014 //purpose  : Remove all the object from the viewer
3015 //Draw arg : No args
3016 //==============================================================================
3017
3018 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3019 {
3020   Handle(V3d_View) V = ViewerTest::CurrentView();
3021   if(!V.IsNull())
3022     ViewerTest::Clear();
3023   return 0;
3024 }
3025
3026 //==============================================================================
3027 //function : VPick
3028 //purpose  :
3029 //==============================================================================
3030
3031 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3032 { if (ViewerTest::CurrentView().IsNull() ) return 1;
3033
3034 if ( argc < 4 ) {
3035   di << argv[0] << "Invalid number of arguments\n";
3036   return 1;
3037 }
3038
3039 while (ViewerMainLoop( argc, argv)) {
3040 }
3041
3042 return 0;
3043 }
3044
3045 //==============================================================================
3046 //function : VSetBg
3047 //purpose  : Load image as background
3048 //==============================================================================
3049
3050 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3051 {
3052   if (argc < 2 || argc > 3)
3053   {
3054     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
3055     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
3056     return 1;
3057   }
3058
3059   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3060   if(AISContext.IsNull())
3061   {
3062     di << "use 'vinit' command before " << argv[0] << "\n";
3063     return 1;
3064   }
3065
3066   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
3067   if (argc == 3)
3068   {
3069     const char* szType = argv[2];
3070     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3071     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3072     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3073     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3074     else
3075     {
3076       di << "Wrong fill type : " << szType << "\n";
3077       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3078       return 1;
3079     }
3080   }
3081
3082   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3083   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
3084
3085   return 0;
3086 }
3087
3088 //==============================================================================
3089 //function : VSetBgMode
3090 //purpose  : Change background image fill type
3091 //==============================================================================
3092
3093 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3094 {
3095   if (argc != 2)
3096   {
3097     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
3098     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
3099     return 1;
3100   }
3101
3102   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3103   if(AISContext.IsNull())
3104   {
3105     di << "use 'vinit' command before " << argv[0] << "\n";
3106     return 1;
3107   }
3108   Aspect_FillMethod aFillType = Aspect_FM_NONE;
3109   const char* szType = argv[1];
3110   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3111   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3112   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3113   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3114   else
3115   {
3116     di << "Wrong fill type : " << szType << "\n";
3117     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3118     return 1;
3119   }
3120   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3121   V3dView->SetBgImageStyle(aFillType, Standard_True);
3122   return 0;
3123 }
3124
3125 //==============================================================================
3126 //function : VSetGradientBg
3127 //purpose  : Mount gradient background
3128 //==============================================================================
3129 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3130 {
3131   if (argc != 8 )
3132   {
3133     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
3134     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
3135     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3136     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3137     return 1;
3138   }
3139
3140   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3141   if(AISContext.IsNull())
3142   {
3143     di << "use 'vinit' command before " << argv[0] << "\n";
3144     return 1;
3145   }
3146   if (argc == 8)
3147   {
3148
3149     Standard_Real R1 = Draw::Atof(argv[1])/255.;
3150     Standard_Real G1 = Draw::Atof(argv[2])/255.;
3151     Standard_Real B1 = Draw::Atof(argv[3])/255.;
3152     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
3153
3154     Standard_Real R2 = Draw::Atof(argv[4])/255.;
3155     Standard_Real G2 = Draw::Atof(argv[5])/255.;
3156     Standard_Real B2 = Draw::Atof(argv[6])/255.;
3157
3158     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
3159     int aType = Draw::Atoi(argv[7]);
3160     if( aType < 0 || aType > 8 )
3161     {
3162       di << "Wrong fill type \n";
3163       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3164       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3165       return 1;
3166     }
3167
3168     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3169
3170     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3171     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
3172   }
3173
3174   return 0;
3175 }
3176
3177 //==============================================================================
3178 //function : VSetGradientBgMode
3179 //purpose  : Change gradient background fill style
3180 //==============================================================================
3181 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3182 {
3183   if (argc != 2 )
3184   {
3185     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
3186     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3187     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3188     return 1;
3189   }
3190
3191   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3192   if(AISContext.IsNull())
3193   {
3194     di << "use 'vinit' command before " << argv[0] << "\n";
3195     return 1;
3196   }
3197   if (argc == 2)
3198   {
3199     int aType = Draw::Atoi(argv[1]);
3200     if( aType < 0 || aType > 8 )
3201     {
3202       di << "Wrong fill type \n";
3203       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3204       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3205       return 1;
3206     }
3207
3208     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3209
3210     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3211     V3dView->SetBgGradientStyle( aMethod, 1 );
3212   }
3213
3214   return 0;
3215 }
3216
3217 //==============================================================================
3218 //function : VSetColorBg
3219 //purpose  : Set color background
3220 //==============================================================================
3221 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3222 {
3223   if (argc != 4 )
3224   {
3225     di << "Usage : " << argv[0] << " R G B : Set color background\n";
3226     di << "R,G,B = [0..255]\n";
3227     return 1;
3228   }
3229
3230   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3231   if(AISContext.IsNull())
3232   {
3233     di << "use 'vinit' command before " << argv[0] << "\n";
3234     return 1;
3235   }
3236   if (argc == 4)
3237   {
3238
3239     Standard_Real R = Draw::Atof(argv[1])/255.;
3240     Standard_Real G = Draw::Atof(argv[2])/255.;
3241     Standard_Real B = Draw::Atof(argv[3])/255.;
3242     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
3243
3244     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3245     V3dView->SetBackgroundColor( aColor );
3246     V3dView->Update();
3247   }
3248
3249   return 0;
3250 }
3251
3252 //==============================================================================
3253 //function : VSetDefaultBg
3254 //purpose  : Set default viewer background fill color
3255 //==============================================================================
3256 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3257 {
3258   if (theArgNb != 4
3259    && theArgNb != 8)
3260   {
3261     std::cout << "Error: wrong syntax! See usage:\n";
3262     theDI.PrintHelp (theArgVec[0]);
3263     return 1;
3264   }
3265
3266   ViewerTest_DefaultBackground.FillMethod =
3267     theArgNb == 4 ? Aspect_GFM_NONE
3268                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
3269
3270   if (theArgNb == 4)
3271   {
3272     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
3273     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
3274     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
3275     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
3276   }
3277   else
3278   {
3279     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
3280     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
3281     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
3282     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
3283
3284     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
3285     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
3286     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
3287     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
3288   }
3289
3290   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
3291        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
3292   {
3293     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
3294     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
3295     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
3296                                          ViewerTest_DefaultBackground.GradientColor2,
3297                                          ViewerTest_DefaultBackground.FillMethod);
3298   }
3299
3300   return 0;
3301 }
3302
3303 //==============================================================================
3304 //function : VScale
3305 //purpose  : View Scaling
3306 //==============================================================================
3307
3308 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3309 {
3310   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3311   if ( V3dView.IsNull() ) return 1;
3312
3313   if ( argc != 4 ) {
3314     di << argv[0] << "Invalid number of arguments\n";
3315     return 1;
3316   }
3317   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3318   return 0;
3319 }
3320 //==============================================================================
3321 //function : VZBuffTrihedron
3322 //purpose  :
3323 //==============================================================================
3324
3325 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3326                             Standard_Integer  theArgNb,
3327                             const char**      theArgVec)
3328 {
3329   Handle(V3d_View) aView = ViewerTest::CurrentView();
3330   if (aView.IsNull())
3331   {
3332     std::cout << "Error: no active viewer!\n";
3333     return 1;
3334   }
3335
3336   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3337
3338   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3339   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3340   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3341   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3342   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3343   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3344   Standard_Real                 aScale        = 0.1;
3345   Standard_Real                 aSizeRatio    = 0.8;
3346   Standard_Real                 anArrowDiam   = 0.05;
3347   Standard_Integer              aNbFacets     = 12;
3348   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3349   {
3350     Standard_CString        anArg = theArgVec[anArgIter];
3351     TCollection_AsciiString aFlag (anArg);
3352     aFlag.LowerCase();
3353     if (anUpdateTool.parseRedrawMode (aFlag))
3354     {
3355       continue;
3356     }
3357     else if (aFlag == "-on")
3358     {
3359       continue;
3360     }
3361     else if (aFlag == "-off")
3362     {
3363       aView->TriedronErase();
3364       return 0;
3365     }
3366     else if (aFlag == "-pos"
3367           || aFlag == "-position"
3368           || aFlag == "-corner")
3369     {
3370       if (++anArgIter >= theArgNb)
3371       {
3372         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3373         return 1;
3374       }
3375
3376       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3377       aPosName.LowerCase();
3378       if (aPosName == "center")
3379       {
3380         aPosition = Aspect_TOTP_CENTER;
3381       }
3382       else if (aPosName == "left_lower"
3383             || aPosName == "lower_left"
3384             || aPosName == "leftlower"
3385             || aPosName == "lowerleft")
3386       {
3387         aPosition = Aspect_TOTP_LEFT_LOWER;
3388       }
3389       else if (aPosName == "left_upper"
3390             || aPosName == "upper_left"
3391             || aPosName == "leftupper"
3392             || aPosName == "upperleft")
3393       {
3394         aPosition = Aspect_TOTP_LEFT_UPPER;
3395       }
3396       else if (aPosName == "right_lower"
3397             || aPosName == "lower_right"
3398             || aPosName == "rightlower"
3399             || aPosName == "lowerright")
3400       {
3401         aPosition = Aspect_TOTP_RIGHT_LOWER;
3402       }
3403       else if (aPosName == "right_upper"
3404             || aPosName == "upper_right"
3405             || aPosName == "rightupper"
3406             || aPosName == "upperright")
3407       {
3408         aPosition = Aspect_TOTP_RIGHT_UPPER;
3409       }
3410       else
3411       {
3412         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3413         return 1;
3414       }
3415     }
3416     else if (aFlag == "-type")
3417     {
3418       if (++anArgIter >= theArgNb)
3419       {
3420         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3421         return 1;
3422       }
3423
3424       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3425       aTypeName.LowerCase();
3426       if (aTypeName == "wireframe"
3427        || aTypeName == "wire")
3428       {
3429         aVisType = V3d_WIREFRAME;
3430       }
3431       else if (aTypeName == "zbuffer"
3432             || aTypeName == "shaded")
3433       {
3434         aVisType = V3d_ZBUFFER;
3435       }
3436       else
3437       {
3438         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3439       }
3440     }
3441     else if (aFlag == "-scale")
3442     {
3443       if (++anArgIter >= theArgNb)
3444       {
3445         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3446         return 1;
3447       }
3448
3449       aScale = Draw::Atof (theArgVec[anArgIter]);
3450     }
3451     else if (aFlag == "-size"
3452           || aFlag == "-sizeratio")
3453     {
3454       if (++anArgIter >= theArgNb)
3455       {
3456         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3457         return 1;
3458       }
3459
3460       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3461     }
3462     else if (aFlag == "-arrowdiam"
3463           || aFlag == "-arrowdiameter")
3464     {
3465       if (++anArgIter >= theArgNb)
3466       {
3467         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3468         return 1;
3469       }
3470
3471       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3472     }
3473     else if (aFlag == "-nbfacets")
3474     {
3475       if (++anArgIter >= theArgNb)
3476       {
3477         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3478         return 1;
3479       }
3480
3481       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3482     }
3483     else if (aFlag == "-colorlabel"
3484           || aFlag == "-colorlabels")
3485     {
3486       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3487                                                            theArgVec + anArgIter + 1,
3488                                                            aLabelsColor);
3489       if (aNbParsed == 0)
3490       {
3491         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3492         return 1;
3493       }
3494       anArgIter += aNbParsed;
3495     }
3496     else if (aFlag == "-colorarrowx")
3497     {
3498       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3499                                                            theArgVec + anArgIter + 1,
3500                                                            anArrowColorX);
3501       if (aNbParsed == 0)
3502       {
3503         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3504         return 1;
3505       }
3506       anArgIter += aNbParsed;
3507     }
3508     else if (aFlag == "-colorarrowy")
3509     {
3510       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3511                                                            theArgVec + anArgIter + 1,
3512                                                            anArrowColorY);
3513       if (aNbParsed == 0)
3514       {
3515         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3516         return 1;
3517       }
3518       anArgIter += aNbParsed;
3519     }
3520     else if (aFlag == "-colorarrowz")
3521     {
3522       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3523                                                            theArgVec + anArgIter + 1,
3524                                                            anArrowColorZ);
3525       if (aNbParsed == 0)
3526       {
3527         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3528         return 1;
3529       }
3530       anArgIter += aNbParsed;
3531     }
3532     else
3533     {
3534       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3535       return 1;
3536     }
3537   }
3538
3539   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3540                                aSizeRatio, anArrowDiam, aNbFacets);
3541   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3542   aView->ZFitAll();
3543   return 0;
3544 }
3545
3546 //==============================================================================
3547 //function : VRotate
3548 //purpose  : Camera Rotating
3549 //==============================================================================
3550
3551 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3552 {
3553   Handle(V3d_View) aView = ViewerTest::CurrentView();
3554   if (aView.IsNull())
3555   {
3556     std::cout << "No active view!\n";
3557     return 1;
3558   }
3559
3560   Standard_Boolean hasFlags = Standard_False;
3561   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3562   {
3563     Standard_CString        anArg (theArgVec[anArgIter]);
3564     TCollection_AsciiString aFlag (anArg);
3565     aFlag.LowerCase();
3566     if (aFlag == "-mousestart"
3567      || aFlag == "-mousefrom")
3568     {
3569       hasFlags = Standard_True;
3570       if (anArgIter + 2 >= theArgNb)
3571       {
3572         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3573         return 1;
3574       }
3575
3576       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3577       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3578       aView->StartRotation (anX, anY);
3579     }
3580     else if (aFlag == "-mousemove")
3581     {
3582       hasFlags = Standard_True;
3583       if (anArgIter + 2 >= theArgNb)
3584       {
3585         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3586         return 1;
3587       }
3588
3589       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3590       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3591       aView->Rotation (anX, anY);
3592     }
3593     else if (theArgNb != 4
3594           && theArgNb != 7)
3595     {
3596       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3597       return 1;
3598     }
3599   }
3600
3601   if (hasFlags)
3602   {
3603     return 0;
3604   }
3605   else if (theArgNb == 4)
3606   {
3607     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3608     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3609     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3610     aView->Rotate (anAX, anAY, anAZ);
3611     return 0;
3612   }
3613   else if (theArgNb == 7)
3614   {
3615     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3616     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3617     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3618
3619     Standard_Real anX = Draw::Atof (theArgVec[4]);
3620     Standard_Real anY = Draw::Atof (theArgVec[5]);
3621     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3622
3623     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3624     return 0;
3625   }
3626
3627   std::cout << "Error: Invalid number of arguments\n";
3628   return 1;
3629 }
3630
3631 //==============================================================================
3632 //function : VZoom
3633 //purpose  : View zoom in / out (relative to current zoom)
3634 //==============================================================================
3635
3636 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3637   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3638   if ( V3dView.IsNull() ) {
3639     return 1;
3640   }
3641
3642   if ( argc == 2 ) {
3643     Standard_Real coef = Draw::Atof(argv[1]);
3644     if ( coef <= 0.0 ) {
3645       di << argv[1] << "Invalid value\n";
3646       return 1;
3647     }
3648     V3dView->SetZoom( Draw::Atof(argv[1]) );
3649     return 0;
3650   } else {
3651     di << argv[0] << " Invalid number of arguments\n";
3652     return 1;
3653   }
3654 }
3655
3656 //==============================================================================
3657 //function : VPan
3658 //purpose  : View panning (in pixels)
3659 //==============================================================================
3660
3661 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3662   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3663   if ( V3dView.IsNull() ) return 1;
3664
3665   if ( argc == 3 ) {
3666     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3667     return 0;
3668   } else {
3669     di << argv[0] << " Invalid number of arguments\n";
3670     return 1;
3671   }
3672 }
3673
3674 //==============================================================================
3675 //function : VPlace
3676 //purpose  : Place the point (in pixels) at the center of the window
3677 //==============================================================================
3678 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3679 {
3680   Handle(V3d_View) aView = ViewerTest::CurrentView();
3681   if (aView.IsNull())
3682   {
3683     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3684     return 1;
3685   }
3686
3687   if (theArgNb != 3)
3688   {
3689     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3690     return 1;
3691   }
3692
3693   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3694
3695   return 0;
3696 }
3697
3698 static int VColorScale (Draw_Interpretor& theDI,
3699                         Standard_Integer  theArgNb,
3700                         const char**      theArgVec)
3701 {
3702   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3703   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3704   if (aContext.IsNull())
3705   {
3706     std::cout << "Error: no active view!\n";
3707     return 1;
3708   }
3709   if (theArgNb <= 1)
3710   {
3711     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3712     return 1;
3713   }
3714
3715   Handle(AIS_ColorScale) aColorScale;
3716   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3717   {
3718     // find existing object
3719     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3720     if (aColorScale.IsNull())
3721     {
3722       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3723       return 1;
3724     }
3725   }
3726
3727   if (theArgNb <= 2)
3728   {
3729     if (aColorScale.IsNull())
3730     {
3731       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3732       return 1;
3733     }
3734
3735     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3736           << "Min range: "            << aColorScale->GetMin() << "\n"
3737           << "Max range: "            << aColorScale->GetMax() << "\n"
3738           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3739           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3740           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3741           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3742           << "Label position: ";
3743     switch (aColorScale->GetLabelPosition())
3744     {
3745       case Aspect_TOCSP_NONE:
3746         theDI << "None\n";
3747         break;
3748       case Aspect_TOCSP_LEFT:
3749         theDI << "Left\n";
3750         break;
3751       case Aspect_TOCSP_RIGHT:
3752         theDI << "Right\n";
3753         break;
3754       case Aspect_TOCSP_CENTER:
3755         theDI << "Center\n";
3756         break;
3757     }
3758     return 0;
3759   }
3760
3761   if (aColorScale.IsNull())
3762   {
3763     aColorScale = new AIS_ColorScale();
3764     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3765     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3766   }
3767
3768   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3769   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3770   {
3771     Standard_CString        anArg = theArgVec[anArgIter];
3772     TCollection_AsciiString aFlag (anArg);
3773     aFlag.LowerCase();
3774     if (anUpdateTool.parseRedrawMode (aFlag))
3775     {
3776       continue;
3777     }
3778     else if (aFlag == "-range")
3779     {
3780       if (anArgIter + 3 >= theArgNb)
3781       {
3782         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3783         return 1;
3784       }
3785
3786       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3787       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3788       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3789       if (!aRangeMin.IsRealValue()
3790        || !aRangeMax.IsRealValue())
3791       {
3792         std::cout << "Error: the range values should be real!\n";
3793         return 1;
3794       }
3795       else if (!aNbIntervals.IsIntegerValue())
3796       {
3797         std::cout << "Error: the number of intervals should be integer!\n";
3798         return 1;
3799       }
3800
3801       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3802       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3803     }
3804     else if (aFlag == "-font")
3805     {
3806       if (anArgIter + 1 >= theArgNb)
3807       {
3808         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3809         return 1;
3810       }
3811       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3812       if (!aFontArg.IsIntegerValue())
3813       {
3814         std::cout << "Error: HeightFont value should be integer!\n";
3815         return 1;
3816       }
3817
3818       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3819       anArgIter += 1;
3820     }
3821     else if (aFlag == "-textpos")
3822     {
3823       if (anArgIter + 1 >= theArgNb)
3824       {
3825         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3826         return 1;
3827       }
3828
3829       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3830       aTextPosArg.LowerCase();
3831       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3832       if (aTextPosArg == "none")
3833       {
3834         aLabPosition = Aspect_TOCSP_NONE;
3835       }
3836       else if (aTextPosArg == "left")
3837       {
3838         aLabPosition = Aspect_TOCSP_LEFT;
3839       }
3840       else if (aTextPosArg == "right")
3841       {
3842         aLabPosition = Aspect_TOCSP_RIGHT;
3843       }
3844       else if (aTextPosArg == "center")
3845       {
3846         aLabPosition = Aspect_TOCSP_CENTER;
3847       }
3848       else
3849       {
3850         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3851         return 1;
3852       }
3853       aColorScale->SetLabelPosition (aLabPosition);
3854     }
3855     else if (aFlag == "-logarithmic"
3856           || aFlag == "-log")
3857     {
3858       if (anArgIter + 1 >= theArgNb)
3859       {
3860         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3861         return 1;
3862       }
3863
3864       Standard_Boolean IsLog;
3865       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3866       {
3867         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3868         return 1;
3869       }
3870       aColorScale->SetLogarithmic (IsLog);
3871     }
3872     else if (aFlag == "-huerange"
3873           || aFlag == "-hue")
3874     {
3875       if (anArgIter + 2 >= theArgNb)
3876       {
3877         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3878         return 1;
3879       }
3880
3881       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3882       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3883       aColorScale->SetHueRange (aHueMin, aHueMax);
3884     }
3885     else if (aFlag == "-colorrange")
3886     {
3887       Quantity_Color aColorMin, aColorMax;
3888       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3889                                                             theArgVec + (anArgIter + 1),
3890                                                             aColorMin);
3891       anArgIter += aNbParsed1;
3892       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3893                                                             theArgVec + (anArgIter + 1),
3894                                                             aColorMax);
3895       anArgIter += aNbParsed2;
3896       if (aNbParsed1 == 0
3897        || aNbParsed2 == 0)
3898       {
3899         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3900         return 1;
3901       }
3902
3903       aColorScale->SetColorRange (aColorMin, aColorMax);
3904     }
3905     else if (aFlag == "-reversed"
3906           || aFlag == "-inverted"
3907           || aFlag == "-topdown"
3908           || aFlag == "-bottomup")
3909     {
3910       Standard_Boolean toEnable = Standard_True;
3911       if (anArgIter + 1 < theArgNb
3912        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3913       {
3914         ++anArgIter;
3915       }
3916       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3917     }
3918     else if (aFlag == "-smooth"
3919           || aFlag == "-smoothtransition")
3920     {
3921       Standard_Boolean toEnable = Standard_True;
3922       if (anArgIter + 1 < theArgNb
3923        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3924       {
3925         ++anArgIter;
3926       }
3927       aColorScale->SetSmoothTransition (toEnable);
3928     }
3929     else if (aFlag == "-xy")
3930     {
3931       if (anArgIter + 2 >= theArgNb)
3932       {
3933         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3934         return 1;
3935       }
3936
3937       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3938       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3939       if (!anX.IsIntegerValue()
3940        || !anY.IsIntegerValue())
3941       {
3942         std::cout << "Error: coordinates should be integer values!\n";
3943         return 1;
3944       }
3945
3946       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3947     }
3948     else if (aFlag == "-width"
3949           || aFlag == "-w"
3950           || aFlag == "-breadth")
3951     {
3952       if (anArgIter + 1 >= theArgNb)
3953       {
3954         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3955         return 1;
3956       }
3957
3958       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3959       if (!aBreadth.IsIntegerValue())
3960       {
3961         std::cout << "Error: a width should be an integer value!\n";
3962         return 1;
3963       }
3964       aColorScale->SetBreadth (aBreadth.IntegerValue());
3965     }
3966     else if (aFlag == "-height"
3967           || aFlag == "-h")
3968     {
3969       if (anArgIter + 1 >= theArgNb)
3970       {
3971         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3972         return 1;
3973       }
3974
3975       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3976       if (!aHeight.IsIntegerValue())
3977       {
3978         std::cout << "Error: a width should be an integer value!\n";
3979         return 1;
3980       }
3981       aColorScale->SetHeight (aHeight.IntegerValue());
3982     }
3983     else if (aFlag == "-color")
3984     {
3985       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3986       {
3987         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3988         return 1;
3989       }
3990       else if (anArgIter + 2 >= theArgNb)
3991       {
3992         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3993         return 1;
3994       }
3995
3996       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3997       if (!anInd.IsIntegerValue())
3998       {
3999         std::cout << "Error: Index value should be integer!\n";
4000         return 1;
4001       }
4002       const Standard_Integer anIndex = anInd.IntegerValue();
4003       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
4004       {
4005         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
4006         return 1;
4007       }
4008
4009       Quantity_Color aColor;
4010       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4011                                                            theArgVec + (anArgIter + 1),
4012                                                            aColor);
4013       if (aNbParsed == 0)
4014       {
4015         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4016         return 1;
4017       }
4018       aColorScale->SetIntervalColor (aColor, anIndex);
4019       aColorScale->SetColorType (Aspect_TOCSD_USER);
4020       anArgIter += aNbParsed;
4021     }
4022     else if (aFlag == "-label")
4023     {
4024       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4025       {
4026         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4027         return 1;
4028       }
4029       else if (anArgIter + 2 >= theArgNb)
4030       {
4031         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4032         return 1;
4033       }
4034
4035       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4036       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4037       {
4038         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4039         return 1;
4040       }
4041
4042       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4043       aColorScale->SetLabel     (aText, anIndex);
4044       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4045       anArgIter += 2;
4046     }
4047     else if (aFlag == "-labelat"
4048           || aFlag == "-labat"
4049           || aFlag == "-labelatborder"
4050           || aFlag == "-labatborder"
4051           || aFlag == "-labelatcenter"
4052           || aFlag == "-labatcenter")
4053     {
4054       Standard_Boolean toEnable = Standard_True;
4055       if (aFlag == "-labelat"
4056        || aFlag == "-labat")
4057       {
4058         Standard_Integer aLabAtBorder = -1;
4059         if (++anArgIter >= theArgNb)
4060         {
4061           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4062           anAtBorder.LowerCase();
4063           if (anAtBorder == "border")
4064           {
4065             aLabAtBorder = 1;
4066           }
4067           else if (anAtBorder == "center")
4068           {
4069             aLabAtBorder = 0;
4070           }
4071         }
4072         if (aLabAtBorder == -1)
4073         {
4074           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4075           return 1;
4076         }
4077         toEnable = (aLabAtBorder == 1);
4078       }
4079       else if (anArgIter + 1 < theArgNb
4080             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4081       {
4082         ++anArgIter;
4083       }
4084       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4085                                   || aFlag == "-labatcenter"
4086                                    ? !toEnable
4087                                    :  toEnable);
4088     }
4089     else if (aFlag == "-colors")
4090     {
4091       Aspect_SequenceOfColor aSeq;
4092       for (;;)
4093       {
4094         Quantity_Color aColor;
4095         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4096                                                              theArgVec + (anArgIter + 1),
4097                                                              aColor);
4098         if (aNbParsed == 0)
4099         {
4100           break;
4101         }
4102         anArgIter += aNbParsed;
4103         aSeq.Append (aColor);
4104       }
4105       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4106       {
4107         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4108                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4109         return 1;
4110       }
4111
4112       aColorScale->SetColors    (aSeq);
4113       aColorScale->SetColorType (Aspect_TOCSD_USER);
4114     }
4115     else if (aFlag == "-labels"
4116           || aFlag == "-freelabels")
4117     {
4118       if (anArgIter + 1 >= theArgNb)
4119       {
4120         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4121         return 1;
4122       }
4123
4124       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4125                                  ? aColorScale->GetNumberOfIntervals() + 1
4126                                  : aColorScale->GetNumberOfIntervals();
4127       if (aFlag == "-freelabels")
4128       {
4129         ++anArgIter;
4130         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4131       }
4132       if (anArgIter + aNbLabels >= theArgNb)
4133       {
4134         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4135         return 1;
4136       }
4137
4138       TColStd_SequenceOfExtendedString aSeq;
4139       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4140       {
4141         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4142       }
4143       aColorScale->SetLabels (aSeq);
4144       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4145     }
4146     else if (aFlag == "-title")
4147     {
4148       if (anArgIter + 1 >= theArgNb)
4149       {
4150         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4151         return 1;
4152       }
4153
4154       Standard_Boolean isTwoArgs = Standard_False;
4155       if (anArgIter + 2 < theArgNb)
4156       {
4157         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4158         aSecondArg.LowerCase();
4159       Standard_DISABLE_DEPRECATION_WARNINGS
4160         if (aSecondArg == "none")
4161         {
4162           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4163           isTwoArgs = Standard_True;
4164         }
4165         else if (aSecondArg == "left")
4166         {
4167           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4168           isTwoArgs = Standard_True;
4169         }
4170         else if (aSecondArg == "right")
4171         {
4172           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4173           isTwoArgs = Standard_True;
4174         }
4175         else if (aSecondArg == "center")
4176         {
4177           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4178           isTwoArgs = Standard_True;
4179         }
4180       Standard_ENABLE_DEPRECATION_WARNINGS
4181       }
4182
4183       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4184       if (isTwoArgs)
4185       {
4186         anArgIter += 1;
4187       }
4188       anArgIter += 1;
4189     }
4190     else if (aFlag == "-demoversion"
4191           || aFlag == "-demo")
4192     {
4193       aColorScale->SetPosition (0, 0);
4194       aColorScale->SetTextHeight (16);
4195       aColorScale->SetRange (0.0, 100.0);
4196       aColorScale->SetNumberOfIntervals (10);
4197       aColorScale->SetBreadth (0);
4198       aColorScale->SetHeight  (0);
4199       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4200       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4201       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4202     }
4203     else if (aFlag == "-findcolor")
4204     {
4205       if (anArgIter + 1 >= theArgNb)
4206       {
4207         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4208         return 1;
4209       }
4210
4211       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4212
4213       if (!anArg1.IsRealValue())
4214       {
4215         std::cout << "Error: the value should be real!\n";
4216         return 1;
4217       }
4218
4219       Quantity_Color aColor;
4220       aColorScale->FindColor (anArg1.RealValue(), aColor);
4221       theDI << Quantity_Color::StringName (aColor.Name());
4222       return 0;
4223     }
4224     else
4225     {
4226       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4227       return 1;
4228     }
4229   }
4230
4231   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4232   aView->Window()->Size (aWinWidth, aWinHeight);
4233   if (aColorScale->GetBreadth() == 0)
4234   {
4235     aColorScale->SetBreadth (aWinWidth);
4236   }
4237   if (aColorScale->GetHeight() == 0)
4238   {
4239     aColorScale->SetHeight (aWinHeight);
4240   }
4241   aColorScale->SetToUpdate();
4242   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4243   return 0;
4244 }
4245
4246 //==============================================================================
4247 //function : VGraduatedTrihedron
4248 //purpose  : Displays or hides a graduated trihedron
4249 //==============================================================================
4250 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4251                                   Quantity_Color& theColor)
4252 {
4253   Quantity_NameOfColor aColorName;
4254   TCollection_AsciiString aVal = theValue;
4255   aVal.UpperCase();
4256   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4257   {
4258     return Standard_False;
4259   }
4260   theColor = Quantity_Color (aColorName);
4261   return Standard_True;
4262 }
4263
4264 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4265 {
4266   if (theArgNum < 2)
4267   {
4268     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4269               << theArgs[0] <<"' for more information.\n";
4270     return 1;  //TCL_ERROR
4271   }
4272
4273   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4274   TCollection_AsciiString aParseKey;
4275   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4276   {
4277     TCollection_AsciiString anArg (theArgs [anArgIt]);
4278
4279     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4280     {
4281       aParseKey = anArg;
4282       aParseKey.Remove (1);
4283       aParseKey.LowerCase();
4284       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4285       continue;
4286     }
4287
4288     if (aParseKey.IsEmpty())
4289     {
4290       continue;
4291     }
4292
4293     aMapOfArgs(aParseKey)->Append (anArg);
4294   }
4295
4296   // Check parameters
4297   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4298        aMapIt.More(); aMapIt.Next())
4299   {
4300     const TCollection_AsciiString& aKey = aMapIt.Key();
4301     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4302
4303     // Bool key, without arguments
4304     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4305         && anArgs->IsEmpty())
4306     {
4307       continue;
4308     }
4309
4310     // One argument
4311     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4312           && anArgs->Length() == 1)
4313     {
4314       continue;
4315     }
4316
4317     // On/off arguments
4318     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4319         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4320         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4321         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4322         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4323     {
4324       continue;
4325     }
4326
4327     // One string argument
4328     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4329           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4330           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4331     {
4332       continue;
4333     }
4334
4335     // One integer argument
4336     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4337           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4338           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4339           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4340          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4341     {
4342       continue;
4343     }
4344
4345     // One real argument
4346     if ( aKey.IsEqual ("arrowlength")
4347          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4348     {
4349       continue;
4350     }
4351
4352     // Two string arguments
4353     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4354          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4355     {
4356       continue;
4357     }
4358
4359     TCollection_AsciiString aLowerKey;
4360     aLowerKey  = "-";
4361     aLowerKey += aKey;
4362     aLowerKey.LowerCase();
4363     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4364     std::cout << "Type help for more information.\n";
4365     return 1;
4366   }
4367
4368   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4369   if (anAISContext.IsNull())
4370   {
4371     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4372     return 1;
4373   }
4374
4375   Standard_Boolean toDisplay = Standard_True;
4376   Quantity_Color aColor;
4377   Graphic3d_GraduatedTrihedron aTrihedronData;
4378   // Process parameters
4379   Handle(TColStd_HSequenceOfAsciiString) aValues;
4380   if (aMapOfArgs.Find ("off", aValues))
4381   {
4382     toDisplay = Standard_False;
4383   }
4384
4385   // AXES NAMES
4386   if (aMapOfArgs.Find ("xname", aValues))
4387   {
4388     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4389   }
4390   if (aMapOfArgs.Find ("yname", aValues))
4391   {
4392     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4393   }
4394   if (aMapOfArgs.Find ("zname", aValues))
4395   {
4396     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4397   }
4398   if (aMapOfArgs.Find ("xdrawname", aValues))
4399   {
4400     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4401   }
4402   if (aMapOfArgs.Find ("ydrawname", aValues))
4403   {
4404     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4405   }
4406   if (aMapOfArgs.Find ("zdrawname", aValues))
4407   {
4408     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4409   }
4410   if (aMapOfArgs.Find ("xnameoffset", aValues))
4411   {
4412     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4413   }
4414   if (aMapOfArgs.Find ("ynameoffset", aValues))
4415   {
4416     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4417   }
4418   if (aMapOfArgs.Find ("znameoffset", aValues))
4419   {
4420     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4421   }
4422
4423   // COLORS
4424   if (aMapOfArgs.Find ("xnamecolor", aValues))
4425   {
4426     if (!GetColor (aValues->Value(1), aColor))
4427     {
4428       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4429       return 1;
4430     }
4431     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4432   }
4433   if (aMapOfArgs.Find ("ynamecolor", aValues))
4434   {
4435     if (!GetColor (aValues->Value(1), aColor))
4436     {
4437       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4438       return 1;
4439     }
4440     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4441   }
4442   if (aMapOfArgs.Find ("znamecolor", aValues))
4443   {
4444     if (!GetColor (aValues->Value(1), aColor))
4445     {
4446       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4447       return 1;
4448     }
4449     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4450   }
4451   if (aMapOfArgs.Find ("xcolor", aValues))
4452   {
4453     if (!GetColor (aValues->Value(1), aColor))
4454     {
4455       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4456       return 1;
4457     }
4458     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4459   }
4460   if (aMapOfArgs.Find ("ycolor", aValues))
4461   {
4462     if (!GetColor (aValues->Value(1), aColor))
4463     {
4464       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4465       return 1;
4466     }
4467     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4468   }
4469   if (aMapOfArgs.Find ("zcolor", aValues))
4470   {
4471     if (!GetColor (aValues->Value(1), aColor))
4472     {
4473       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4474       return 1;
4475     }
4476     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4477   }
4478
4479   // TICKMARKS
4480   if (aMapOfArgs.Find ("xticks", aValues))
4481   {
4482     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4483   }
4484   if (aMapOfArgs.Find ("yticks", aValues))
4485   {
4486     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4487   }
4488   if (aMapOfArgs.Find ("zticks", aValues))
4489   {
4490     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4491   }
4492   if (aMapOfArgs.Find ("xticklength", aValues))
4493   {
4494     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4495   }
4496   if (aMapOfArgs.Find ("yticklength", aValues))
4497   {
4498     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4499   }
4500   if (aMapOfArgs.Find ("zticklength", aValues))
4501   {
4502     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4503   }
4504   if (aMapOfArgs.Find ("xdrawticks", aValues))
4505   {
4506     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4507   }
4508   if (aMapOfArgs.Find ("ydrawticks", aValues))
4509   {
4510     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4511   }
4512   if (aMapOfArgs.Find ("zdrawticks", aValues))
4513   {
4514     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4515   }
4516
4517   // VALUES
4518   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4519   {
4520     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4521   }
4522   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4523   {
4524     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4525   }
4526   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4527   {
4528     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4529   }
4530   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4531   {
4532     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4533   }
4534   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4535   {
4536     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4537   }
4538   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4539   {
4540     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4541   }
4542
4543   // ARROWS
4544   if (aMapOfArgs.Find ("arrowlength", aValues))
4545   {
4546     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4547   }
4548
4549   // FONTS
4550   if (aMapOfArgs.Find ("namefont", aValues))
4551   {
4552     aTrihedronData.SetNamesFont (aValues->Value(1));
4553   }
4554   if (aMapOfArgs.Find ("valuesfont", aValues))
4555   {
4556     aTrihedronData.SetValuesFont (aValues->Value(1));
4557   }
4558
4559   if (aMapOfArgs.Find ("drawgrid", aValues))
4560   {
4561     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4562   }
4563   if (aMapOfArgs.Find ("drawaxes", aValues))
4564   {
4565     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4566   }
4567
4568   // The final step: display of erase trihedron
4569   if (toDisplay)
4570   {
4571     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4572   }
4573   else
4574   {
4575     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4576   }
4577
4578   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4579   ViewerTest::CurrentView()->Redraw();
4580
4581   return 0;
4582 }
4583
4584 //==============================================================================
4585 //function : VTile
4586 //purpose  :
4587 //==============================================================================
4588 static int VTile (Draw_Interpretor& theDI,
4589                   Standard_Integer  theArgNb,
4590                   const char**      theArgVec)
4591 {
4592   Handle(V3d_View) aView = ViewerTest::CurrentView();
4593   if (aView.IsNull())
4594   {
4595     std::cerr << "Error: no active viewer.\n";
4596     return 1;
4597   }
4598
4599   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4600   if (theArgNb < 2)
4601   {
4602     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4603           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4604           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4605     return 0;
4606   }
4607
4608   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4609   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4610   {
4611     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4612     anArg.LowerCase();
4613     if (anArg == "-lowerleft"
4614      || anArg == "-upperleft")
4615     {
4616       if (anArgIter + 3 < theArgNb)
4617       {
4618         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4619         return 1;
4620       }
4621       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4622       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4623       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4624     }
4625     else if (anArg == "-total"
4626           || anArg == "-totalsize"
4627           || anArg == "-viewsize")
4628     {
4629       if (anArgIter + 3 < theArgNb)
4630       {
4631         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4632         return 1;
4633       }
4634       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4635       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4636       if (aTile.TotalSize.x() < 1
4637        || aTile.TotalSize.y() < 1)
4638       {
4639         std::cerr << "Error: total size is incorrect.\n";
4640         return 1;
4641       }
4642     }
4643     else if (anArg == "-tilesize")
4644     {
4645       if (anArgIter + 3 < theArgNb)
4646       {
4647         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4648         return 1;
4649       }
4650
4651       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4652       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4653       if (aTile.TileSize.x() < 1
4654        || aTile.TileSize.y() < 1)
4655       {
4656         std::cerr << "Error: tile size is incorrect.\n";
4657         return 1;
4658       }
4659     }
4660     else if (anArg == "-unset")
4661     {
4662       aView->Camera()->SetTile (Graphic3d_CameraTile());
4663       aView->Redraw();
4664       return 0;
4665     }
4666   }
4667
4668   if (aTile.TileSize.x() < 1
4669    || aTile.TileSize.y() < 1)
4670   {
4671     std::cerr << "Error: tile size is undefined.\n";
4672     return 1;
4673   }
4674   else if (aTile.TotalSize.x() < 1
4675         || aTile.TotalSize.y() < 1)
4676   {
4677     std::cerr << "Error: total size is undefined.\n";
4678     return 1;
4679   }
4680
4681   aView->Camera()->SetTile (aTile);
4682   aView->Redraw();
4683   return 0;
4684 }
4685
4686 //! Format ZLayer ID.
4687 inline const char* formZLayerId (const Standard_Integer theLayerId)
4688 {
4689   switch (theLayerId)
4690   {
4691     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4692     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4693     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4694     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4695     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4696     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4697   }
4698   return "";
4699 }
4700
4701 //! Print the ZLayer information.
4702 inline void printZLayerInfo (Draw_Interpretor& theDI,
4703                              const Graphic3d_ZLayerSettings& theLayer)
4704 {
4705   if (!theLayer.Name().IsEmpty())
4706   {
4707     theDI << "  Name: " << theLayer.Name() << "\n";
4708   }
4709   if (theLayer.IsImmediate())
4710   {
4711     theDI << "  Immediate: TRUE\n";
4712   }
4713   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4714   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
4715   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
4716   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4717   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4718   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4719   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4720   {
4721     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4722   }
4723 }
4724
4725 //==============================================================================
4726 //function : VZLayer
4727 //purpose  : Test z layer operations for v3d viewer
4728 //==============================================================================
4729 static int VZLayer (Draw_Interpretor& theDI,
4730                     Standard_Integer  theArgNb,
4731                     const char**      theArgVec)
4732 {
4733   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4734   if (aContextAIS.IsNull())
4735   {
4736     std::cout << "No active viewer!\n";
4737     return 1;
4738   }
4739
4740   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4741   if (theArgNb < 2)
4742   {
4743     TColStd_SequenceOfInteger aLayers;
4744     aViewer->GetAllZLayers (aLayers);
4745     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4746     {
4747       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4748       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4749       printZLayerInfo (theDI, aSettings);
4750     }
4751     return 1;
4752   }
4753
4754   Standard_Integer anArgIter = 1;
4755   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4756   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4757   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4758   {
4759     ++anArgIter;
4760   }
4761
4762   {
4763     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4764     if (aFirstArg.IsIntegerValue())
4765     {
4766       ++anArgIter;
4767       aLayerId = aFirstArg.IntegerValue();
4768     }
4769     else
4770     {
4771       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
4772       {
4773         ++anArgIter;
4774       }
4775     }
4776   }
4777
4778   for (; anArgIter < theArgNb; ++anArgIter)
4779   {
4780     // perform operation
4781     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4782     anArg.LowerCase();
4783     if (anUpdateTool.parseRedrawMode (anArg))
4784     {
4785       //
4786     }
4787     else if (anArg == "-add"
4788           || anArg == "add")
4789     {
4790       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4791       if (!aViewer->AddZLayer (aLayerId))
4792       {
4793         std::cout << "Error: can not add a new z layer!\n";
4794         return 0;
4795       }
4796
4797       theDI << aLayerId;
4798     }
4799     else if (anArg == "-del"
4800           || anArg == "-delete"
4801           || anArg == "del")
4802     {
4803       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4804       {
4805         if (++anArgIter >= theArgNb)
4806         {
4807           std::cout << "Syntax error: id of z layer to remove is missing\n";
4808           return 1;
4809         }
4810
4811         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4812       }
4813
4814       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4815        || aLayerId == Graphic3d_ZLayerId_Default
4816        || aLayerId == Graphic3d_ZLayerId_Top
4817        || aLayerId == Graphic3d_ZLayerId_Topmost
4818        || aLayerId == Graphic3d_ZLayerId_TopOSD
4819        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4820       {
4821         std::cout << "Syntax error: standard Z layer can not be removed\n";
4822         return 1;
4823       }
4824
4825       // move all object displayed in removing layer to default layer
4826       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4827            anObjIter.More(); anObjIter.Next())
4828       {
4829         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
4830         if (aPrs.IsNull()
4831          || aPrs->ZLayer() != aLayerId)
4832         {
4833           continue;
4834         }
4835         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4836       }
4837
4838       if (!aViewer->RemoveZLayer (aLayerId))
4839       {
4840         std::cout << "Z layer can not be removed!\n";
4841       }
4842       else
4843       {
4844         theDI << aLayerId << " ";
4845       }
4846     }
4847     else if (anArg == "-get"
4848           || anArg == "get")
4849     {
4850       TColStd_SequenceOfInteger aLayers;
4851       aViewer->GetAllZLayers (aLayers);
4852       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4853       {
4854         theDI << aLayeriter.Value() << " ";
4855       }
4856
4857       theDI << "\n";
4858     }
4859     else if (anArg == "-name")
4860     {
4861       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4862       {
4863         std::cout << "Syntax error: id of Z layer is missing\n";
4864         return 1;
4865       }
4866
4867       if (++anArgIter >= theArgNb)
4868       {
4869         std::cout << "Syntax error: name is missing\n";
4870         return 1;
4871       }
4872
4873       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4874       aSettings.SetName (theArgVec[anArgIter]);
4875       aViewer->SetZLayerSettings (aLayerId, aSettings);
4876     }
4877     else if (anArg == "-origin")
4878     {
4879       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4880       {
4881         std::cout << "Syntax error: id of Z layer is missing\n";
4882         return 1;
4883       }
4884
4885       if (anArgIter + 2 >= theArgNb)
4886       {
4887         std::cout << "Syntax error: origin coordinates are missing\n";
4888         return 1;
4889       }
4890
4891       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4892       gp_XYZ anOrigin;
4893       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4894       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4895       anOrigin.SetZ (0.0);
4896       if (anArgIter + 3 < theArgNb)
4897       {
4898         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4899         anArgIter += 3;
4900       }
4901       else
4902       {
4903         anArgIter += 2;
4904       }
4905       aSettings.SetOrigin (anOrigin);
4906       aViewer->SetZLayerSettings (aLayerId, aSettings);
4907     }
4908     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4909           && anArgIter + 1 < theArgNb
4910           && (anArg == "-cullingdistance"
4911            || anArg == "-cullingdist"
4912            || anArg == "-culldistance"
4913            || anArg == "-culldist"
4914            || anArg == "-distcull"
4915            || anArg == "-distculling"
4916            || anArg == "-distanceculling"))
4917     {
4918       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4919       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
4920       aSettings.SetCullingDistance (aDist);
4921       aViewer->SetZLayerSettings (aLayerId, aSettings);
4922     }
4923     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4924           && anArgIter + 1 < theArgNb
4925           && (anArg == "-cullingsize"
4926            || anArg == "-cullsize"
4927            || anArg == "-sizecull"
4928            || anArg == "-sizeculling"))
4929     {
4930       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4931       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
4932       aSettings.SetCullingSize (aSize);
4933       aViewer->SetZLayerSettings (aLayerId, aSettings);
4934     }
4935     else if (anArg == "-settings"
4936           || anArg == "settings")
4937     {
4938       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4939       {
4940         if (++anArgIter >= theArgNb)
4941         {
4942           std::cout << "Syntax error: id of Z layer is missing\n";
4943           return 1;
4944         }
4945
4946         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4947       }
4948
4949       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4950       printZLayerInfo (theDI, aSettings);
4951     }
4952     else if (anArg == "-enable"
4953           || anArg == "enable"
4954           || anArg == "-disable"
4955           || anArg == "disable")
4956     {
4957       const Standard_Boolean toEnable = anArg == "-enable"
4958                                      || anArg == "enable";
4959       if (++anArgIter >= theArgNb)
4960       {
4961         std::cout << "Syntax error: option name is missing\n";
4962         return 1;
4963       }
4964
4965       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4966       aSubOp.LowerCase();
4967       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4968       {
4969         if (++anArgIter >= theArgNb)
4970         {
4971           std::cout << "Syntax error: id of Z layer is missing\n";
4972           return 1;
4973         }
4974
4975         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4976       }
4977
4978       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4979       if (aSubOp == "depthtest"
4980        || aSubOp == "test")
4981       {
4982         aSettings.SetEnableDepthTest (toEnable);
4983       }
4984       else if (aSubOp == "depthwrite"
4985             || aSubOp == "write")
4986       {
4987         aSettings.SetEnableDepthWrite (toEnable);
4988       }
4989       else if (aSubOp == "depthclear"
4990             || aSubOp == "clear")
4991       {
4992         aSettings.SetClearDepth (toEnable);
4993       }
4994       else if (aSubOp == "depthoffset"
4995             || aSubOp == "offset")
4996       {
4997         Graphic3d_PolygonOffset aParams;
4998         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4999         if (toEnable)
5000         {
5001           if (anArgIter + 2 >= theArgNb)
5002           {
5003             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5004             return 1;
5005           }
5006
5007           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5008           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5009         }
5010         aSettings.SetPolygonOffset (aParams);
5011       }
5012       else if (aSubOp == "positiveoffset"
5013             || aSubOp == "poffset")
5014       {
5015         if (toEnable)
5016         {
5017           aSettings.SetDepthOffsetPositive();
5018         }
5019         else
5020         {
5021           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5022         }
5023       }
5024       else if (aSubOp == "negativeoffset"
5025             || aSubOp == "noffset")
5026       {
5027         if (toEnable)
5028         {
5029           aSettings.SetDepthOffsetNegative();
5030         }
5031         else
5032         {
5033           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5034         }
5035       }
5036       else if (aSubOp == "textureenv")
5037       {
5038         aSettings.SetEnvironmentTexture (toEnable);
5039       }
5040
5041       aViewer->SetZLayerSettings (aLayerId, aSettings);
5042     }
5043     else
5044     {
5045       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5046       return 1;
5047     }
5048   }
5049
5050   return 0;
5051 }
5052
5053 // The interactive presentation of 2d layer item
5054 // for "vlayerline" command it provides a presentation of
5055 // line with user-defined linewidth, linetype and transparency.
5056 class V3d_LineItem : public AIS_InteractiveObject
5057 {
5058 public:
5059   // CASCADE RTTI
5060   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5061
5062   // constructor
5063   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5064                                Standard_Real X2, Standard_Real Y2,
5065                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5066                                Standard_Real theWidth    = 0.5,
5067                                Standard_Real theTransp   = 1.0);
5068
5069   private:
5070
5071   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5072                 const Handle(Prs3d_Presentation)& thePresentation,
5073                 const Standard_Integer theMode) Standard_OVERRIDE;
5074
5075   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5076                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5077   {}
5078
5079 private:
5080
5081   Standard_Real       myX1, myY1, myX2, myY2;
5082   Aspect_TypeOfLine   myType;
5083   Standard_Real       myWidth;
5084 };
5085
5086 // default constructor for line item
5087 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5088                            Standard_Real X2, Standard_Real Y2,
5089                            Aspect_TypeOfLine theType,
5090                            Standard_Real theWidth,
5091                            Standard_Real theTransp) :
5092   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5093   myType(theType), myWidth(theWidth)
5094 {
5095   SetTransparency (1-theTransp);
5096 }
5097
5098 // render line
5099 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5100                             const Handle(Prs3d_Presentation)& thePresentation,
5101                             const Standard_Integer /*theMode*/)
5102 {
5103   thePresentation->Clear();
5104   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5105   Standard_Integer aWidth, aHeight;
5106   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5107   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5108   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5109   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5110   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5111   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5112   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5113   aGroup->AddPrimitiveArray (aPrim);
5114 }
5115
5116 //=============================================================================
5117 //function : VLayerLine
5118 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5119 //         : linewidth, transparency coefficient
5120 //============================================================================
5121 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5122 {
5123   // get the active view
5124   Handle(V3d_View) aView = ViewerTest::CurrentView();
5125   if (aView.IsNull())
5126   {
5127     di << "Call vinit before!\n";
5128     return 1;
5129   }
5130   else if (argc < 5)
5131   {
5132     di << "Use: " << argv[0];
5133     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5134     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5135     di << "              0 - solid  \n";
5136     di << "              1 - dashed \n";
5137     di << "              2 - dot    \n";
5138     di << "              3 - dashdot\n";
5139     di << " transparency : { 0.0 - 1.0 } \n";
5140     di << "                  0.0 - transparent\n";
5141     di << "                  1.0 - visible    \n";
5142     return 1;
5143   }
5144
5145   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5146   // get the input params
5147   Standard_Real X1 = Draw::Atof(argv[1]);
5148   Standard_Real Y1 = Draw::Atof(argv[2]);
5149   Standard_Real X2 = Draw::Atof(argv[3]);
5150   Standard_Real Y2 = Draw::Atof(argv[4]);
5151
5152   Standard_Real aWidth = 0.5;
5153   Standard_Real aTransparency = 1.0;
5154
5155   // has width
5156   if (argc > 5)
5157     aWidth = Draw::Atof(argv[5]);
5158
5159   // select appropriate line type
5160   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5161   if (argc > 6
5162   && !ViewerTest::ParseLineType (argv[6], aLineType))
5163   {
5164     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5165     return 1;
5166   }
5167
5168   // has transparency
5169   if (argc > 7)
5170   {
5171     aTransparency = Draw::Atof(argv[7]);
5172     if (aTransparency < 0 || aTransparency > 1.0)
5173       aTransparency = 1.0;
5174   }
5175
5176   static Handle (V3d_LineItem) aLine;
5177   if (!aLine.IsNull())
5178   {
5179     aContext->Erase (aLine, Standard_False);
5180   }
5181   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5182                             aLineType, aWidth,
5183                             aTransparency);
5184
5185   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5186   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5187   aLine->SetToUpdate();
5188   aContext->Display (aLine, Standard_True);
5189
5190   return 0;
5191 }
5192
5193
5194 //==============================================================================
5195 //function : VGrid
5196 //purpose  :
5197 //==============================================================================
5198
5199 static int VGrid (Draw_Interpretor& /*theDI*/,
5200                   Standard_Integer  theArgNb,
5201                   const char**      theArgVec)
5202 {
5203   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5204   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5205   if (aView.IsNull() || aViewer.IsNull())
5206   {
5207     std::cerr << "Error: no active view\n";
5208     return 1;
5209   }
5210
5211   Aspect_GridType     aType = aViewer->GridType();
5212   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5213   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5214   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5215   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
5216   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5217   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5218   {
5219     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5220     anArg.LowerCase();
5221     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5222     {
5223       continue;
5224     }
5225     else if (anArgIter + 1 < theArgNb
5226           && anArg == "-type")
5227     {
5228       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5229       anArgNext.LowerCase();
5230       if (anArgNext == "r"
5231        || anArgNext == "rect"
5232        || anArgNext == "rectangular")
5233       {
5234         aType = Aspect_GT_Rectangular;
5235       }
5236       else if (anArgNext == "c"
5237             || anArgNext == "circ"
5238             || anArgNext == "circular")
5239       {
5240         aType = Aspect_GT_Circular;
5241       }
5242       else
5243       {
5244         std::cout << "Syntax error at '" << anArgNext << "'\n";
5245         return 1;
5246       }
5247     }
5248     else if (anArgIter + 1 < theArgNb
5249           && anArg == "-mode")
5250     {
5251       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5252       anArgNext.LowerCase();
5253       if (anArgNext == "l"
5254        || anArgNext == "line"
5255        || anArgNext == "lines")
5256       {
5257         aMode = Aspect_GDM_Lines;
5258       }
5259       else if (anArgNext == "p"
5260             || anArgNext == "point"
5261             || anArgNext == "points")
5262       {
5263         aMode = Aspect_GDM_Points;
5264       }
5265       else
5266       {
5267         std::cout << "Syntax error at '" << anArgNext << "'\n";
5268         return 1;
5269       }
5270     }
5271     else if (anArgIter + 2 < theArgNb
5272           && (anArg == "-origin"
5273            || anArg == "-orig"))
5274     {
5275       hasOrigin = true;
5276       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5277                               Draw::Atof (theArgVec[anArgIter + 2]));
5278       anArgIter += 2;
5279     }
5280     else if (anArgIter + 2 < theArgNb
5281           && anArg == "-step")
5282     {
5283       hasStep = true;
5284       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5285                             Draw::Atof (theArgVec[anArgIter + 2]));
5286       if (aNewStepXY.x() <= 0.0
5287        || aNewStepXY.y() <= 0.0)
5288       {
5289         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5290         return 1;
5291       }
5292       anArgIter += 2;
5293     }
5294     else if (anArgIter + 1 < theArgNb
5295           && (anArg == "-angle"
5296            || anArg == "-rotangle"
5297            || anArg == "-rotationangle"))
5298     {
5299       hasRotAngle = true;
5300       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
5301     }
5302     else if (anArgIter + 1 < theArgNb
5303           && (anArg == "-zoffset"
5304            || anArg == "-dz"))
5305     {
5306       hasZOffset = true;
5307       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
5308     }
5309     else if (anArgIter + 1 < theArgNb
5310           && anArg == "-radius")
5311     {
5312       hasSize = true;
5313       ++anArgIter;
5314       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
5315       if (aNewStepXY.x() <= 0.0)
5316       {
5317         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
5318         return 1;
5319       }
5320     }
5321     else if (anArgIter + 2 < theArgNb
5322           && anArg == "-size")
5323     {
5324       hasSize = true;
5325       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5326                             Draw::Atof (theArgVec[anArgIter + 2]));
5327       if (aNewStepXY.x() <= 0.0
5328        || aNewStepXY.y() <= 0.0)
5329       {
5330         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5331         return 1;
5332       }
5333       anArgIter += 2;
5334     }
5335     else if (anArg == "r"
5336           || anArg == "rect"
5337           || anArg == "rectangular")
5338     {
5339       aType = Aspect_GT_Rectangular;
5340     }
5341     else if (anArg == "c"
5342           || anArg == "circ"
5343           || anArg == "circular")
5344     {
5345       aType = Aspect_GT_Circular;
5346     }
5347     else if (anArg == "l"
5348           || anArg == "line"
5349           || anArg == "lines")
5350     {
5351       aMode = Aspect_GDM_Lines;
5352     }
5353     else if (anArg == "p"
5354           || anArg == "point"
5355           || anArg == "points")
5356     {
5357       aMode = Aspect_GDM_Points;
5358     }
5359     else if (anArgIter + 1 >= theArgNb
5360           && anArg == "off")
5361     {
5362       aViewer->DeactivateGrid();
5363       return 0;
5364     }
5365     else
5366     {
5367       std::cout << "Syntax error at '" << anArg << "'\n";
5368       return 1;
5369     }
5370   }
5371
5372   if (aType == Aspect_GT_Rectangular)
5373   {
5374     Graphic3d_Vec2d anOrigXY, aStepXY;
5375     Standard_Real aRotAngle = 0.0;
5376     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5377     if (hasOrigin)
5378     {
5379       anOrigXY = aNewOriginXY;
5380     }
5381     if (hasStep)
5382     {
5383       aStepXY = aNewStepXY;
5384     }
5385     if (hasRotAngle)
5386     {
5387       aRotAngle = aNewRotAngle;
5388     }
5389     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5390     if (hasSize || hasZOffset)
5391     {
5392       Graphic3d_Vec3d aSize;
5393       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5394       if (hasSize)
5395       {
5396         aSize.x() = aNewSizeXY.x();
5397         aSize.y() = aNewSizeXY.y();
5398       }
5399       if (hasZOffset)
5400       {
5401         aSize.z() = aNewZOffset;
5402       }
5403       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5404     }
5405   }
5406   else if (aType == Aspect_GT_Circular)
5407   {
5408     Graphic3d_Vec2d anOrigXY;
5409     Standard_Real aRadiusStep;
5410     Standard_Integer aDivisionNumber;
5411     Standard_Real aRotAngle = 0.0;
5412     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5413     if (hasOrigin)
5414     {
5415       anOrigXY = aNewOriginXY;
5416     }
5417     if (hasStep)
5418     {
5419       aRadiusStep     = aNewStepXY[0];
5420       aDivisionNumber = (int )aNewStepXY[1];
5421       if (aDivisionNumber < 1)
5422       {
5423         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
5424         return 1;
5425       }
5426     }
5427     if (hasRotAngle)
5428     {
5429       aRotAngle = aNewRotAngle;
5430     }
5431
5432     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5433     if (hasSize || hasZOffset)
5434     {
5435       Standard_Real aRadius = 0.0, aZOffset = 0.0;
5436       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
5437       if (hasSize)
5438       {
5439         aRadius = aNewSizeXY.x();
5440         if (aNewSizeXY.y() != 0.0)
5441         {
5442           std::cout << "Syntax error: circular size should be specified as radius\n";
5443           return 1;
5444         }
5445       }
5446       if (hasZOffset)
5447       {
5448         aZOffset = aNewZOffset;
5449       }
5450       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
5451     }
5452   }
5453   aViewer->ActivateGrid (aType, aMode);
5454   return 0;
5455 }
5456
5457 //==============================================================================
5458 //function : VPriviledgedPlane
5459 //purpose  :
5460 //==============================================================================
5461
5462 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5463                               Standard_Integer  theArgNb,
5464                               const char**      theArgVec)
5465 {
5466   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5467   {
5468     std::cerr << "Error: wrong number of arguments! See usage:\n";
5469     theDI.PrintHelp (theArgVec[0]);
5470     return 1;
5471   }
5472
5473   // get the active viewer
5474   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5475   if (aViewer.IsNull())
5476   {
5477     std::cerr << "Error: no active viewer. Please call vinit.\n";
5478     return 1;
5479   }
5480
5481   if (theArgNb == 1)
5482   {
5483     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5484     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5485     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5486     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5487     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5488           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5489           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5490     return 0;
5491   }
5492
5493   Standard_Integer anArgIdx = 1;
5494   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5495   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5496   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5497   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5498   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5499   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5500
5501   gp_Ax3 aPriviledgedPlane;
5502   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5503   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5504   if (theArgNb > 7)
5505   {
5506     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5507     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5508     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5509     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5510     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5511   }
5512   else
5513   {
5514     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5515   }
5516
5517   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5518
5519   return 0;
5520 }
5521
5522 //==============================================================================
5523 //function : VConvert
5524 //purpose  :
5525 //==============================================================================
5526
5527 static int VConvert (Draw_Interpretor& theDI,
5528                      Standard_Integer  theArgNb,
5529                      const char**      theArgVec)
5530 {
5531   // get the active view
5532   Handle(V3d_View) aView = ViewerTest::CurrentView();
5533   if (aView.IsNull())
5534   {
5535     std::cerr << "Error: no active view. Please call vinit.\n";
5536     return 1;
5537   }
5538
5539   enum { Model, Ray, View, Window, Grid } aMode = Model;
5540
5541   // access coordinate arguments
5542   TColStd_SequenceOfReal aCoord;
5543   Standard_Integer anArgIdx = 1;
5544   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5545   {
5546     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5547     if (!anArg.IsRealValue())
5548     {
5549       break;
5550     }
5551     aCoord.Append (anArg.RealValue());
5552   }
5553
5554   // non-numeric argument too early
5555   if (aCoord.IsEmpty())
5556   {
5557     std::cerr << "Error: wrong number of arguments! See usage:\n";
5558     theDI.PrintHelp (theArgVec[0]);
5559     return 1;
5560   }
5561
5562   // collect all other arguments and options
5563   for (; anArgIdx < theArgNb; ++anArgIdx)
5564   {
5565     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5566     anArg.LowerCase();
5567     if      (anArg == "window") aMode = Window;
5568     else if (anArg == "view")   aMode = View;
5569     else if (anArg == "grid")   aMode = Grid;
5570     else if (anArg == "ray")    aMode = Ray;
5571     else
5572     {
5573       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5574       theDI.PrintHelp (theArgVec[0]);
5575       return 1;
5576     }
5577   }
5578
5579   // complete input checks
5580   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5581       (aCoord.Length() == 2 && theArgNb > 4) ||
5582       (aCoord.Length() == 3 && theArgNb > 5))
5583   {
5584     std::cerr << "Error: wrong number of arguments! See usage:\n";
5585     theDI.PrintHelp (theArgVec[0]);
5586     return 1;
5587   }
5588
5589   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5590   Standard_Integer aXYp[2] = {0, 0};
5591
5592   // convert one-dimensional coordinate
5593   if (aCoord.Length() == 1)
5594   {
5595     switch (aMode)
5596     {
5597       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5598       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5599       default:
5600         std::cerr << "Error: wrong arguments! See usage:\n";
5601         theDI.PrintHelp (theArgVec[0]);
5602         return 1;
5603     }
5604   }
5605
5606   // convert 2D coordinates from projection or view reference space
5607   if (aCoord.Length() == 2)
5608   {
5609     switch (aMode)
5610     {
5611       case Model :
5612         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5613         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5614         return 0;
5615
5616       case View :
5617         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5618         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5619         return 0;
5620
5621       case Window :
5622         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5623         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5624         return 0;
5625
5626       case Grid :
5627         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5628         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5629         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5630         return 0;
5631
5632       case Ray :
5633         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5634                                 (Standard_Integer) aCoord (2),
5635                                 aXYZ[0], aXYZ[1], aXYZ[2],
5636                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5637         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5638         return 0;
5639
5640       default:
5641         std::cerr << "Error: wrong arguments! See usage:\n";
5642         theDI.PrintHelp (theArgVec[0]);
5643         return 1;
5644     }
5645   }
5646
5647   // convert 3D coordinates from view reference space
5648   else if (aCoord.Length() == 3)
5649   {
5650     switch (aMode)
5651     {
5652       case Window :
5653         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5654         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5655         return 0;
5656
5657       case Grid :
5658         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5659         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5660         return 0;
5661
5662       default:
5663         std::cerr << "Error: wrong arguments! See usage:\n";
5664         theDI.PrintHelp (theArgVec[0]);
5665         return 1;
5666     }
5667   }
5668
5669   return 0;
5670 }
5671
5672 //==============================================================================
5673 //function : VFps
5674 //purpose  :
5675 //==============================================================================
5676
5677 static int VFps (Draw_Interpretor& theDI,
5678                  Standard_Integer  theArgNb,
5679                  const char**      theArgVec)
5680 {
5681   // get the active view
5682   Handle(V3d_View) aView = ViewerTest::CurrentView();
5683   if (aView.IsNull())
5684   {
5685     std::cerr << "No active view. Please call vinit.\n";
5686     return 1;
5687   }
5688
5689   Standard_Integer aFramesNb = -1;
5690   Standard_Real aDuration = -1.0;
5691   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5692   {
5693     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5694     anArg.LowerCase();
5695     if (aDuration < 0.0
5696      && anArgIter + 1 < theArgNb
5697      && (anArg == "-duration"
5698       || anArg == "-dur"
5699       || anArg == "-time"))
5700     {
5701       aDuration = Draw::Atof (theArgVec[++anArgIter]);
5702     }
5703     else if (aFramesNb < 0
5704           && anArg.IsIntegerValue())
5705     {
5706       aFramesNb = anArg.IntegerValue();
5707       if (aFramesNb <= 0)
5708       {
5709         std::cerr << "Syntax error at '" << anArg << "'\n";
5710         return 1;
5711       }
5712     }
5713     else
5714     {
5715       std::cerr << "Syntax error at '" << anArg << "'\n";
5716       return 1;
5717     }
5718   }
5719   if (aFramesNb < 0 && aDuration < 0.0)
5720   {
5721     aFramesNb = 100;
5722   }
5723
5724   // the time is meaningless for first call
5725   // due to async OpenGl rendering
5726   aView->Redraw();
5727
5728   // redraw view in loop to estimate average values
5729   OSD_Timer aTimer;
5730   aTimer.Start();
5731   Standard_Integer aFrameIter = 1;
5732   for (;; ++aFrameIter)
5733   {
5734     aView->Redraw();
5735     if ((aFramesNb > 0
5736       && aFrameIter >= aFramesNb)
5737      || (aDuration > 0.0
5738       && aTimer.ElapsedTime() >= aDuration))
5739     {
5740       break;
5741     }
5742   }
5743   aTimer.Stop();
5744   Standard_Real aCpu;
5745   const Standard_Real aTime = aTimer.ElapsedTime();
5746   aTimer.OSD_Chronometer::Show (aCpu);
5747
5748   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
5749   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
5750
5751   // return statistics
5752   theDI << "FPS: " << aFpsAver << "\n"
5753         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5754
5755   // compute additional statistics in ray-tracing mode
5756   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
5757   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5758   {
5759     Graphic3d_Vec2i aWinSize (0, 0);
5760     aView->Window()->Size (aWinSize.x(), aWinSize.y());
5761
5762     // 1 shadow ray and 1 secondary ray pew each bounce
5763     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5764     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5765   }
5766
5767   return 0;
5768 }
5769
5770 //! Auxiliary function for parsing glsl dump level argument.
5771 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
5772                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
5773 {
5774   TCollection_AsciiString aTypeStr (theArg);
5775   aTypeStr.LowerCase();
5776   if (aTypeStr == "off"
5777    || aTypeStr == "0")
5778   {
5779     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
5780   }
5781   else if (aTypeStr == "short")
5782   {
5783     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
5784   }
5785   else if (aTypeStr == "full"
5786         || aTypeStr == "1")
5787   {
5788     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
5789   }
5790   else
5791   {
5792     return Standard_False;
5793   }
5794   return Standard_True;
5795 }
5796
5797 //==============================================================================
5798 //function : VGlDebug
5799 //purpose  :
5800 //==============================================================================
5801
5802 static int VGlDebug (Draw_Interpretor& theDI,
5803                      Standard_Integer  theArgNb,
5804                      const char**      theArgVec)
5805 {
5806   Handle(OpenGl_GraphicDriver) aDriver;
5807   Handle(V3d_View) aView = ViewerTest::CurrentView();
5808   if (!aView.IsNull())
5809   {
5810     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5811   }
5812   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5813   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5814
5815   if (theArgNb < 2)
5816   {
5817     TCollection_AsciiString aDebActive, aSyncActive;
5818     if (aCaps == NULL)
5819     {
5820       aCaps = aDefCaps;
5821     }
5822     else
5823     {
5824       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5825                                                                   "GL_ARB_debug_output");
5826       aDebActive = isActive ? " (active)" : " (inactive)";
5827       if (isActive)
5828       {
5829         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5830         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5831       }
5832     }
5833
5834     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
5835       + "glslSourceCode: "
5836       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
5837          ? "Off"
5838          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
5839           ? "Short"
5840           : "Full")
5841       + "\n";
5842     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5843           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5844           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5845           << aGlslCodeDebugStatus
5846           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5847     return 0;
5848   }
5849
5850   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5851   {
5852     Standard_CString        anArg     = theArgVec[anArgIter];
5853     TCollection_AsciiString anArgCase (anArg);
5854     anArgCase.LowerCase();
5855     Standard_Boolean toEnableDebug = Standard_True;
5856     if (anArgCase == "-glsl"
5857      || anArgCase == "-glslwarn"
5858      || anArgCase == "-glslwarns"
5859      || anArgCase == "-glslwarnings")
5860     {
5861       Standard_Boolean toShowWarns = Standard_True;
5862       if (++anArgIter < theArgNb
5863       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5864       {
5865         --anArgIter;
5866       }
5867       aDefCaps->glslWarnings = toShowWarns;
5868       if (aCaps != NULL)
5869       {
5870         aCaps->glslWarnings = toShowWarns;
5871       }
5872     }
5873     else if (anArgCase == "-extra"
5874           || anArgCase == "-extramsg"
5875           || anArgCase == "-extramessages")
5876     {
5877       Standard_Boolean toShow = Standard_True;
5878       if (++anArgIter < theArgNb
5879       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5880       {
5881         --anArgIter;
5882       }
5883       aDefCaps->suppressExtraMsg = !toShow;
5884       if (aCaps != NULL)
5885       {
5886         aCaps->suppressExtraMsg = !toShow;
5887       }
5888     }
5889     else if (anArgCase == "-noextra"
5890           || anArgCase == "-noextramsg"
5891           || anArgCase == "-noextramessages")
5892     {
5893       Standard_Boolean toSuppress = Standard_True;
5894       if (++anArgIter < theArgNb
5895       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5896       {
5897         --anArgIter;
5898       }
5899       aDefCaps->suppressExtraMsg = toSuppress;
5900       if (aCaps != NULL)
5901       {
5902         aCaps->suppressExtraMsg = toSuppress;
5903       }
5904     }
5905     else if (anArgCase == "-sync")
5906     {
5907       Standard_Boolean toSync = Standard_True;
5908       if (++anArgIter < theArgNb
5909       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5910       {
5911         --anArgIter;
5912       }
5913       aDefCaps->contextSyncDebug = toSync;
5914       if (toSync)
5915       {
5916         aDefCaps->contextDebug = Standard_True;
5917       }
5918     }
5919     else if (anArgCase == "-glslsourcecode"
5920           || anArgCase == "-glslcode")
5921     {
5922       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
5923       if (++anArgIter < theArgNb
5924       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
5925       {
5926         --anArgIter;
5927       }
5928       aDefCaps->glslDumpLevel = aGslsDumpLevel;
5929       if (aCaps != NULL)
5930       {
5931         aCaps->glslDumpLevel = aGslsDumpLevel;
5932       }
5933     }
5934     else if (anArgCase == "-debug")
5935     {
5936       if (++anArgIter < theArgNb
5937       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5938       {
5939         --anArgIter;
5940       }
5941       aDefCaps->contextDebug = toEnableDebug;
5942     }
5943     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5944           && (anArgIter + 1 == theArgNb))
5945     {
5946       // simple alias to turn on almost everything
5947       aDefCaps->contextDebug     = toEnableDebug;
5948       aDefCaps->contextSyncDebug = toEnableDebug;
5949       aDefCaps->glslWarnings     = toEnableDebug;
5950       if (!toEnableDebug)
5951       {
5952         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
5953       }
5954       aDefCaps->suppressExtraMsg = !toEnableDebug;
5955       if (aCaps != NULL)
5956       {
5957         aCaps->contextDebug     = toEnableDebug;
5958         aCaps->contextSyncDebug = toEnableDebug;
5959         aCaps->glslWarnings     = toEnableDebug;
5960         if (!toEnableDebug)
5961         {
5962           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
5963         }
5964         aCaps->suppressExtraMsg = !toEnableDebug;
5965       }
5966     }
5967     else
5968     {
5969       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5970       return 1;
5971     }
5972   }
5973
5974   return 0;
5975 }
5976
5977 //==============================================================================
5978 //function : VVbo
5979 //purpose  :
5980 //==============================================================================
5981
5982 static int VVbo (Draw_Interpretor& theDI,
5983                  Standard_Integer  theArgNb,
5984                  const char**      theArgVec)
5985 {
5986   const Standard_Boolean toSet    = (theArgNb > 1);
5987   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5988   if (toSet)
5989   {
5990     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5991   }
5992
5993   // get the context
5994   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5995   if (aContextAIS.IsNull())
5996   {
5997     if (!toSet)
5998     {
5999       std::cerr << "No active view!\n";
6000     }
6001     return 1;
6002   }
6003   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
6004   if (!aDriver.IsNull())
6005   {
6006     if (!toSet)
6007     {
6008       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
6009     }
6010     else
6011     {
6012       aDriver->ChangeOptions().vboDisable = toUseVbo;
6013     }
6014   }
6015
6016   return 0;
6017 }
6018
6019 //==============================================================================
6020 //function : VCaps
6021 //purpose  :
6022 //==============================================================================
6023
6024 static int VCaps (Draw_Interpretor& theDI,
6025                   Standard_Integer  theArgNb,
6026                   const char**      theArgVec)
6027 {
6028   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
6029   Handle(OpenGl_GraphicDriver)   aDriver;
6030   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6031   if (!aContext.IsNull())
6032   {
6033     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
6034     aCaps   = &aDriver->ChangeOptions();
6035   }
6036
6037   if (theArgNb < 2)
6038   {
6039     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
6040     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
6041     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
6042     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
6043     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
6044     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
6045     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
6046     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
6047     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
6048     return 0;
6049   }
6050
6051   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6052   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6053   {
6054     Standard_CString        anArg     = theArgVec[anArgIter];
6055     TCollection_AsciiString anArgCase (anArg);
6056     anArgCase.LowerCase();
6057     if (anUpdateTool.parseRedrawMode (anArg))
6058     {
6059       continue;
6060     }
6061     else if (anArgCase == "-vsync"
6062           || anArgCase == "-swapinterval")
6063     {
6064       Standard_Boolean toEnable = Standard_True;
6065       if (++anArgIter < theArgNb
6066       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6067       {
6068         --anArgIter;
6069       }
6070       aCaps->swapInterval = toEnable;
6071     }
6072     else if (anArgCase == "-ffp")
6073     {
6074       Standard_Boolean toEnable = Standard_True;
6075       if (++anArgIter < theArgNb
6076       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6077       {
6078         --anArgIter;
6079       }
6080       aCaps->ffpEnable = toEnable;
6081     }
6082     else if (anArgCase == "-polygonmode")
6083     {
6084       Standard_Boolean toEnable = Standard_True;
6085       if (++anArgIter < theArgNb
6086       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6087       {
6088         --anArgIter;
6089       }
6090       aCaps->usePolygonMode = toEnable;
6091     }
6092     else if (anArgCase == "-vbo")
6093     {
6094       Standard_Boolean toEnable = Standard_True;
6095       if (++anArgIter < theArgNb
6096       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6097       {
6098         --anArgIter;
6099       }
6100       aCaps->vboDisable = !toEnable;
6101     }
6102     else if (anArgCase == "-sprite"
6103           || anArgCase == "-sprites")
6104     {
6105       Standard_Boolean toEnable = Standard_True;
6106       if (++anArgIter < theArgNb
6107       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6108       {
6109         --anArgIter;
6110       }
6111       aCaps->pntSpritesDisable = !toEnable;
6112     }
6113     else if (anArgCase == "-softmode")
6114     {
6115       Standard_Boolean toEnable = Standard_True;
6116       if (++anArgIter < theArgNb
6117       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6118       {
6119         --anArgIter;
6120       }
6121       aCaps->contextNoAccel = toEnable;
6122     }
6123     else if (anArgCase == "-winbuffer"
6124           || anArgCase == "-windowbuffer"
6125           || anArgCase == "-usewinbuffer"
6126           || anArgCase == "-usewindowbuffer"
6127           || anArgCase == "-usesystembuffer")
6128     {
6129       Standard_Boolean toEnable = Standard_True;
6130       if (++anArgIter < theArgNb
6131       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6132       {
6133         --anArgIter;
6134       }
6135       aCaps->useSystemBuffer = toEnable;
6136     }
6137     else if (anArgCase == "-accel"
6138           || anArgCase == "-acceleration")
6139     {
6140       Standard_Boolean toEnable = Standard_True;
6141       if (++anArgIter < theArgNb
6142       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6143       {
6144         --anArgIter;
6145       }
6146       aCaps->contextNoAccel = !toEnable;
6147     }
6148     else if (anArgCase == "-compat"
6149           || anArgCase == "-compatprofile"
6150           || anArgCase == "-compatible"
6151           || anArgCase == "-compatibleprofile")
6152     {
6153       Standard_Boolean toEnable = Standard_True;
6154       if (++anArgIter < theArgNb
6155       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6156       {
6157         --anArgIter;
6158       }
6159       aCaps->contextCompatible = toEnable;
6160       if (!aCaps->contextCompatible)
6161       {
6162         aCaps->ffpEnable = Standard_False;
6163       }
6164     }
6165     else if (anArgCase == "-core"
6166           || anArgCase == "-coreprofile")
6167     {
6168       Standard_Boolean toEnable = Standard_True;
6169       if (++anArgIter < theArgNb
6170       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6171       {
6172         --anArgIter;
6173       }
6174       aCaps->contextCompatible = !toEnable;
6175       if (!aCaps->contextCompatible)
6176       {
6177         aCaps->ffpEnable = Standard_False;
6178       }
6179     }
6180     else if (anArgCase == "-stereo"
6181           || anArgCase == "-quadbuffer")
6182     {
6183       Standard_Boolean toEnable = Standard_True;
6184       if (++anArgIter < theArgNb
6185       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6186       {
6187         --anArgIter;
6188       }
6189       aCaps->contextStereo = toEnable;
6190     }
6191     else
6192     {
6193       std::cout << "Error: unknown argument '" << anArg << "'\n";
6194       return 1;
6195     }
6196   }
6197   if (aCaps != &ViewerTest_myDefaultCaps)
6198   {
6199     ViewerTest_myDefaultCaps = *aCaps;
6200   }
6201   return 0;
6202 }
6203
6204 //==============================================================================
6205 //function : VMemGpu
6206 //purpose  :
6207 //==============================================================================
6208
6209 static int VMemGpu (Draw_Interpretor& theDI,
6210                     Standard_Integer  theArgNb,
6211                     const char**      theArgVec)
6212 {
6213   // get the context
6214   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6215   if (aContextAIS.IsNull())
6216   {
6217     std::cerr << "No active view. Please call vinit.\n";
6218     return 1;
6219   }
6220
6221   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
6222   if (aDriver.IsNull())
6223   {
6224     std::cerr << "Graphic driver not available.\n";
6225     return 1;
6226   }
6227
6228   Standard_Size aFreeBytes = 0;
6229   TCollection_AsciiString anInfo;
6230   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
6231   {
6232     std::cerr << "Information not available.\n";
6233     return 1;
6234   }
6235
6236   if (theArgNb > 1 && *theArgVec[1] == 'f')
6237   {
6238     theDI << Standard_Real (aFreeBytes);
6239   }
6240   else
6241   {
6242     theDI << anInfo;
6243   }
6244
6245   return 0;
6246 }
6247
6248 // ==============================================================================
6249 // function : VReadPixel
6250 // purpose  :
6251 // ==============================================================================
6252 static int VReadPixel (Draw_Interpretor& theDI,
6253                        Standard_Integer  theArgNb,
6254                        const char**      theArgVec)
6255 {
6256   // get the active view
6257   Handle(V3d_View) aView = ViewerTest::CurrentView();
6258   if (aView.IsNull())
6259   {
6260     std::cerr << "No active view. Please call vinit.\n";
6261     return 1;
6262   }
6263   else if (theArgNb < 3)
6264   {
6265     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
6266     return 1;
6267   }
6268
6269   Image_Format         aFormat     = Image_Format_RGBA;
6270   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
6271
6272   Standard_Integer aWidth, aHeight;
6273   aView->Window()->Size (aWidth, aHeight);
6274   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
6275   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
6276   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
6277   {
6278     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
6279     return 1;
6280   }
6281
6282   Standard_Boolean toShowName = Standard_False;
6283   Standard_Boolean toShowHls  = Standard_False;
6284   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6285   {
6286     TCollection_AsciiString aParam (theArgVec[anIter]);
6287     aParam.LowerCase();
6288     if (aParam == "-rgb"
6289      || aParam == "rgb")
6290     {
6291       aFormat     = Image_Format_RGB;
6292       aBufferType = Graphic3d_BT_RGB;
6293     }
6294     else if (aParam == "-hls"
6295           || aParam == "hls")
6296     {
6297       aFormat     = Image_Format_RGB;
6298       aBufferType = Graphic3d_BT_RGB;
6299       toShowHls   = Standard_True;
6300     }
6301     else if (aParam == "-rgbf"
6302           || aParam == "rgbf")
6303     {
6304       aFormat     = Image_Format_RGBF;
6305       aBufferType = Graphic3d_BT_RGB;
6306     }
6307     else if (aParam == "-rgba"
6308           || aParam == "rgba")
6309     {
6310       aFormat     = Image_Format_RGBA;
6311       aBufferType = Graphic3d_BT_RGBA;
6312     }
6313     else if (aParam == "-rgbaf"
6314           || aParam == "rgbaf")
6315     {
6316       aFormat     = Image_Format_RGBAF;
6317       aBufferType = Graphic3d_BT_RGBA;
6318     }
6319     else if (aParam == "-depth"
6320           || aParam == "depth")
6321     {
6322       aFormat     = Image_Format_GrayF;
6323       aBufferType = Graphic3d_BT_Depth;
6324     }
6325     else if (aParam == "-name"
6326           || aParam == "name")
6327     {
6328       toShowName = Standard_True;
6329     }
6330     else
6331     {
6332       std::cout << "Syntax error at '" << aParam << "'\n";
6333     }
6334   }
6335
6336   Image_PixMap anImage;
6337   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6338   {
6339     std::cerr << "Image allocation failed\n";
6340     return 1;
6341   }
6342   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6343   {
6344     std::cerr << "Image dump failed\n";
6345     return 1;
6346   }
6347
6348   // redirect possible warning messages that could have been added by ToPixMap
6349   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6350   // contaminate result of the command
6351   Standard_CString aWarnLog = theDI.Result();
6352   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6353   {
6354     std::cout << aWarnLog << std::endl;
6355   }
6356   theDI.Reset();
6357
6358   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6359   if (toShowName)
6360   {
6361     if (aBufferType == Graphic3d_BT_RGBA)
6362     {
6363       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6364     }
6365     else
6366     {
6367       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6368     }
6369   }
6370   else
6371   {
6372     switch (aBufferType)
6373     {
6374       default:
6375       case Graphic3d_BT_RGB:
6376       {
6377         if (toShowHls)
6378         {
6379           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6380         }
6381         else
6382         {
6383           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6384         }
6385         break;
6386       }
6387       case Graphic3d_BT_RGBA:
6388       {
6389         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6390         break;
6391       }
6392       case Graphic3d_BT_Depth:
6393       {
6394         theDI << aColor.GetRGB().Red();
6395         break;
6396       }
6397     }
6398   }
6399
6400   return 0;
6401 }
6402
6403 //! Auxiliary presentation for an image plane.
6404 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6405 {
6406 public:
6407   //! Main constructor.
6408   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6409                        const Standard_Real theWidth,
6410                        const Standard_Real theHeight,
6411                        const TCollection_AsciiString& theLabel)
6412   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6413   {
6414     SetDisplayMode (0);
6415     SetHilightMode (1);
6416     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6417     {
6418       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6419       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6420       Graphic3d_MaterialAspect aMat;
6421       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6422       aMat.SetAmbient  (1.0);
6423       aMat.SetDiffuse  (1.0);
6424       aMat.SetSpecular (1.0);
6425       aMat.SetEmissive (1.0);
6426       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6427       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6428       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6429       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6430       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6431       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6432       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6433       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6434       aFillAspect->SetFrontMaterial (aMat);
6435       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6436       aFillAspect->SetTextureMapOn();
6437     }
6438     {
6439       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6440       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6441       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6442       myDrawer->SetTextAspect (aTextAspect);
6443     }
6444     {
6445       const gp_Dir aNorm (0.0, 0.0, 1.0);
6446       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6447       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6448       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6449       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6450       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6451       myTris->AddEdge (1);
6452       myTris->AddEdge (2);
6453       myTris->AddEdge (3);
6454       myTris->AddEdge (3);
6455       myTris->AddEdge (2);
6456       myTris->AddEdge (4);
6457
6458       myRect = new Graphic3d_ArrayOfPolylines (4);
6459       myRect->AddVertex (myTris->Vertice (1));
6460       myRect->AddVertex (myTris->Vertice (3));
6461       myRect->AddVertex (myTris->Vertice (4));
6462       myRect->AddVertex (myTris->Vertice (2));
6463     }
6464   }
6465
6466   //! Returns TRUE for accepted display modes.
6467   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6468
6469   //! Compute presentation.
6470   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6471   {
6472     switch (theMode)
6473     {
6474       case 0:
6475       {
6476         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6477         aGroup->AddPrimitiveArray (myTris);
6478         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6479         aGroup->AddPrimitiveArray (myRect);
6480         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6481         return;
6482       }
6483       case 1:
6484       {
6485         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6486         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6487         aGroup->AddPrimitiveArray (myRect);
6488         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6489         return;
6490       }
6491     }
6492   }
6493
6494   //! Compute selection.
6495   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6496   {
6497     if (theMode == 0)
6498     {
6499       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6500       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6501       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6502       theSel->Add (aSensitive);
6503     }
6504   }
6505
6506 private:
6507   Handle(Graphic3d_ArrayOfTriangles) myTris;
6508   Handle(Graphic3d_ArrayOfPolylines) myRect;
6509   TCollection_AsciiString myLabel;
6510   Standard_Real myWidth;
6511   Standard_Real myHeight;
6512 };
6513
6514 //==============================================================================
6515 //function : VDiffImage
6516 //purpose  : The draw-command compares two images.
6517 //==============================================================================
6518
6519 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6520 {
6521   if (theArgNb < 3)
6522   {
6523     std::cout << "Syntax error: not enough arguments.\n";
6524     return 1;
6525   }
6526
6527   Standard_Integer anArgIter = 1;
6528   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6529   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6530   TCollection_AsciiString aDiffImagePath;
6531   Standard_Real    aTolColor        = -1.0;
6532   Standard_Integer toBlackWhite     = -1;
6533   Standard_Integer isBorderFilterOn = -1;
6534   Standard_Boolean isOldSyntax = Standard_False;
6535   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6536   for (; anArgIter < theArgNb; ++anArgIter)
6537   {
6538     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6539     anArg.LowerCase();
6540     if (anArgIter + 1 < theArgNb
6541      && (anArg == "-toleranceofcolor"
6542       || anArg == "-tolerancecolor"
6543       || anArg == "-tolerance"
6544       || anArg == "-toler"))
6545     {
6546       aTolColor = Atof (theArgVec[++anArgIter]);
6547       if (aTolColor < 0.0 || aTolColor > 1.0)
6548       {
6549         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6550         return 1;
6551       }
6552     }
6553     else if (anArg == "-blackwhite")
6554     {
6555       Standard_Boolean toEnable = Standard_True;
6556       if (anArgIter + 1 < theArgNb
6557        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6558       {
6559         ++anArgIter;
6560       }
6561       toBlackWhite = toEnable ? 1 : 0;
6562     }
6563     else if (anArg == "-borderfilter")
6564     {
6565       Standard_Boolean toEnable = Standard_True;
6566       if (anArgIter + 1 < theArgNb
6567        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6568       {
6569         ++anArgIter;
6570       }
6571       isBorderFilterOn = toEnable ? 1 : 0;
6572     }
6573     else if (anArg == "-exitonclose")
6574     {
6575       Draw_ToExitOnCloseView = true;
6576       if (anArgIter + 1 < theArgNb
6577        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6578       {
6579         ++anArgIter;
6580       }
6581     }
6582     else if (anArg == "-closeonescape"
6583           || anArg == "-closeonesc")
6584     {
6585       Draw_ToCloseViewOnEsc = true;
6586       if (anArgIter + 1 < theArgNb
6587        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6588       {
6589         ++anArgIter;
6590       }
6591     }
6592     else if (anArgIter + 3 < theArgNb
6593           && anArg == "-display")
6594     {
6595       aViewName   = theArgVec[++anArgIter];
6596       aPrsNameRef = theArgVec[++anArgIter];
6597       aPrsNameNew = theArgVec[++anArgIter];
6598       if (anArgIter + 1 < theArgNb
6599       && *theArgVec[anArgIter + 1] != '-')
6600       {
6601         aPrsNameDiff = theArgVec[++anArgIter];
6602       }
6603     }
6604     else if (aTolColor < 0.0
6605           && anArg.IsRealValue())
6606     {
6607       isOldSyntax = Standard_True;
6608       aTolColor = anArg.RealValue();
6609       if (aTolColor < 0.0 || aTolColor > 1.0)
6610       {
6611         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6612         return 1;
6613       }
6614     }
6615     else if (isOldSyntax
6616           && toBlackWhite == -1
6617           && (anArg == "0" || anArg == "1"))
6618     {
6619       toBlackWhite = anArg == "1" ? 1 : 0;
6620     }
6621     else if (isOldSyntax
6622           && isBorderFilterOn == -1
6623           && (anArg == "0" || anArg == "1"))
6624     {
6625       isBorderFilterOn = anArg == "1" ? 1 : 0;
6626     }
6627     else if (aDiffImagePath.IsEmpty())
6628     {
6629       aDiffImagePath = theArgVec[anArgIter];
6630     }
6631     else
6632     {
6633       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6634       return 1;
6635     }
6636   }
6637
6638   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6639   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6640   if (!anImgRef->Load (anImgPathRef))
6641   {
6642     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6643     return 1;
6644   }
6645   if (!anImgNew->Load (anImgPathNew))
6646   {
6647     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6648     return 1;
6649   }
6650
6651   // compare the images
6652   Image_Diff aComparer;
6653   Standard_Integer aDiffColorsNb = -1;
6654   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6655   {
6656     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6657     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6658     aDiffColorsNb = aComparer.Compare();
6659     theDI << aDiffColorsNb << "\n";
6660   }
6661
6662   // save image of difference
6663   Handle(Image_AlienPixMap) aDiff;
6664   if (aDiffColorsNb > 0
6665   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6666   {
6667     aDiff = new Image_AlienPixMap();
6668     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6669     {
6670       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6671       return 1;
6672     }
6673     aComparer.SaveDiffImage (*aDiff);
6674     if (!aDiffImagePath.IsEmpty()
6675      && !aDiff->Save (aDiffImagePath))
6676     {
6677       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6678       return 1;
6679     }
6680   }
6681
6682   if (aViewName.IsEmpty())
6683   {
6684     return 0;
6685   }
6686
6687   ViewerTest_Names aViewNames (aViewName);
6688   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6689   {
6690     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6691     theDI.Eval (aCommand.ToCString());
6692   }
6693
6694   Standard_Integer aPxLeft = 0;
6695   Standard_Integer aPxTop  = 0;
6696   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6697   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6698                               ? int(anImgRef->SizeY() * 2)
6699                               : int(anImgRef->SizeY());
6700   TCollection_AsciiString aDisplayName;
6701   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
6702                                                             aViewName, aDisplayName);
6703
6704   Standard_Real aRatio = anImgRef->Ratio();
6705   Standard_Real aSizeX = 1.0;
6706   Standard_Real aSizeY = aSizeX / aRatio;
6707   {
6708     OSD_Path aPath (anImgPathRef);
6709     TCollection_AsciiString aLabelRef;
6710     if (!aPath.Name().IsEmpty())
6711     {
6712       aLabelRef = aPath.Name() + aPath.Extension();
6713     }
6714     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6715
6716     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6717     gp_Trsf aTrsfRef;
6718     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6719     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6720     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6721   }
6722   {
6723     OSD_Path aPath (anImgPathNew);
6724     TCollection_AsciiString aLabelNew;
6725     if (!aPath.Name().IsEmpty())
6726     {
6727       aLabelNew = aPath.Name() + aPath.Extension();
6728     }
6729     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6730
6731     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6732     gp_Trsf aTrsfRef;
6733     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6734     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6735     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6736   }
6737   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6738   if (!aDiff.IsNull())
6739   {
6740     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6741     gp_Trsf aTrsfDiff;
6742     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6743     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6744   }
6745   if (!aPrsNameDiff.IsEmpty())
6746   {
6747     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6748   }
6749   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6750   ViewerTest::CurrentView()->FitAll();
6751   return 0;
6752 }
6753
6754 //=======================================================================
6755 //function : VSelect
6756 //purpose  : Emulates different types of selection by mouse:
6757 //           1) single click selection
6758 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6759 //           3) selection with polygon having corners at
6760 //           pixel positions (x1,y1),...,(xn,yn)
6761 //           4) any of these selections with shift button pressed
6762 //=======================================================================
6763 static Standard_Integer VSelect (Draw_Interpretor& di,
6764                                  Standard_Integer argc,
6765                                  const char ** argv)
6766 {
6767   if(argc < 3)
6768   {
6769     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6770     return 1;
6771   }
6772
6773   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6774   if(myAIScontext.IsNull())
6775   {
6776     di << "use 'vinit' command before " << argv[0] << "\n";
6777     return 1;
6778   }
6779
6780   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6781   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6782   TCollection_AsciiString anArg;
6783   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6784   anArg.LowerCase();
6785   if (anArg == "-allowoverlap")
6786   {
6787     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6788       : argc == 7;
6789     if (!isValidated)
6790     {
6791       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6792       return 1;
6793     }
6794
6795     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6796     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6797     aCoordsNb -= 2;
6798   }
6799
6800   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6801   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6802   if(aCoordsNb == 2)
6803   {
6804     if(isShiftSelection)
6805       aCurrentEventManager->ShiftSelect();
6806     else
6807       aCurrentEventManager->Select();
6808   }
6809   else if(aCoordsNb == 4)
6810   {
6811     if(isShiftSelection)
6812       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6813     else
6814       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6815   }
6816   else
6817   {
6818     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6819
6820     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6821       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6822
6823     if(isShiftSelection)
6824       aCurrentEventManager->ShiftSelect(aPolyline);
6825     else
6826       aCurrentEventManager->Select(aPolyline);
6827   }
6828   return 0;
6829 }
6830
6831 //=======================================================================
6832 //function : VMoveTo
6833 //purpose  : Emulates cursor movement to defined pixel position
6834 //=======================================================================
6835 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
6836                                 Standard_Integer theNbArgs,
6837                                 const char**     theArgVec)
6838 {
6839   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
6840   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
6841   if (aContext.IsNull())
6842   {
6843     std::cout << "Error: no active View\n";
6844     return 1;
6845   }
6846
6847   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
6848   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
6849   {
6850     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
6851     anArgStr.LowerCase();
6852     if (anArgStr == "-reset"
6853      || anArgStr == "-clear")
6854     {
6855       if (anArgIter + 1 < theNbArgs)
6856       {
6857         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
6858         return 1;
6859       }
6860
6861       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
6862                                        && aContext->CurrentViewer()->GridEcho();
6863       if (toEchoGrid)
6864       {
6865         aContext->CurrentViewer()->HideGridEcho (aView);
6866       }
6867       if (aContext->ClearDetected() || toEchoGrid)
6868       {
6869         aContext->CurrentViewer()->RedrawImmediate();
6870       }
6871       return 0;
6872     }
6873     else if (aMousePos.x() == IntegerLast()
6874           && anArgStr.IsIntegerValue())
6875     {
6876       aMousePos.x() = anArgStr.IntegerValue();
6877     }
6878     else if (aMousePos.y() == IntegerLast()
6879           && anArgStr.IsIntegerValue())
6880     {
6881       aMousePos.y() = anArgStr.IntegerValue();
6882     }
6883     else
6884     {
6885       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6886       return 1;
6887     }
6888   }
6889
6890   if (aMousePos.x() == IntegerLast()
6891    || aMousePos.y() == IntegerLast())
6892   {
6893     std::cout << "Syntax error: wrong number of arguments\n";
6894     return 1;
6895   }
6896
6897   ViewerTest::CurrentEventManager()->MoveTo (aMousePos.x(), aMousePos.y());
6898   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
6899   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
6900   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
6901   {
6902     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
6903     {
6904       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
6905       break;
6906     }
6907   }
6908   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
6909   return 0;
6910 }
6911
6912 namespace
6913 {
6914   //! Global map storing all animations registered in ViewerTest.
6915   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6916
6917   //! The animation calling the Draw Harness command.
6918   class ViewerTest_AnimationProc : public AIS_Animation
6919   {
6920   public:
6921
6922     //! Main constructor.
6923     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6924                               Draw_Interpretor* theDI,
6925                               const TCollection_AsciiString& theCommand)
6926     : AIS_Animation (theAnimationName),
6927       myDrawInter(theDI),
6928       myCommand  (theCommand)
6929     {
6930       //
6931     }
6932
6933   protected:
6934
6935     //! Evaluate the command.
6936     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6937     {
6938       TCollection_AsciiString aCmd = myCommand;
6939       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6940       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6941       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6942       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6943       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6944       myDrawInter->Eval (aCmd.ToCString());
6945     }
6946
6947     //! Find the keyword in the command and replace it with value.
6948     //! @return the position of the keyword to pass value
6949     void replace (TCollection_AsciiString&       theCmd,
6950                   const TCollection_AsciiString& theKey,
6951                   const TCollection_AsciiString& theVal)
6952     {
6953       TCollection_AsciiString aCmd (theCmd);
6954       aCmd.LowerCase();
6955       const Standard_Integer aPos = aCmd.Search (theKey);
6956       if (aPos == -1)
6957       {
6958         return;
6959       }
6960
6961       TCollection_AsciiString aPart1, aPart2;
6962       Standard_Integer aPart1To = aPos - 1;
6963       if (aPart1To >= 1
6964        && aPart1To <= theCmd.Length())
6965       {
6966         aPart1 = theCmd.SubString (1, aPart1To);
6967       }
6968
6969       Standard_Integer aPart2From = aPos + theKey.Length();
6970       if (aPart2From >= 1
6971        && aPart2From <= theCmd.Length())
6972       {
6973         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6974       }
6975
6976       theCmd = aPart1 + theVal + aPart2;
6977     }
6978
6979   protected:
6980
6981     Draw_Interpretor*       myDrawInter;
6982     TCollection_AsciiString myCommand;
6983
6984   };
6985
6986   //! Replace the animation with the new one.
6987   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6988                                 Handle(AIS_Animation)&       theAnimation,
6989                                 const Handle(AIS_Animation)& theAnimationNew)
6990   {
6991     theAnimationNew->CopyFrom (theAnimation);
6992     if (!theParentAnimation.IsNull())
6993     {
6994       theParentAnimation->Replace (theAnimation, theAnimationNew);
6995     }
6996     else
6997     {
6998       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6999       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7000     }
7001     theAnimation = theAnimationNew;
7002   }
7003
7004   //! Parse the point.
7005   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7006   {
7007     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7008     if (!anXYZ[0].IsRealValue()
7009      || !anXYZ[1].IsRealValue()
7010      || !anXYZ[2].IsRealValue())
7011     {
7012       return Standard_False;
7013     }
7014
7015     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7016     return Standard_True;
7017   }
7018
7019   //! Parse the quaternion.
7020   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7021   {
7022     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7023     if (!anXYZW[0].IsRealValue()
7024      || !anXYZW[1].IsRealValue()
7025      || !anXYZW[2].IsRealValue()
7026      || !anXYZW[3].IsRealValue())
7027     {
7028       return Standard_False;
7029     }
7030
7031     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7032     return Standard_True;
7033   }
7034
7035   //! Auxiliary class for flipping image upside-down.
7036   class ImageFlipper
7037   {
7038   public:
7039
7040     //! Empty constructor.
7041     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7042
7043     //! Perform flipping.
7044     Standard_Boolean FlipY (Image_PixMap& theImage)
7045     {
7046       if (theImage.IsEmpty()
7047        || theImage.SizeX() == 0
7048        || theImage.SizeY() == 0)
7049       {
7050         return Standard_False;
7051       }
7052
7053       const Standard_Size aRowSize = theImage.SizeRowBytes();
7054       if (myTmp.Size() < aRowSize
7055       && !myTmp.Allocate (aRowSize))
7056       {
7057         return Standard_False;
7058       }
7059
7060       // for odd height middle row should be left as is
7061       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7062       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7063       {
7064         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7065         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7066         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7067         memcpy (aTop,               aBot,         aRowSize);
7068         memcpy (aBot,               myTmp.Data(), aRowSize);
7069       }
7070       return Standard_True;
7071     }
7072
7073   private:
7074     NCollection_Buffer myTmp;
7075   };
7076
7077 }
7078
7079 //=================================================================================================
7080 //function : VViewParams
7081 //purpose  : Gets or sets AIS View characteristics
7082 //=================================================================================================
7083 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7084 {
7085   Handle(V3d_View) aView = ViewerTest::CurrentView();
7086   if (aView.IsNull())
7087   {
7088     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7089     return 1;
7090   }
7091
7092   Standard_Boolean toSetProj     = Standard_False;
7093   Standard_Boolean toSetUp       = Standard_False;
7094   Standard_Boolean toSetAt       = Standard_False;
7095   Standard_Boolean toSetEye      = Standard_False;
7096   Standard_Boolean toSetScale    = Standard_False;
7097   Standard_Boolean toSetSize     = Standard_False;
7098   Standard_Boolean toSetCenter2d = Standard_False;
7099   Standard_Real    aViewScale = aView->Scale();
7100   Standard_Real    aViewSize  = 1.0;
7101   Graphic3d_Vec2i  aCenter2d;
7102   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7103   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7104   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7105   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7106   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7107   if (theArgsNb == 1)
7108   {
7109     // print all of the available view parameters
7110     char aText[4096];
7111     Sprintf (aText,
7112              "Scale: %g\n"
7113              "Proj:  %12g %12g %12g\n"
7114              "Up:    %12g %12g %12g\n"
7115              "At:    %12g %12g %12g\n"
7116              "Eye:   %12g %12g %12g\n",
7117               aViewScale,
7118               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7119               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7120               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7121               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7122     theDi << aText;
7123     return 0;
7124   }
7125
7126   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7127   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7128   {
7129     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7130     anArg.LowerCase();
7131     if (anUpdateTool.parseRedrawMode (anArg))
7132     {
7133       continue;
7134     }
7135     else if (anArg == "-cmd"
7136           || anArg == "-command"
7137           || anArg == "-args")
7138     {
7139       char aText[4096];
7140       Sprintf (aText,
7141                "-scale %g "
7142                "-proj %g %g %g "
7143                "-up %g %g %g "
7144                "-at %g %g %g\n",
7145                 aViewScale,
7146                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7147                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7148                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7149       theDi << aText;
7150     }
7151     else if (anArg == "-scale"
7152           || anArg == "-size")
7153     {
7154       if (anArgIter + 1 < theArgsNb
7155        && *theArgVec[anArgIter + 1] != '-')
7156       {
7157         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
7158         if (aValueArg.IsRealValue())
7159         {
7160           ++anArgIter;
7161           if (anArg == "-scale")
7162           {
7163             toSetScale = Standard_True;
7164             aViewScale = aValueArg.RealValue();
7165           }
7166           else if (anArg == "-size")
7167           {
7168             toSetSize = Standard_True;
7169             aViewSize = aValueArg.RealValue();
7170           }
7171           continue;
7172         }
7173       }
7174       if (anArg == "-scale")
7175       {
7176         theDi << "Scale: " << aView->Scale() << "\n";
7177       }
7178       else if (anArg == "-size")
7179       {
7180         Graphic3d_Vec2d aSizeXY;
7181         aView->Size (aSizeXY.x(), aSizeXY.y());
7182         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
7183       }
7184     }
7185     else if (anArg == "-eye"
7186           || anArg == "-at"
7187           || anArg == "-up"
7188           || anArg == "-proj")
7189     {
7190       if (anArgIter + 3 < theArgsNb)
7191       {
7192         gp_XYZ anXYZ;
7193         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
7194         {
7195           anArgIter += 3;
7196           if (anArg == "-eye")
7197           {
7198             toSetEye = Standard_True;
7199             aViewEye = anXYZ;
7200           }
7201           else if (anArg == "-at")
7202           {
7203             toSetAt = Standard_True;
7204             aViewAt = anXYZ;
7205           }
7206           else if (anArg == "-up")
7207           {
7208             toSetUp = Standard_True;
7209             aViewUp = anXYZ;
7210           }
7211           else if (anArg == "-proj")
7212           {
7213             toSetProj = Standard_True;
7214             aViewProj = anXYZ;
7215           }
7216           continue;
7217         }
7218       }
7219
7220       if (anArg == "-eye")
7221       {
7222         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
7223       }
7224       else if (anArg == "-at")
7225       {
7226         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
7227       }
7228       else if (anArg == "-up")
7229       {
7230         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
7231       }
7232       else if (anArg == "-proj")
7233       {
7234         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
7235       }
7236     }
7237     else if (anArg == "-center")
7238     {
7239       if (anArgIter + 2 < theArgsNb)
7240       {
7241         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
7242         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
7243         if (anX.IsIntegerValue()
7244          && anY.IsIntegerValue())
7245         {
7246           toSetCenter2d = Standard_True;
7247           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
7248         }
7249       }
7250     }
7251     else
7252     {
7253       std::cout << "Syntax error at '" << anArg << "'\n";
7254       return 1;
7255     }
7256   }
7257
7258   // change view parameters in proper order
7259   if (toSetScale)
7260   {
7261     aView->SetScale (aViewScale);
7262   }
7263   if (toSetSize)
7264   {
7265     aView->SetSize (aViewSize);
7266   }
7267   if (toSetEye)
7268   {
7269     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7270   }
7271   if (toSetAt)
7272   {
7273     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7274   }
7275   if (toSetProj)
7276   {
7277     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7278   }
7279   if (toSetUp)
7280   {
7281     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7282   }
7283   if (toSetCenter2d)
7284   {
7285     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
7286   }
7287
7288   return 0;
7289 }
7290
7291 //==============================================================================
7292 //function : V2DMode
7293 //purpose  :
7294 //==============================================================================
7295 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7296 {
7297   bool is2dMode = true;
7298   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7299   if (aV3dView.IsNull())
7300   {
7301     std::cout << "Error: no active view.\n";
7302     return 1;
7303   }
7304   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7305   {
7306     const TCollection_AsciiString anArg = theArgVec[anArgIt];
7307     TCollection_AsciiString anArgCase = anArg;
7308     anArgCase.LowerCase();
7309     if (anArgIt + 1 < theArgsNb
7310      && anArgCase == "-name")
7311     {
7312       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
7313       TCollection_AsciiString aViewName = aViewNames.GetViewName();
7314       if (!ViewerTest_myViews.IsBound1 (aViewName))
7315       {
7316         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
7317         return 1;
7318       }
7319       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7320     }
7321     else if (anArgCase == "-mode")
7322     {
7323       if (anArgIt + 1 < theArgsNb
7324        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
7325       {
7326         ++anArgIt;
7327       }
7328     }
7329     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
7330     {
7331       //
7332     }
7333     else
7334     {
7335       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
7336       return 1;
7337     }
7338   }
7339
7340   aV3dView->SetView2DMode (is2dMode);
7341   return 0;
7342 }
7343
7344 //==============================================================================
7345 //function : VAnimation
7346 //purpose  :
7347 //==============================================================================
7348 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7349                                     Standard_Integer  theArgNb,
7350                                     const char**      theArgVec)
7351 {
7352   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7353   if (theArgNb < 2)
7354   {
7355     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7356          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7357     {
7358       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
7359     }
7360     return 0;
7361   }
7362   if (aCtx.IsNull())
7363   {
7364     std::cout << "Error: no active view\n";
7365     return 1;
7366   }
7367
7368   Standard_Integer anArgIter = 1;
7369   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7370   if (aNameArg.IsEmpty())
7371   {
7372     std::cout << "Syntax error: animation name is not defined.\n";
7373     return 1;
7374   }
7375
7376   TCollection_AsciiString aNameArgLower = aNameArg;
7377   aNameArgLower.LowerCase();
7378   if (aNameArgLower == "-reset"
7379    || aNameArgLower == "-clear")
7380   {
7381     ViewerTest_AnimationTimelineMap.Clear();
7382     return 0;
7383   }
7384   else if (aNameArg.Value (1) == '-')
7385   {
7386     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
7387     return 1;
7388   }
7389
7390   const char* aNameSplitter = "/";
7391   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7392   if (aSplitPos == -1)
7393   {
7394     aNameSplitter = ".";
7395     aSplitPos = aNameArg.Search (aNameSplitter);
7396   }
7397
7398   // find existing or create a new animation by specified name within syntax "parent.child".
7399   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
7400   for (; !aNameArg.IsEmpty();)
7401   {
7402     TCollection_AsciiString aNameParent;
7403     if (aSplitPos != -1)
7404     {
7405       if (aSplitPos == aNameArg.Length())
7406       {
7407         std::cout << "Syntax error: animation name is not defined.\n";
7408         return 1;
7409       }
7410
7411       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7412       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7413
7414       aSplitPos = aNameArg.Search (aNameSplitter);
7415     }
7416     else
7417     {
7418       aNameParent = aNameArg;
7419       aNameArg.Clear();
7420     }
7421
7422     if (anAnimation.IsNull())
7423     {
7424       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7425       {
7426         anAnimation = new AIS_Animation (aNameParent);
7427         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7428       }
7429       aRootAnimation = anAnimation;
7430     }
7431     else
7432     {
7433       aParentAnimation = anAnimation;
7434       anAnimation = aParentAnimation->Find (aNameParent);
7435       if (anAnimation.IsNull())
7436       {
7437         anAnimation = new AIS_Animation (aNameParent);
7438         aParentAnimation->Add (anAnimation);
7439       }
7440     }
7441   }
7442
7443   if (anArgIter >= theArgNb)
7444   {
7445     // just print the list of children
7446     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7447     {
7448       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7449     }
7450     return 0;
7451   }
7452
7453   // animation parameters
7454   Standard_Boolean toPlay = Standard_False;
7455   Standard_Real aPlaySpeed     = 1.0;
7456   Standard_Real aPlayStartTime = anAnimation->StartPts();
7457   Standard_Real aPlayDuration  = anAnimation->Duration();
7458   Standard_Boolean isFreeCamera = Standard_False;
7459   Standard_Boolean isLockLoop   = Standard_False;
7460
7461   // video recording parameters
7462   TCollection_AsciiString aRecFile;
7463   Image_VideoParams aRecParams;
7464
7465   Handle(V3d_View) aView = ViewerTest::CurrentView();
7466   for (; anArgIter < theArgNb; ++anArgIter)
7467   {
7468     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7469     anArg.LowerCase();
7470     // general options
7471     if (anArg == "-reset"
7472      || anArg == "-clear")
7473     {
7474       anAnimation->Clear();
7475     }
7476     else if (anArg == "-remove"
7477           || anArg == "-del"
7478           || anArg == "-delete")
7479     {
7480       if (!aParentAnimation.IsNull())
7481       {
7482         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7483       }
7484       else
7485       {
7486         aParentAnimation->Remove (anAnimation);
7487       }
7488     }
7489     // playback options
7490     else if (anArg == "-play")
7491     {
7492       toPlay = Standard_True;
7493       if (++anArgIter < theArgNb)
7494       {
7495         if (*theArgVec[anArgIter] == '-')
7496         {
7497           --anArgIter;
7498           continue;
7499         }
7500         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7501
7502         if (++anArgIter < theArgNb)
7503         {
7504           if (*theArgVec[anArgIter] == '-')
7505           {
7506             --anArgIter;
7507             continue;
7508           }
7509           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7510         }
7511       }
7512     }
7513     else if (anArg == "-resume")
7514     {
7515       toPlay = Standard_True;
7516       aPlayStartTime = anAnimation->ElapsedTime();
7517       if (++anArgIter < theArgNb)
7518       {
7519         if (*theArgVec[anArgIter] == '-')
7520         {
7521           --anArgIter;
7522           continue;
7523         }
7524
7525         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7526       }
7527     }
7528     else if (anArg == "-playspeed"
7529           || anArg == "-speed")
7530     {
7531       if (++anArgIter >= theArgNb)
7532       {
7533         std::cout << "Syntax error at " << anArg << ".\n";
7534         return 1;
7535       }
7536       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7537     }
7538     else if (anArg == "-lock"
7539           || anArg == "-lockloop"
7540           || anArg == "-playlockloop")
7541     {
7542       isLockLoop = Standard_True;
7543     }
7544     else if (anArg == "-freecamera"
7545           || anArg == "-playfreecamera"
7546           || anArg == "-freelook")
7547     {
7548       isFreeCamera = Standard_True;
7549     }
7550     // video recodring options
7551     else if (anArg == "-rec"
7552           || anArg == "-record")
7553     {
7554       if (++anArgIter >= theArgNb)
7555       {
7556         std::cout << "Syntax error at " << anArg << ".\n";
7557         return 1;
7558       }
7559
7560       aRecFile = theArgVec[anArgIter];
7561       if (aRecParams.FpsNum <= 0)
7562       {
7563         aRecParams.FpsNum = 24;
7564       }
7565
7566       if (anArgIter + 2 < theArgNb
7567       && *theArgVec[anArgIter + 1] != '-'
7568       && *theArgVec[anArgIter + 2] != '-')
7569       {
7570         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7571         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7572         if (aWidthArg .IsIntegerValue()
7573          && aHeightArg.IsIntegerValue())
7574         {
7575           aRecParams.Width  = aWidthArg .IntegerValue();
7576           aRecParams.Height = aHeightArg.IntegerValue();
7577           anArgIter += 2;
7578         }
7579       }
7580     }
7581     else if (anArg == "-fps")
7582     {
7583       if (++anArgIter >= theArgNb)
7584       {
7585         std::cout << "Syntax error at " << anArg << ".\n";
7586         return 1;
7587       }
7588
7589       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7590       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7591       if (aSplitIndex == 0)
7592       {
7593         aRecParams.FpsNum = aFpsArg.IntegerValue();
7594       }
7595       else
7596       {
7597         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7598         aFpsArg.Split (aFpsArg.Length() - 1);
7599         const TCollection_AsciiString aNumStr = aFpsArg;
7600         aRecParams.FpsNum = aNumStr.IntegerValue();
7601         aRecParams.FpsDen = aDenStr.IntegerValue();
7602         if (aRecParams.FpsDen < 1)
7603         {
7604           std::cout << "Syntax error at " << anArg << ".\n";
7605           return 1;
7606         }
7607       }
7608     }
7609     else if (anArg == "-format")
7610     {
7611       if (++anArgIter >= theArgNb)
7612       {
7613         std::cout << "Syntax error at " << anArg << ".\n";
7614         return 1;
7615       }
7616       aRecParams.Format = theArgVec[anArgIter];
7617     }
7618     else if (anArg == "-pix_fmt"
7619           || anArg == "-pixfmt"
7620           || anArg == "-pixelformat")
7621     {
7622       if (++anArgIter >= theArgNb)
7623       {
7624         std::cout << "Syntax error at " << anArg << ".\n";
7625         return 1;
7626       }
7627       aRecParams.PixelFormat = theArgVec[anArgIter];
7628     }
7629     else if (anArg == "-codec"
7630           || anArg == "-vcodec"
7631           || anArg == "-videocodec")
7632     {
7633       if (++anArgIter >= theArgNb)
7634       {
7635         std::cout << "Syntax error at " << anArg << ".\n";
7636         return 1;
7637       }
7638       aRecParams.VideoCodec = theArgVec[anArgIter];
7639     }
7640     else if (anArg == "-crf"
7641           || anArg == "-preset"
7642           || anArg == "-qp")
7643     {
7644       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7645       if (++anArgIter >= theArgNb)
7646       {
7647         std::cout << "Syntax error at " << anArg << ".\n";
7648         return 1;
7649       }
7650
7651       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7652     }
7653     // animation definition options
7654     else if (anArg == "-start"
7655           || anArg == "-starttime"
7656           || anArg == "-startpts")
7657     {
7658       if (++anArgIter >= theArgNb)
7659       {
7660         std::cout << "Syntax error at " << anArg << ".\n";
7661         return 1;
7662       }
7663
7664       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7665       aRootAnimation->UpdateTotalDuration();
7666     }
7667     else if (anArg == "-end"
7668           || anArg == "-endtime"
7669           || anArg == "-endpts")
7670     {
7671       if (++anArgIter >= theArgNb)
7672       {
7673         std::cout << "Syntax error at " << anArg << ".\n";
7674         return 1;
7675       }
7676
7677       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7678       aRootAnimation->UpdateTotalDuration();
7679     }
7680     else if (anArg == "-dur"
7681           || anArg == "-duration")
7682     {
7683       if (++anArgIter >= theArgNb)
7684       {
7685         std::cout << "Syntax error at " << anArg << ".\n";
7686         return 1;
7687       }
7688
7689       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7690       aRootAnimation->UpdateTotalDuration();
7691     }
7692     else if (anArg == "-command"
7693           || anArg == "-cmd"
7694           || anArg == "-invoke"
7695           || anArg == "-eval"
7696           || anArg == "-proc")
7697     {
7698       if (++anArgIter >= theArgNb)
7699       {
7700         std::cout << "Syntax error at " << anArg << ".\n";
7701         return 1;
7702       }
7703
7704       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7705       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7706     }
7707     else if (anArg == "-objecttrsf"
7708           || anArg == "-objectransformation"
7709           || anArg == "-objtransformation"
7710           || anArg == "-objtrsf"
7711           || anArg == "-object"
7712           || anArg == "-obj")
7713     {
7714       if (++anArgIter >= theArgNb)
7715       {
7716         std::cout << "Syntax error at " << anArg << ".\n";
7717         return 1;
7718       }
7719
7720       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7721       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7722       Handle(AIS_InteractiveObject) anObject;
7723       if (!aMapOfAIS.Find2 (anObjName, anObject))
7724       {
7725         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7726         return 1;
7727       }
7728
7729       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7730       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7731       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7732       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7733       Standard_Boolean isTrsfSet = Standard_False;
7734       Standard_Integer aTrsfArgIter = anArgIter + 1;
7735       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7736       {
7737         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7738         aTrsfArg.LowerCase();
7739         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7740         if (aTrsfArg.StartsWith ("-rotation")
7741          || aTrsfArg.StartsWith ("-rot"))
7742         {
7743           isTrsfSet = Standard_True;
7744           if (aTrsfArgIter + 4 >= theArgNb
7745           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7746           {
7747             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7748             return 1;
7749           }
7750           aTrsfArgIter += 4;
7751         }
7752         else if (aTrsfArg.StartsWith ("-location")
7753               || aTrsfArg.StartsWith ("-loc"))
7754         {
7755           isTrsfSet = Standard_True;
7756           if (aTrsfArgIter + 3 >= theArgNb
7757           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7758           {
7759             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7760             return 1;
7761           }
7762           aTrsfArgIter += 3;
7763         }
7764         else if (aTrsfArg.StartsWith ("-scale"))
7765         {
7766           isTrsfSet = Standard_True;
7767           if (++aTrsfArgIter >= theArgNb)
7768           {
7769             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7770             return 1;
7771           }
7772
7773           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7774           if (!aScaleStr.IsRealValue())
7775           {
7776             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7777             return 1;
7778           }
7779           aScales[anIndex] = aScaleStr.RealValue();
7780         }
7781         else
7782         {
7783           anArgIter = aTrsfArgIter - 1;
7784           break;
7785         }
7786       }
7787       if (!isTrsfSet)
7788       {
7789         std::cout << "Syntax error at " << anArg << ".\n";
7790         return 1;
7791       }
7792       else if (aTrsfArgIter >= theArgNb)
7793       {
7794         anArgIter = theArgNb;
7795       }
7796
7797       aTrsfs[0].SetRotation        (aRotQuats[0]);
7798       aTrsfs[1].SetRotation        (aRotQuats[1]);
7799       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7800       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7801       aTrsfs[0].SetScaleFactor     (aScales[0]);
7802       aTrsfs[1].SetScaleFactor     (aScales[1]);
7803
7804       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7805       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7806     }
7807     else if (anArg == "-viewtrsf"
7808           || anArg == "-view")
7809     {
7810       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7811       if (aCamAnimation.IsNull())
7812       {
7813         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7814         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7815       }
7816
7817       Handle(Graphic3d_Camera) aCams[2] =
7818       {
7819         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7820         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7821       };
7822
7823       Standard_Boolean isTrsfSet = Standard_False;
7824       Standard_Integer aViewArgIter = anArgIter + 1;
7825       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7826       {
7827         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7828         aViewArg.LowerCase();
7829         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7830         if (aViewArg.StartsWith ("-scale"))
7831         {
7832           isTrsfSet = Standard_True;
7833           if (++aViewArgIter >= theArgNb)
7834           {
7835             std::cout << "Syntax error at " << anArg << ".\n";
7836             return 1;
7837           }
7838
7839           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7840           if (!aScaleStr.IsRealValue())
7841           {
7842             std::cout << "Syntax error at " << aViewArg << ".\n";
7843             return 1;
7844           }
7845           Standard_Real aScale = aScaleStr.RealValue();
7846           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7847           aCams[anIndex]->SetScale (aScale);
7848         }
7849         else if (aViewArg.StartsWith ("-eye")
7850               || aViewArg.StartsWith ("-center")
7851               || aViewArg.StartsWith ("-at")
7852               || aViewArg.StartsWith ("-up"))
7853         {
7854           isTrsfSet = Standard_True;
7855           gp_XYZ anXYZ;
7856           if (aViewArgIter + 3 >= theArgNb
7857           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7858           {
7859             std::cout << "Syntax error at " << aViewArg << ".\n";
7860             return 1;
7861           }
7862           aViewArgIter += 3;
7863
7864           if (aViewArg.StartsWith ("-eye"))
7865           {
7866             aCams[anIndex]->SetEye (anXYZ);
7867           }
7868           else if (aViewArg.StartsWith ("-center")
7869                 || aViewArg.StartsWith ("-at"))
7870           {
7871             aCams[anIndex]->SetCenter (anXYZ);
7872           }
7873           else if (aViewArg.StartsWith ("-up"))
7874           {
7875             aCams[anIndex]->SetUp (anXYZ);
7876           }
7877         }
7878         else
7879         {
7880           anArgIter = aViewArgIter - 1;
7881           break;
7882         }
7883       }
7884       if (!isTrsfSet)
7885       {
7886         std::cout << "Syntax error at " << anArg << ".\n";
7887         return 1;
7888       }
7889       else if (aViewArgIter >= theArgNb)
7890       {
7891         anArgIter = theArgNb;
7892       }
7893
7894       aCamAnimation->SetCameraStart(aCams[0]);
7895       aCamAnimation->SetCameraEnd  (aCams[1]);
7896     }
7897     else
7898     {
7899       std::cout << "Syntax error at " << anArg << ".\n";
7900       return 1;
7901     }
7902   }
7903
7904   if (!toPlay && aRecFile.IsEmpty())
7905   {
7906     return 0;
7907   }
7908
7909   // Start animation timeline and process frame updating.
7910   TheIsAnimating = Standard_True;
7911   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7912   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7913   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7914   if (isFreeCamera)
7915   {
7916     aView->Camera()->Copy (aCameraBack);
7917   }
7918
7919   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7920   if (aRecParams.FpsNum <= 0)
7921   {
7922     while (!anAnimation->IsStopped())
7923     {
7924       aCameraBack->Copy (aView->Camera());
7925       const Standard_Real aPts = anAnimation->UpdateTimer();
7926       if (isFreeCamera)
7927       {
7928         aView->Camera()->Copy (aCameraBack);
7929       }
7930
7931       if (aPts >= anUpperPts)
7932       {
7933         anAnimation->Pause();
7934         break;
7935       }
7936
7937       if (aView->IsInvalidated())
7938       {
7939         aView->Redraw();
7940       }
7941       else
7942       {
7943         aView->RedrawImmediate();
7944       }
7945
7946       if (!isLockLoop)
7947       {
7948         // handle user events
7949         theDI.Eval ("after 1 set waiter 1");
7950         theDI.Eval ("vwait waiter");
7951       }
7952       if (!TheIsAnimating)
7953       {
7954         anAnimation->Pause();
7955         theDI << aPts;
7956         break;
7957       }
7958     }
7959
7960     if (aView->IsInvalidated())
7961     {
7962       aView->Redraw();
7963     }
7964     else
7965     {
7966       aView->RedrawImmediate();
7967     }
7968   }
7969   else
7970   {
7971     OSD_Timer aPerfTimer;
7972     aPerfTimer.Start();
7973
7974     Handle(Image_VideoRecorder) aRecorder;
7975     ImageFlipper aFlipper;
7976     Handle(Draw_ProgressIndicator) aProgress;
7977     if (!aRecFile.IsEmpty())
7978     {
7979       if (aRecParams.Width  <= 0
7980        || aRecParams.Height <= 0)
7981       {
7982         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7983       }
7984
7985       aRecorder = new Image_VideoRecorder();
7986       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7987       {
7988         std::cout << "Error: failed to open video file for recording\n";
7989         return 0;
7990       }
7991
7992       aProgress = new Draw_ProgressIndicator (theDI, 1);
7993     }
7994
7995     // Manage frame-rated animation here
7996     Standard_Real aPts = aPlayStartTime;
7997     int64_t aNbFrames = 0;
7998     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7999     Standard_Integer aSecondsProgress = 0;
8000     for (; aPts <= anUpperPts && aPSentry.More();)
8001     {
8002       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8003       aPts = aPlayStartTime + aRecPts;
8004       ++aNbFrames;
8005       if (!anAnimation->Update (aPts))
8006       {
8007         break;
8008       }
8009
8010       if (!aRecorder.IsNull())
8011       {
8012         V3d_ImageDumpOptions aDumpParams;
8013         aDumpParams.Width          = aRecParams.Width;
8014         aDumpParams.Height         = aRecParams.Height;
8015         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8016         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8017         aDumpParams.ToAdjustAspect = Standard_True;
8018         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8019         {
8020           std::cout << "Error: view dump is failed!\n";
8021           return 0;
8022         }
8023         aFlipper.FlipY (aRecorder->ChangeFrame());
8024         if (!aRecorder->PushFrame())
8025         {
8026           return 0;
8027         }
8028       }
8029       else
8030       {
8031         aView->Redraw();
8032       }
8033
8034       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8035       {
8036         aPSentry.Next();
8037         ++aSecondsProgress;
8038       }
8039     }
8040
8041     aPerfTimer.Stop();
8042     anAnimation->Stop();
8043     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8044     theDI << "Average FPS: " << aRecFps << "\n"
8045           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8046
8047     aView->Redraw();
8048   }
8049
8050   aView->SetImmediateUpdate (wasImmediateUpdate);
8051   TheIsAnimating = Standard_False;
8052   return 0;
8053 }
8054
8055
8056 //=======================================================================
8057 //function : VChangeSelected
8058 //purpose  : Adds the shape to selection or remove one from it
8059 //=======================================================================
8060 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8061                                 Standard_Integer argc,
8062                                 const char ** argv)
8063 {
8064   if(argc != 2)
8065   {
8066     di<<"Usage : " << argv[0] << " shape \n";
8067     return 1;
8068   }
8069   //get AIS_Shape:
8070   TCollection_AsciiString aName(argv[1]);
8071   Handle(AIS_InteractiveObject) anAISObject;
8072   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8073     || anAISObject.IsNull())
8074   {
8075     di<<"Use 'vdisplay' before";
8076     return 1;
8077   }
8078
8079   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8080   return 0;
8081 }
8082
8083 //=======================================================================
8084 //function : VNbSelected
8085 //purpose  : Returns number of selected objects
8086 //=======================================================================
8087 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8088                                 Standard_Integer argc,
8089                                 const char ** argv)
8090 {
8091   if(argc != 1)
8092   {
8093     di << "Usage : " << argv[0] << "\n";
8094     return 1;
8095   }
8096   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8097   if(aContext.IsNull())
8098   {
8099     di << "use 'vinit' command before " << argv[0] << "\n";
8100     return 1;
8101   }
8102   di << aContext->NbSelected() << "\n";
8103   return 0;
8104 }
8105
8106 //=======================================================================
8107 //function : VPurgeDisplay
8108 //purpose  : Switches altialiasing on or off
8109 //=======================================================================
8110 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8111                                 Standard_Integer argc,
8112                                 const char ** argv)
8113 {
8114   if (argc > 1)
8115   {
8116     di << "Usage : " << argv[0] << "\n";
8117     return 1;
8118   }
8119   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8120   if (aContext.IsNull())
8121   {
8122     di << "use 'vinit' command before " << argv[0] << "\n";
8123     return 1;
8124   }
8125
8126   di << aContext->PurgeDisplay() << "\n";
8127   return 0;
8128 }
8129
8130 //=======================================================================
8131 //function : VSetViewSize
8132 //purpose  :
8133 //=======================================================================
8134 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8135                                 Standard_Integer argc,
8136                                 const char ** argv)
8137 {
8138   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8139   if(aContext.IsNull())
8140   {
8141     di << "use 'vinit' command before " << argv[0] << "\n";
8142     return 1;
8143   }
8144   if(argc != 2)
8145   {
8146     di<<"Usage : " << argv[0] << " Size\n";
8147     return 1;
8148   }
8149   Standard_Real aSize = Draw::Atof (argv[1]);
8150   if (aSize <= 0.)
8151   {
8152     di<<"Bad Size value  : " << aSize << "\n";
8153     return 1;
8154   }
8155
8156   Handle(V3d_View) aView = ViewerTest::CurrentView();
8157   aView->SetSize(aSize);
8158   return 0;
8159 }
8160
8161 //=======================================================================
8162 //function : VMoveView
8163 //purpose  :
8164 //=======================================================================
8165 static Standard_Integer VMoveView (Draw_Interpretor& di,
8166                                 Standard_Integer argc,
8167                                 const char ** argv)
8168 {
8169   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8170   if(aContext.IsNull())
8171   {
8172     di << "use 'vinit' command before " << argv[0] << "\n";
8173     return 1;
8174   }
8175   if(argc < 4 || argc > 5)
8176   {
8177     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8178     return 1;
8179   }
8180   Standard_Real Dx = Draw::Atof (argv[1]);
8181   Standard_Real Dy = Draw::Atof (argv[2]);
8182   Standard_Real Dz = Draw::Atof (argv[3]);
8183   Standard_Boolean aStart = Standard_True;
8184   if (argc == 5)
8185   {
8186       aStart = (Draw::Atoi (argv[4]) > 0);
8187   }
8188
8189   Handle(V3d_View) aView = ViewerTest::CurrentView();
8190   aView->Move(Dx,Dy,Dz,aStart);
8191   return 0;
8192 }
8193
8194 //=======================================================================
8195 //function : VTranslateView
8196 //purpose  :
8197 //=======================================================================
8198 static Standard_Integer VTranslateView (Draw_Interpretor& di,
8199                                 Standard_Integer argc,
8200                                 const char ** argv)
8201 {
8202   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8203   if(aContext.IsNull())
8204   {
8205     di << "use 'vinit' command before " << argv[0] << "\n";
8206     return 1;
8207   }
8208   if(argc < 4 || argc > 5)
8209   {
8210     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8211     return 1;
8212   }
8213   Standard_Real Dx = Draw::Atof (argv[1]);
8214   Standard_Real Dy = Draw::Atof (argv[2]);
8215   Standard_Real Dz = Draw::Atof (argv[3]);
8216   Standard_Boolean aStart = Standard_True;
8217   if (argc == 5)
8218   {
8219       aStart = (Draw::Atoi (argv[4]) > 0);
8220   }
8221
8222   Handle(V3d_View) aView = ViewerTest::CurrentView();
8223   aView->Translate(Dx,Dy,Dz,aStart);
8224   return 0;
8225 }
8226
8227 //=======================================================================
8228 //function : VTurnView
8229 //purpose  :
8230 //=======================================================================
8231 static Standard_Integer VTurnView (Draw_Interpretor& di,
8232                                 Standard_Integer argc,
8233                                 const char ** argv)
8234 {
8235   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8236   if(aContext.IsNull()) {
8237     di << "use 'vinit' command before " << argv[0] << "\n";
8238     return 1;
8239   }
8240   if(argc < 4 || argc > 5){
8241     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
8242     return 1;
8243   }
8244   Standard_Real Ax = Draw::Atof (argv[1]);
8245   Standard_Real Ay = Draw::Atof (argv[2]);
8246   Standard_Real Az = Draw::Atof (argv[3]);
8247   Standard_Boolean aStart = Standard_True;
8248   if (argc == 5)
8249   {
8250       aStart = (Draw::Atoi (argv[4]) > 0);
8251   }
8252
8253   Handle(V3d_View) aView = ViewerTest::CurrentView();
8254   aView->Turn(Ax,Ay,Az,aStart);
8255   return 0;
8256 }
8257
8258 //==============================================================================
8259 //function : VTextureEnv
8260 //purpose  : ENables or disables environment mapping
8261 //==============================================================================
8262 class OCC_TextureEnv : public Graphic3d_TextureEnv
8263 {
8264 public:
8265   OCC_TextureEnv(const Standard_CString FileName);
8266   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8267   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8268                             const Standard_Boolean theModulateFlag,
8269                             const Graphic3d_TypeOfTextureFilter theFilter,
8270                             const Standard_ShortReal theXScale,
8271                             const Standard_ShortReal theYScale,
8272                             const Standard_ShortReal theXShift,
8273                             const Standard_ShortReal theYShift,
8274                             const Standard_ShortReal theAngle);
8275   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
8276 };
8277 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
8278
8279 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8280   : Graphic3d_TextureEnv(theFileName)
8281 {
8282 }
8283
8284 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8285   : Graphic3d_TextureEnv(theTexId)
8286 {
8287 }
8288
8289 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8290                                           const Standard_Boolean theModulateFlag,
8291                                           const Graphic3d_TypeOfTextureFilter theFilter,
8292                                           const Standard_ShortReal theXScale,
8293                                           const Standard_ShortReal theYScale,
8294                                           const Standard_ShortReal theXShift,
8295                                           const Standard_ShortReal theYShift,
8296                                           const Standard_ShortReal theAngle)
8297 {
8298   myParams->SetRepeat     (theRepeatFlag);
8299   myParams->SetModulate   (theModulateFlag);
8300   myParams->SetFilter     (theFilter);
8301   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
8302   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8303   myParams->SetRotation   (theAngle);
8304 }
8305
8306 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
8307 {
8308   // get the active view
8309   Handle(V3d_View) aView = ViewerTest::CurrentView();
8310   if (aView.IsNull())
8311   {
8312     std::cerr << "No active view. Please call vinit.\n";
8313     return 1;
8314   }
8315
8316   // Checking the input arguments
8317   Standard_Boolean anEnableFlag = Standard_False;
8318   Standard_Boolean isOk         = theArgNb >= 2;
8319   if (isOk)
8320   {
8321     TCollection_AsciiString anEnableOpt(theArgVec[1]);
8322     anEnableFlag = anEnableOpt.IsEqual("on");
8323     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
8324   }
8325   if (anEnableFlag)
8326   {
8327     isOk = (theArgNb == 3 || theArgNb == 11);
8328     if (isOk)
8329     {
8330       TCollection_AsciiString aTextureOpt(theArgVec[2]);
8331       isOk = (!aTextureOpt.IsIntegerValue() ||
8332              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8333
8334       if (isOk && theArgNb == 11)
8335       {
8336         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
8337                                 aModulateOpt(theArgVec[4]),
8338                                 aFilterOpt  (theArgVec[5]),
8339                                 aSScaleOpt  (theArgVec[6]),
8340                                 aTScaleOpt  (theArgVec[7]),
8341                                 aSTransOpt  (theArgVec[8]),
8342                                 aTTransOpt  (theArgVec[9]),
8343                                 anAngleOpt  (theArgVec[10]);
8344         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
8345                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8346                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
8347                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
8348                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
8349                 anAngleOpt.IsRealValue());
8350       }
8351     }
8352   }
8353
8354   if (!isOk)
8355   {
8356     std::cerr << "Usage :" << std::endl;
8357     std::cerr << theArgVec[0] << " off" << std::endl;
8358     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;
8359     return 1;
8360   }
8361
8362   if (anEnableFlag)
8363   {
8364     TCollection_AsciiString aTextureOpt(theArgVec[2]);
8365     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8366                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8367                                      new OCC_TextureEnv(theArgVec[2]);
8368
8369     if (theArgNb == 11)
8370     {
8371       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8372       aTexEnv->SetTextureParameters(
8373         aRepeatOpt.  IsEqual("repeat"),
8374         aModulateOpt.IsEqual("modulate"),
8375         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8376                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8377                                                                            Graphic3d_TOTF_TRILINEAR,
8378         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8379         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8380         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8381         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8382         (Standard_ShortReal)Draw::Atof(theArgVec[10])
8383         );
8384     }
8385     aView->SetTextureEnv(aTexEnv);
8386   }
8387   else // Disabling environment mapping
8388   {
8389     Handle(Graphic3d_TextureEnv) aTexture;
8390     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8391   }
8392
8393   aView->Redraw();
8394   return 0;
8395 }
8396
8397 namespace
8398 {
8399   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8400
8401   //! Remove registered clipping plane from all views and objects.
8402   static void removePlane (MapOfPlanes& theRegPlanes,
8403                            const TCollection_AsciiString& theName)
8404   {
8405     Handle(Graphic3d_ClipPlane) aClipPlane;
8406     if (!theRegPlanes.Find (theName, aClipPlane))
8407     {
8408       std::cout << "Warning: no such plane.\n";
8409       return;
8410     }
8411
8412     theRegPlanes.UnBind (theName);
8413     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8414          anIObjIt.More(); anIObjIt.Next())
8415     {
8416       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
8417       aPrs->RemoveClipPlane (aClipPlane);
8418     }
8419
8420     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8421          aViewIt.More(); aViewIt.Next())
8422     {
8423       const Handle(V3d_View)& aView = aViewIt.Key2();
8424       aView->RemoveClipPlane(aClipPlane);
8425     }
8426
8427     ViewerTest::RedrawAllViews();
8428   }
8429 }
8430
8431 //===============================================================================================
8432 //function : VClipPlane
8433 //purpose  :
8434 //===============================================================================================
8435 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8436 {
8437   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8438   static MapOfPlanes aRegPlanes;
8439
8440   if (theArgsNb < 2)
8441   {
8442     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8443     {
8444       theDi << aPlaneIter.Key() << " ";
8445     }
8446     return 0;
8447   }
8448
8449   TCollection_AsciiString aCommand (theArgVec[1]);
8450   aCommand.LowerCase();
8451   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8452   if (anActiveView.IsNull())
8453   {
8454     std::cout << "Error: no active view.\n";
8455     return 1;
8456   }
8457
8458   // print maximum number of planes for current viewer
8459   if (aCommand == "-maxplanes"
8460    || aCommand == "maxplanes")
8461   {
8462     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8463           << " plane slots provided by driver.\n";
8464     return 0;
8465   }
8466
8467   // create / delete plane instance
8468   if (aCommand == "-create"
8469    || aCommand == "create"
8470    || aCommand == "-delete"
8471    || aCommand == "delete"
8472    || aCommand == "-clone"
8473    || aCommand == "clone")
8474   {
8475     if (theArgsNb < 3)
8476     {
8477       std::cout << "Syntax error: plane name is required.\n";
8478       return 1;
8479     }
8480
8481     Standard_Boolean toCreate = aCommand == "-create"
8482                              || aCommand == "create";
8483     Standard_Boolean toClone  = aCommand == "-clone"
8484                              || aCommand == "clone";
8485     Standard_Boolean toDelete = aCommand == "-delete"
8486                              || aCommand == "delete";
8487     TCollection_AsciiString aPlane (theArgVec[2]);
8488
8489     if (toCreate)
8490     {
8491       if (aRegPlanes.IsBound (aPlane))
8492       {
8493         std::cout << "Warning: existing plane has been overridden.\n";
8494         toDelete = true;
8495       }
8496       else
8497       {
8498         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8499         return 0;
8500       }
8501     }
8502     else if (toClone) // toClone
8503     {
8504       if (!aRegPlanes.IsBound (aPlane))
8505       {
8506         std::cout << "Error: no such plane.\n";
8507         return 1;
8508       }
8509       else if (theArgsNb < 4)
8510       {
8511         std::cout << "Syntax error: enter name for new plane.\n";
8512         return 1;
8513       }
8514
8515       TCollection_AsciiString aClone (theArgVec[3]);
8516       if (aRegPlanes.IsBound (aClone))
8517       {
8518         std::cout << "Error: plane name is in use.\n";
8519         return 1;
8520       }
8521
8522       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8523
8524       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8525       return 0;
8526     }
8527
8528     if (toDelete)
8529     {
8530       if (aPlane == "ALL"
8531        || aPlane == "all"
8532        || aPlane == "*")
8533       {
8534         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8535         {
8536           aPlane = aPlaneIter.Key();
8537           removePlane (aRegPlanes, aPlane);
8538           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8539         }
8540       }
8541       else
8542       {
8543         removePlane (aRegPlanes, aPlane);
8544       }
8545     }
8546
8547     if (toCreate)
8548     {
8549       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8550     }
8551     return 0;
8552   }
8553
8554   // set / unset plane command
8555   if (aCommand == "set"
8556    || aCommand == "unset")
8557   {
8558     if (theArgsNb < 5)
8559     {
8560       std::cout << "Syntax error: need more arguments.\n";
8561       return 1;
8562     }
8563
8564     // redirect to new syntax
8565     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8566     anArgVec.SetValue (1, theArgVec[0]);
8567     anArgVec.SetValue (2, theArgVec[2]);
8568     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8569     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8570     {
8571       anArgVec.SetValue (anIt, theArgVec[anIt]);
8572     }
8573
8574     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8575   }
8576
8577   // change plane command
8578   TCollection_AsciiString aPlaneName;
8579   Handle(Graphic3d_ClipPlane) aClipPlane;
8580   Standard_Integer anArgIter = 0;
8581   if (aCommand == "-change"
8582    || aCommand == "change")
8583   {
8584     // old syntax support
8585     if (theArgsNb < 3)
8586     {
8587       std::cout << "Syntax error: need more arguments.\n";
8588       return 1;
8589     }
8590
8591     anArgIter  = 3;
8592     aPlaneName = theArgVec[2];
8593     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8594     {
8595       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8596       return 1;
8597     }
8598   }
8599   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8600   {
8601     anArgIter  = 2;
8602     aPlaneName = theArgVec[1];
8603   }
8604   else
8605   {
8606     anArgIter  = 2;
8607     aPlaneName = theArgVec[1];
8608     aClipPlane = new Graphic3d_ClipPlane();
8609     aRegPlanes.Bind (aPlaneName, aClipPlane);
8610     theDi << "Created new plane " << aPlaneName << ".\n";
8611   }
8612
8613   if (theArgsNb - anArgIter < 1)
8614   {
8615     std::cout << "Syntax error: need more arguments.\n";
8616     return 1;
8617   }
8618
8619   for (; anArgIter < theArgsNb; ++anArgIter)
8620   {
8621     const char**     aChangeArgs   = theArgVec + anArgIter;
8622     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8623     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8624     aChangeArg.LowerCase();
8625
8626     Standard_Boolean toEnable = Standard_True;
8627     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8628     {
8629       aClipPlane->SetOn (toEnable);
8630     }
8631     else if (aChangeArg.StartsWith ("-equation")
8632           || aChangeArg.StartsWith ("equation"))
8633     {
8634       if (aNbChangeArgs < 5)
8635       {
8636         std::cout << "Syntax error: need more arguments.\n";
8637         return 1;
8638       }
8639
8640       Standard_Integer aSubIndex = 1;
8641       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
8642       if (aPrefixLen < aChangeArg.Length())
8643       {
8644         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
8645         if (!aSubStr.IsIntegerValue()
8646           || aSubStr.IntegerValue() <= 0)
8647         {
8648           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8649           return 1;
8650         }
8651         aSubIndex = aSubStr.IntegerValue();
8652       }
8653
8654       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
8655       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
8656       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
8657       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
8658       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8659       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
8660       {
8661         if (aSubPln->ChainNextPlane().IsNull())
8662         {
8663           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8664         }
8665         aSubPln = aSubPln->ChainNextPlane();
8666       }
8667       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8668       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8669       anArgIter += 4;
8670     }
8671     else if ((aChangeArg == "-boxinterior"
8672            || aChangeArg == "-boxint"
8673            || aChangeArg == "-box")
8674             && aNbChangeArgs >= 7)
8675     {
8676       Graphic3d_BndBox3d aBndBox;
8677       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
8678       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
8679       anArgIter += 6;
8680
8681       Standard_Integer aNbSubPlanes = 6;
8682       const Graphic3d_Vec3d aDirArray[6] =
8683       {
8684         Graphic3d_Vec3d (-1, 0, 0),
8685         Graphic3d_Vec3d ( 1, 0, 0),
8686         Graphic3d_Vec3d ( 0,-1, 0),
8687         Graphic3d_Vec3d ( 0, 1, 0),
8688         Graphic3d_Vec3d ( 0, 0,-1),
8689         Graphic3d_Vec3d ( 0, 0, 1),
8690       };
8691       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8692       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
8693       {
8694         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
8695         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
8696         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
8697         if (aSubPlaneIter + 1 == aNbSubPlanes)
8698         {
8699           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8700         }
8701         else
8702         {
8703           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8704         }
8705         aSubPln = aSubPln->ChainNextPlane();
8706       }
8707     }
8708     else if (aChangeArg == "-capping"
8709           || aChangeArg == "capping")
8710     {
8711       if (aNbChangeArgs < 2)
8712       {
8713         std::cout << "Syntax error: need more arguments.\n";
8714         return 1;
8715       }
8716
8717       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8718       {
8719         aClipPlane->SetCapping (toEnable);
8720         anArgIter += 1;
8721       }
8722       else
8723       {
8724         // just skip otherwise (old syntax)
8725       }
8726     }
8727     else if (aChangeArg == "-useobjectmaterial"
8728           || aChangeArg == "-useobjectmat"
8729           || aChangeArg == "-useobjmat"
8730           || aChangeArg == "-useobjmaterial")
8731     {
8732       if (aNbChangeArgs < 2)
8733       {
8734         std::cout << "Syntax error: need more arguments.\n";
8735         return 1;
8736       }
8737
8738       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8739       {
8740         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8741         anArgIter += 1;
8742       }
8743     }
8744     else if (aChangeArg == "-useobjecttexture"
8745           || aChangeArg == "-useobjecttex"
8746           || aChangeArg == "-useobjtexture"
8747           || aChangeArg == "-useobjtex")
8748     {
8749       if (aNbChangeArgs < 2)
8750       {
8751         std::cout << "Syntax error: need more arguments.\n";
8752         return 1;
8753       }
8754
8755       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8756       {
8757         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8758         anArgIter += 1;
8759       }
8760     }
8761     else if (aChangeArg == "-useobjectshader"
8762           || aChangeArg == "-useobjshader")
8763     {
8764       if (aNbChangeArgs < 2)
8765       {
8766         std::cout << "Syntax error: need more arguments.\n";
8767         return 1;
8768       }
8769
8770       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8771       {
8772         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8773         anArgIter += 1;
8774       }
8775     }
8776     else if (aChangeArg == "-color"
8777           || aChangeArg == "color")
8778     {
8779       Quantity_Color aColor;
8780       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8781                                                            aChangeArgs + 1,
8782                                                            aColor);
8783       if (aNbParsed == 0)
8784       {
8785         std::cout << "Syntax error: need more arguments.\n";
8786         return 1;
8787       }
8788
8789       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8790       aMat.SetAmbientColor (aColor);
8791       aMat.SetDiffuseColor (aColor);
8792       aClipPlane->SetCappingMaterial (aMat);
8793       anArgIter += aNbParsed;
8794     }
8795     else if ((aChangeArg == "-transparency"
8796            || aChangeArg == "-transp")
8797           && aNbChangeArgs >= 2)
8798     {
8799       TCollection_AsciiString aValStr (aChangeArgs[1]);
8800       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
8801       if (aValStr.IsRealValue())
8802       {
8803         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8804         aMat.SetTransparency ((float )aValStr.RealValue());
8805         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
8806         aClipPlane->SetCappingMaterial (aMat);
8807       }
8808       else
8809       {
8810         aValStr.LowerCase();
8811         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
8812         if (aValStr == "opaque")
8813         {
8814           aMode = Graphic3d_AlphaMode_Opaque;
8815         }
8816         else if (aValStr == "mask")
8817         {
8818           aMode = Graphic3d_AlphaMode_Mask;
8819         }
8820         else if (aValStr == "blend")
8821         {
8822           aMode = Graphic3d_AlphaMode_Blend;
8823         }
8824         else if (aValStr == "blendauto")
8825         {
8826           aMode = Graphic3d_AlphaMode_BlendAuto;
8827         }
8828         else
8829         {
8830           std::cout << "Syntax error at '" << aValStr << "'\n";
8831           return 1;
8832         }
8833         anAspect->SetAlphaMode (aMode);
8834         aClipPlane->SetCappingAspect (anAspect);
8835       }
8836       anArgIter += 1;
8837     }
8838     else if (aChangeArg == "-texname"
8839           || aChangeArg == "texname")
8840     {
8841       if (aNbChangeArgs < 2)
8842       {
8843         std::cout << "Syntax error: need more arguments.\n";
8844         return 1;
8845       }
8846
8847       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8848       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8849       if (!aTexture->IsDone())
8850       {
8851         aClipPlane->SetCappingTexture (NULL);
8852       }
8853       else
8854       {
8855         aTexture->EnableModulate();
8856         aTexture->EnableRepeat();
8857         aClipPlane->SetCappingTexture (aTexture);
8858       }
8859       anArgIter += 1;
8860     }
8861     else if (aChangeArg == "-texscale"
8862           || aChangeArg == "texscale")
8863     {
8864       if (aClipPlane->CappingTexture().IsNull())
8865       {
8866         std::cout << "Error: no texture is set.\n";
8867         return 1;
8868       }
8869
8870       if (aNbChangeArgs < 3)
8871       {
8872         std::cout << "Syntax error: need more arguments.\n";
8873         return 1;
8874       }
8875
8876       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8877       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8878       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8879       anArgIter += 2;
8880     }
8881     else if (aChangeArg == "-texorigin"
8882           || aChangeArg == "texorigin") // texture origin
8883     {
8884       if (aClipPlane->CappingTexture().IsNull())
8885       {
8886         std::cout << "Error: no texture is set.\n";
8887         return 1;
8888       }
8889
8890       if (aNbChangeArgs < 3)
8891       {
8892         std::cout << "Syntax error: need more arguments.\n";
8893         return 1;
8894       }
8895
8896       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8897       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8898
8899       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8900       anArgIter += 2;
8901     }
8902     else if (aChangeArg == "-texrotate"
8903           || aChangeArg == "texrotate") // texture rotation
8904     {
8905       if (aClipPlane->CappingTexture().IsNull())
8906       {
8907         std::cout << "Error: no texture is set.\n";
8908         return 1;
8909       }
8910
8911       if (aNbChangeArgs < 2)
8912       {
8913         std::cout << "Syntax error: need more arguments.\n";
8914         return 1;
8915       }
8916
8917       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8918       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8919       anArgIter += 1;
8920     }
8921     else if (aChangeArg == "-hatch"
8922           || aChangeArg == "hatch")
8923     {
8924       if (aNbChangeArgs < 2)
8925       {
8926         std::cout << "Syntax error: need more arguments.\n";
8927         return 1;
8928       }
8929
8930       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8931       aHatchStr.LowerCase();
8932       if (aHatchStr == "on")
8933       {
8934         aClipPlane->SetCappingHatchOn();
8935       }
8936       else if (aHatchStr == "off")
8937       {
8938         aClipPlane->SetCappingHatchOff();
8939       }
8940       else
8941       {
8942         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8943       }
8944       anArgIter += 1;
8945     }
8946     else if (aChangeArg == "-delete"
8947           || aChangeArg == "delete")
8948     {
8949       removePlane (aRegPlanes, aPlaneName);
8950       return 0;
8951     }
8952     else if (aChangeArg == "-set"
8953           || aChangeArg == "-unset"
8954           || aChangeArg == "-setoverrideglobal")
8955     {
8956       // set / unset plane command
8957       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
8958       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
8959       Standard_Integer anIt = 1;
8960       for (; anIt < aNbChangeArgs; ++anIt)
8961       {
8962         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8963         if (anEntityName.IsEmpty()
8964          || anEntityName.Value (1) == '-')
8965         {
8966           break;
8967         }
8968         else if (!toOverrideGlobal
8969                && ViewerTest_myViews.IsBound1 (anEntityName))
8970         {
8971           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8972           if (toSet)
8973           {
8974             aView->AddClipPlane (aClipPlane);
8975           }
8976           else
8977           {
8978             aView->RemoveClipPlane (aClipPlane);
8979           }
8980           continue;
8981         }
8982         else if (GetMapOfAIS().IsBound2 (anEntityName))
8983         {
8984           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
8985           if (toSet)
8986           {
8987             aIObj->AddClipPlane (aClipPlane);
8988           }
8989           else
8990           {
8991             aIObj->RemoveClipPlane (aClipPlane);
8992           }
8993           if (!aIObj->ClipPlanes().IsNull())
8994           {
8995             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
8996           }
8997         }
8998         else
8999         {
9000           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9001           return 1;
9002         }
9003       }
9004
9005       if (anIt == 1)
9006       {
9007         // apply to active view
9008         if (toSet)
9009         {
9010           anActiveView->AddClipPlane (aClipPlane);
9011         }
9012         else
9013         {
9014           anActiveView->RemoveClipPlane (aClipPlane);
9015         }
9016       }
9017       else
9018       {
9019         anArgIter = anArgIter + anIt - 1;
9020       }
9021     }
9022     else
9023     {
9024       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9025       return 1;
9026     }
9027   }
9028
9029   ViewerTest::RedrawAllViews();
9030   return 0;
9031 }
9032
9033 //===============================================================================================
9034 //function : VZRange
9035 //purpose  :
9036 //===============================================================================================
9037 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9038 {
9039   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9040
9041   if (aCurrentView.IsNull())
9042   {
9043     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9044     return 1;
9045   }
9046
9047   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9048
9049   if (theArgsNb < 2)
9050   {
9051     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9052     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9053     return 0;
9054   }
9055
9056   if (theArgsNb == 3)
9057   {
9058     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9059     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9060
9061     if (aNewZNear >= aNewZFar)
9062     {
9063       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9064       return 1;
9065     }
9066
9067     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9068     {
9069       std::cout << theArgVec[0] << ": invalid arguments: ";
9070       std::cout << "znear, zfar should be positive for perspective camera.\n";
9071       return 1;
9072     }
9073
9074     aCamera->SetZRange (aNewZNear, aNewZFar);
9075   }
9076   else
9077   {
9078     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9079     return 1;
9080   }
9081
9082   aCurrentView->Redraw();
9083
9084   return 0;
9085 }
9086
9087 //===============================================================================================
9088 //function : VAutoZFit
9089 //purpose  :
9090 //===============================================================================================
9091 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9092 {
9093   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9094
9095   if (aCurrentView.IsNull())
9096   {
9097     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9098     return 1;
9099   }
9100
9101   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9102
9103   if (theArgsNb > 3)
9104   {
9105     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9106     return 1;
9107   }
9108
9109   if (theArgsNb < 2)
9110   {
9111     theDi << "Auto z-fit mode: \n"
9112           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9113           << "Scale: " << aScale << "\n";
9114     return 0;
9115   }
9116
9117   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9118
9119   if (theArgsNb >= 3)
9120   {
9121     aScale = Draw::Atoi (theArgVec[2]);
9122   }
9123
9124   aCurrentView->SetAutoZFitMode (isOn, aScale);
9125   aCurrentView->AutoZFit();
9126   aCurrentView->Redraw();
9127
9128   return 0;
9129 }
9130
9131 //! Auxiliary function to print projection type
9132 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9133 {
9134   switch (theProjType)
9135   {
9136     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9137     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9138     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9139     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9140     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9141   }
9142   return "UNKNOWN";
9143 }
9144
9145 //===============================================================================================
9146 //function : VCamera
9147 //purpose  :
9148 //===============================================================================================
9149 static int VCamera (Draw_Interpretor& theDI,
9150                     Standard_Integer  theArgsNb,
9151                     const char**      theArgVec)
9152 {
9153   Handle(V3d_View) aView = ViewerTest::CurrentView();
9154   if (aView.IsNull())
9155   {
9156     std::cout << "Error: no active view.\n";
9157     return 1;
9158   }
9159
9160   Handle(Graphic3d_Camera) aCamera = aView->Camera();
9161   if (theArgsNb < 2)
9162   {
9163     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
9164     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
9165     theDI << "Distance:   " << aCamera->Distance() << "\n";
9166     theDI << "IOD:        " << aCamera->IOD() << "\n";
9167     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
9168     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
9169     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
9170     return 0;
9171   }
9172
9173   TCollection_AsciiString aPrsName;
9174   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9175   {
9176     Standard_CString        anArg = theArgVec[anArgIter];
9177     TCollection_AsciiString anArgCase (anArg);
9178     anArgCase.LowerCase();
9179     if (anArgCase == "-proj"
9180      || anArgCase == "-projection"
9181      || anArgCase == "-projtype"
9182      || anArgCase == "-projectiontype")
9183     {
9184       theDI << projTypeName (aCamera->ProjectionType()) << " ";
9185     }
9186     else if (anArgCase == "-ortho"
9187           || anArgCase == "-orthographic")
9188     {
9189       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
9190     }
9191     else if (anArgCase == "-persp"
9192           || anArgCase == "-perspective"
9193           || anArgCase == "-perspmono"
9194           || anArgCase == "-perspectivemono"
9195           || anArgCase == "-mono")
9196     {
9197       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9198     }
9199     else if (anArgCase == "-stereo"
9200           || anArgCase == "-stereoscopic"
9201           || anArgCase == "-perspstereo"
9202           || anArgCase == "-perspectivestereo")
9203     {
9204       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9205     }
9206     else if (anArgCase == "-left"
9207           || anArgCase == "-lefteye"
9208           || anArgCase == "-monoleft"
9209           || anArgCase == "-monolefteye"
9210           || anArgCase == "-perpsleft"
9211           || anArgCase == "-perpslefteye")
9212     {
9213       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
9214     }
9215     else if (anArgCase == "-right"
9216           || anArgCase == "-righteye"
9217           || anArgCase == "-monoright"
9218           || anArgCase == "-monorighteye"
9219           || anArgCase == "-perpsright")
9220     {
9221       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
9222     }
9223     else if (anArgCase == "-dist"
9224           || anArgCase == "-distance")
9225     {
9226       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9227       if (anArgValue != NULL
9228       && *anArgValue != '-')
9229       {
9230         ++anArgIter;
9231         aCamera->SetDistance (Draw::Atof (anArgValue));
9232         continue;
9233       }
9234       theDI << aCamera->Distance() << " ";
9235     }
9236     else if (anArgCase == "-iod")
9237     {
9238       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9239       if (anArgValue != NULL
9240       && *anArgValue != '-')
9241       {
9242         ++anArgIter;
9243         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
9244         continue;
9245       }
9246       theDI << aCamera->IOD() << " ";
9247     }
9248     else if (anArgCase == "-iodtype")
9249     {
9250       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9251       TCollection_AsciiString anValueCase (anArgValue);
9252       anValueCase.LowerCase();
9253       if (anValueCase == "abs"
9254        || anValueCase == "absolute")
9255       {
9256         ++anArgIter;
9257         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
9258         continue;
9259       }
9260       else if (anValueCase == "rel"
9261             || anValueCase == "relative")
9262       {
9263         ++anArgIter;
9264         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
9265         continue;
9266       }
9267       else if (*anArgValue != '-')
9268       {
9269         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
9270         return 1;
9271       }
9272       switch (aCamera->GetIODType())
9273       {
9274         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
9275         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
9276       }
9277     }
9278     else if (anArgCase == "-zfocus")
9279     {
9280       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9281       if (anArgValue != NULL
9282       && *anArgValue != '-')
9283       {
9284         ++anArgIter;
9285         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
9286         continue;
9287       }
9288       theDI << aCamera->ZFocus() << " ";
9289     }
9290     else if (anArgCase == "-zfocustype")
9291     {
9292       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9293       TCollection_AsciiString anValueCase (anArgValue);
9294       anValueCase.LowerCase();
9295       if (anValueCase == "abs"
9296        || anValueCase == "absolute")
9297       {
9298         ++anArgIter;
9299         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
9300         continue;
9301       }
9302       else if (anValueCase == "rel"
9303             || anValueCase == "relative")
9304       {
9305         ++anArgIter;
9306         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
9307         continue;
9308       }
9309       else if (*anArgValue != '-')
9310       {
9311         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
9312         return 1;
9313       }
9314       switch (aCamera->ZFocusType())
9315       {
9316         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
9317         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
9318       }
9319     }
9320     else if (anArgCase == "-fov"
9321           || anArgCase == "-fovy")
9322     {
9323       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9324       if (anArgValue != NULL
9325       && *anArgValue != '-')
9326       {
9327         ++anArgIter;
9328         aCamera->SetFOVy (Draw::Atof (anArgValue));
9329         continue;
9330       }
9331       theDI << aCamera->FOVy() << " ";
9332     }
9333     else if (aPrsName.IsEmpty()
9334          && !anArgCase.StartsWith ("-"))
9335     {
9336       aPrsName = anArg;
9337     }
9338     else
9339     {
9340       std::cout << "Error: unknown argument '" << anArg << "'\n";
9341       return 1;
9342     }
9343   }
9344
9345   if (aPrsName.IsEmpty()
9346    || theArgsNb > 2)
9347   {
9348     aView->AutoZFit();
9349     aView->Redraw();
9350   }
9351
9352   if (!aPrsName.IsEmpty())
9353   {
9354     Handle(AIS_CameraFrustum) aCameraFrustum;
9355     if (GetMapOfAIS().IsBound2 (aPrsName))
9356     {
9357       // find existing object
9358       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
9359       if (aCameraFrustum.IsNull())
9360       {
9361         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
9362         return 1;
9363       }
9364     }
9365
9366     if (aCameraFrustum.IsNull())
9367     {
9368       aCameraFrustum = new AIS_CameraFrustum();
9369     }
9370     else
9371     {
9372       // not include displayed object of old camera frustum in the new one.
9373       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
9374       aView->ZFitAll();
9375     }
9376     aCameraFrustum->SetCameraFrustum (aView->Camera());
9377
9378     ViewerTest::Display (aPrsName, aCameraFrustum);
9379   }
9380
9381   return 0;
9382 }
9383
9384 //! Parse stereo output mode
9385 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
9386                                          Graphic3d_StereoMode& theMode)
9387 {
9388   TCollection_AsciiString aFlag (theArg);
9389   aFlag.LowerCase();
9390   if (aFlag == "quadbuffer")
9391   {
9392     theMode = Graphic3d_StereoMode_QuadBuffer;
9393   }
9394   else if (aFlag == "anaglyph")
9395   {
9396     theMode = Graphic3d_StereoMode_Anaglyph;
9397   }
9398   else if (aFlag == "row"
9399         || aFlag == "rowinterlaced")
9400   {
9401     theMode = Graphic3d_StereoMode_RowInterlaced;
9402   }
9403   else if (aFlag == "col"
9404         || aFlag == "colinterlaced"
9405         || aFlag == "columninterlaced")
9406   {
9407     theMode = Graphic3d_StereoMode_ColumnInterlaced;
9408   }
9409   else if (aFlag == "chess"
9410         || aFlag == "chessboard")
9411   {
9412     theMode = Graphic3d_StereoMode_ChessBoard;
9413   }
9414   else if (aFlag == "sbs"
9415         || aFlag == "sidebyside")
9416   {
9417     theMode = Graphic3d_StereoMode_SideBySide;
9418   }
9419   else if (aFlag == "ou"
9420         || aFlag == "overunder")
9421   {
9422     theMode = Graphic3d_StereoMode_OverUnder;
9423   }
9424   else if (aFlag == "pageflip"
9425         || aFlag == "softpageflip")
9426   {
9427     theMode = Graphic3d_StereoMode_SoftPageFlip;
9428   }
9429   else
9430   {
9431     return Standard_False;
9432   }
9433   return Standard_True;
9434 }
9435
9436 //! Parse anaglyph filter
9437 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
9438                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
9439 {
9440   TCollection_AsciiString aFlag (theArg);
9441   aFlag.LowerCase();
9442   if (aFlag == "redcyansimple")
9443   {
9444     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9445   }
9446   else if (aFlag == "redcyan"
9447         || aFlag == "redcyanoptimized")
9448   {
9449     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
9450   }
9451   else if (aFlag == "yellowbluesimple")
9452   {
9453     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
9454   }
9455   else if (aFlag == "yellowblue"
9456         || aFlag == "yellowblueoptimized")
9457   {
9458     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
9459   }
9460   else if (aFlag == "greenmagenta"
9461         || aFlag == "greenmagentasimple")
9462   {
9463     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
9464   }
9465   else
9466   {
9467     return Standard_False;
9468   }
9469   return Standard_True;
9470 }
9471
9472 //==============================================================================
9473 //function : VStereo
9474 //purpose  :
9475 //==============================================================================
9476
9477 static int VStereo (Draw_Interpretor& theDI,
9478                     Standard_Integer  theArgNb,
9479                     const char**      theArgVec)
9480 {
9481   Handle(V3d_View) aView = ViewerTest::CurrentView();
9482   if (theArgNb < 2)
9483   {
9484     if (aView.IsNull())
9485     {
9486       std::cout << "Error: no active viewer!\n";
9487       return 0;
9488     }
9489
9490     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
9491     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
9492     if (isActive)
9493     {
9494       TCollection_AsciiString aMode;
9495       switch (aView->RenderingParams().StereoMode)
9496       {
9497         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
9498         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
9499         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
9500         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
9501         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
9502         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
9503         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
9504         case Graphic3d_StereoMode_Anaglyph  :
9505           aMode = "anaglyph";
9506           switch (aView->RenderingParams().AnaglyphFilter)
9507           {
9508             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
9509             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
9510             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
9511             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
9512             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
9513             default: break;
9514           }
9515         default: break;
9516       }
9517       theDI << "Mode " << aMode << "\n";
9518     }
9519     return 0;
9520   }
9521
9522   Handle(Graphic3d_Camera) aCamera;
9523   Graphic3d_RenderingParams*   aParams   = NULL;
9524   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
9525   if (!aView.IsNull())
9526   {
9527     aParams   = &aView->ChangeRenderingParams();
9528     aMode     = aParams->StereoMode;
9529     aCamera   = aView->Camera();
9530   }
9531
9532   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9533   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9534   {
9535     Standard_CString        anArg = theArgVec[anArgIter];
9536     TCollection_AsciiString aFlag (anArg);
9537     aFlag.LowerCase();
9538     if (anUpdateTool.parseRedrawMode (aFlag))
9539     {
9540       continue;
9541     }
9542     else if (aFlag == "0"
9543           || aFlag == "off")
9544     {
9545       if (++anArgIter < theArgNb)
9546       {
9547         std::cout << "Error: wrong number of arguments!\n";
9548         return 1;
9549       }
9550
9551       if (!aCamera.IsNull()
9552        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
9553       {
9554         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9555       }
9556       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
9557       return 0;
9558     }
9559     else if (aFlag == "1"
9560           || aFlag == "on")
9561     {
9562       if (++anArgIter < theArgNb)
9563       {
9564         std::cout << "Error: wrong number of arguments!\n";
9565         return 1;
9566       }
9567
9568       if (!aCamera.IsNull())
9569       {
9570         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9571       }
9572       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9573       return 0;
9574     }
9575     else if (aFlag == "-reverse"
9576           || aFlag == "-reversed"
9577           || aFlag == "-swap")
9578     {
9579       Standard_Boolean toEnable = Standard_True;
9580       if (++anArgIter < theArgNb
9581       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9582       {
9583         --anArgIter;
9584       }
9585       aParams->ToReverseStereo = toEnable;
9586     }
9587     else if (aFlag == "-noreverse"
9588           || aFlag == "-noswap")
9589     {
9590       Standard_Boolean toDisable = Standard_True;
9591       if (++anArgIter < theArgNb
9592       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9593       {
9594         --anArgIter;
9595       }
9596       aParams->ToReverseStereo = !toDisable;
9597     }
9598     else if (aFlag == "-mode"
9599           || aFlag == "-stereomode")
9600     {
9601       if (++anArgIter >= theArgNb
9602       || !parseStereoMode (theArgVec[anArgIter], aMode))
9603       {
9604         std::cout << "Error: syntax error at '" << anArg << "'\n";
9605         return 1;
9606       }
9607
9608       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9609       {
9610         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9611       }
9612     }
9613     else if (aFlag == "-anaglyph"
9614           || aFlag == "-anaglyphfilter")
9615     {
9616       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9617       if (++anArgIter >= theArgNb
9618       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9619       {
9620         std::cout << "Error: syntax error at '" << anArg << "'\n";
9621         return 1;
9622       }
9623
9624       aMode = Graphic3d_StereoMode_Anaglyph;
9625       aParams->AnaglyphFilter = aFilter;
9626     }
9627     else if (parseStereoMode (anArg, aMode)) // short syntax
9628     {
9629       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9630       {
9631         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9632       }
9633     }
9634     else
9635     {
9636       std::cout << "Error: syntax error at '" << anArg << "'\n";
9637       return 1;
9638     }
9639   }
9640
9641   if (!aView.IsNull())
9642   {
9643     aParams->StereoMode = aMode;
9644     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9645   }
9646   return 0;
9647 }
9648
9649 //===============================================================================================
9650 //function : VDefaults
9651 //purpose  :
9652 //===============================================================================================
9653 static int VDefaults (Draw_Interpretor& theDi,
9654                       Standard_Integer  theArgsNb,
9655                       const char**      theArgVec)
9656 {
9657   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9658   if (aCtx.IsNull())
9659   {
9660     std::cerr << "No active viewer!\n";
9661     return 1;
9662   }
9663
9664   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9665   if (theArgsNb < 2)
9666   {
9667     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9668     {
9669       theDi << "DeflType:           relative\n"
9670             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9671     }
9672     else
9673     {
9674       theDi << "DeflType:           absolute\n"
9675             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9676     }
9677     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9678     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9679     return 0;
9680   }
9681
9682   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9683   {
9684     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9685     anArg.UpperCase();
9686     if (anArg == "-ABSDEFL"
9687      || anArg == "-ABSOLUTEDEFLECTION"
9688      || anArg == "-DEFL"
9689      || anArg == "-DEFLECTION")
9690     {
9691       if (++anArgIter >= theArgsNb)
9692       {
9693         std::cout << "Error: wrong syntax at " << anArg << "\n";
9694         return 1;
9695       }
9696       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9697       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9698     }
9699     else if (anArg == "-RELDEFL"
9700           || anArg == "-RELATIVEDEFLECTION"
9701           || anArg == "-DEVCOEFF"
9702           || anArg == "-DEVIATIONCOEFF"
9703           || anArg == "-DEVIATIONCOEFFICIENT")
9704     {
9705       if (++anArgIter >= theArgsNb)
9706       {
9707         std::cout << "Error: wrong syntax at " << anArg << "\n";
9708         return 1;
9709       }
9710       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9711       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9712     }
9713     else if (anArg == "-ANGDEFL"
9714           || anArg == "-ANGULARDEFL"
9715           || anArg == "-ANGULARDEFLECTION")
9716     {
9717       if (++anArgIter >= theArgsNb)
9718       {
9719         std::cout << "Error: wrong syntax at " << anArg << "\n";
9720         return 1;
9721       }
9722       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9723       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9724     }
9725     else if (anArg == "-AUTOTR"
9726           || anArg == "-AUTOTRIANG"
9727           || anArg == "-AUTOTRIANGULATION")
9728     {
9729       if (++anArgIter >= theArgsNb)
9730       {
9731         std::cout << "Error: wrong syntax at " << anArg << "\n";
9732         return 1;
9733       }
9734       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9735       aValue.LowerCase();
9736       if (aValue == "on"
9737        || aValue == "1")
9738       {
9739         aDefParams->SetAutoTriangulation (Standard_True);
9740       }
9741       else if (aValue == "off"
9742             || aValue == "0")
9743       {
9744         aDefParams->SetAutoTriangulation (Standard_False);
9745       }
9746     }
9747     else
9748     {
9749       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9750     }
9751   }
9752
9753   return 0;
9754 }
9755
9756 //! Auxiliary method
9757 inline void addLight (const Handle(V3d_Light)& theLightNew,
9758                       const Graphic3d_ZLayerId theLayer,
9759                       const Standard_Boolean   theIsGlobal)
9760 {
9761   if (theLightNew.IsNull())
9762   {
9763     return;
9764   }
9765
9766   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9767   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
9768   {
9769     aViewer->AddLight (theLightNew);
9770     if (theIsGlobal)
9771     {
9772       aViewer->SetLightOn (theLightNew);
9773     }
9774     else
9775     {
9776       ViewerTest::CurrentView()->SetLightOn (theLightNew);
9777     }
9778   }
9779   else
9780   {
9781     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
9782     if (aSettings.Lights().IsNull())
9783     {
9784       aSettings.SetLights (new Graphic3d_LightSet());
9785     }
9786     aSettings.Lights()->Add (theLightNew);
9787     aViewer->SetZLayerSettings (theLayer, aSettings);
9788   }
9789 }
9790
9791 //! Auxiliary method
9792 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9793 {
9794   TCollection_AsciiString anArgNextCase (theArgNext);
9795   anArgNextCase.UpperCase();
9796   if (anArgNextCase.Length() > 5
9797    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9798   {
9799     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9800   }
9801   else
9802   {
9803     return theArgNext.IntegerValue();
9804   }
9805 }
9806
9807 //===============================================================================================
9808 //function : VLight
9809 //purpose  :
9810 //===============================================================================================
9811 static int VLight (Draw_Interpretor& theDi,
9812                    Standard_Integer  theArgsNb,
9813                    const char**      theArgVec)
9814 {
9815   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9816   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9817   if (aView.IsNull()
9818    || aViewer.IsNull())
9819   {
9820     std::cerr << "No active viewer!\n";
9821     return 1;
9822   }
9823
9824   Standard_Real anXYZ[3]   = {};
9825   Standard_Real anAtten[2] = {};
9826   if (theArgsNb < 2)
9827   {
9828     // print lights info
9829     Standard_Integer aLightId = 0;
9830     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9831     {
9832       Handle(V3d_Light) aLight = aLightIter.Value();
9833       const Quantity_Color aColor = aLight->Color();
9834       theDi << "Light #" << aLightId
9835             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
9836             << " [" << aLight->GetId() << "]" << "\n";
9837       switch (aLight->Type())
9838       {
9839         case V3d_AMBIENT:
9840         {
9841           theDi << "  Type:       Ambient\n";
9842           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9843           break;
9844         }
9845         case V3d_DIRECTIONAL:
9846         {
9847           theDi << "  Type:       Directional\n";
9848           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9849           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9850           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9851           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9852           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9853           break;
9854         }
9855         case V3d_POSITIONAL:
9856         {
9857           theDi << "  Type:       Positional\n";
9858           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9859           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9860           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9861           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9862           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9863           aLight->Attenuation (anAtten[0], anAtten[1]);
9864           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9865           break;
9866         }
9867         case V3d_SPOT:
9868         {
9869           theDi << "  Type:       Spot\n";
9870           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9871           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9872           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9873           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9874           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9875           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9876           aLight->Attenuation (anAtten[0], anAtten[1]);
9877           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9878           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
9879           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
9880           break;
9881         }
9882         default:
9883         {
9884           theDi << "  Type:       UNKNOWN\n";
9885           break;
9886         }
9887       }
9888       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
9889     }
9890   }
9891
9892   Handle(V3d_Light) aLightNew;
9893   Handle(V3d_Light) aLightOld;
9894   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
9895   Standard_Boolean  isGlobal = Standard_True;
9896   Standard_Boolean  toCreate = Standard_False;
9897   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9898   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9899   {
9900     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9901
9902     TCollection_AsciiString aName, aValue;
9903     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9904     TCollection_AsciiString anArgCase (anArg);
9905     anArgCase.UpperCase();
9906     if (anUpdateTool.parseRedrawMode (anArg))
9907     {
9908       continue;
9909     }
9910
9911     if (anArgCase.IsEqual ("NEW")
9912      || anArgCase.IsEqual ("ADD")
9913      || anArgCase.IsEqual ("CREATE")
9914      || anArgCase.IsEqual ("-NEW")
9915      || anArgCase.IsEqual ("-ADD")
9916      || anArgCase.IsEqual ("-CREATE"))
9917     {
9918       toCreate = Standard_True;
9919     }
9920     else if (anArgCase.IsEqual ("-LAYER")
9921           || anArgCase.IsEqual ("-ZLAYER"))
9922     {
9923       if (++anArgIt >= theArgsNb)
9924       {
9925         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9926         return 1;
9927       }
9928
9929       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
9930       aValStr.LowerCase();
9931       if (aValStr == "default"
9932        || aValStr == "def")
9933       {
9934         aLayer = Graphic3d_ZLayerId_Default;
9935       }
9936       else if (aValStr == "top")
9937       {
9938         aLayer = Graphic3d_ZLayerId_Top;
9939       }
9940       else if (aValStr == "topmost")
9941       {
9942         aLayer = Graphic3d_ZLayerId_Topmost;
9943       }
9944       else if (aValStr == "toposd"
9945             || aValStr == "osd")
9946       {
9947         aLayer = Graphic3d_ZLayerId_TopOSD;
9948       }
9949       else if (aValStr == "botosd"
9950             || aValStr == "bottom")
9951       {
9952         aLayer = Graphic3d_ZLayerId_BotOSD;
9953       }
9954       else if (aValStr.IsIntegerValue())
9955       {
9956         aLayer = Draw::Atoi (theArgVec[anArgIt]);
9957       }
9958       else
9959       {
9960         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
9961         return 1;
9962       }
9963     }
9964     else if (anArgCase.IsEqual ("GLOB")
9965           || anArgCase.IsEqual ("GLOBAL")
9966           || anArgCase.IsEqual ("-GLOB")
9967           || anArgCase.IsEqual ("-GLOBAL"))
9968     {
9969       isGlobal = Standard_True;
9970     }
9971     else if (anArgCase.IsEqual ("LOC")
9972           || anArgCase.IsEqual ("LOCAL")
9973           || anArgCase.IsEqual ("-LOC")
9974           || anArgCase.IsEqual ("-LOCAL"))
9975     {
9976       isGlobal = Standard_False;
9977     }
9978     else if (anArgCase.IsEqual ("DEF")
9979           || anArgCase.IsEqual ("DEFAULTS")
9980           || anArgCase.IsEqual ("-DEF")
9981           || anArgCase.IsEqual ("-DEFAULTS"))
9982     {
9983       toCreate = Standard_False;
9984       aViewer->SetDefaultLights();
9985     }
9986     else if (anArgCase.IsEqual ("CLR")
9987           || anArgCase.IsEqual ("CLEAR")
9988           || anArgCase.IsEqual ("-CLR")
9989           || anArgCase.IsEqual ("-CLEAR"))
9990     {
9991       toCreate = Standard_False;
9992
9993       TColStd_SequenceOfInteger aLayers;
9994       aViewer->GetAllZLayers (aLayers);
9995       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9996       {
9997         if (aLayeriter.Value() == aLayer
9998          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9999         {
10000           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10001           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10002           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10003           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10004           {
10005             break;
10006           }
10007         }
10008       }
10009
10010       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10011       {
10012         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10013         {
10014           Handle(V3d_Light) aLight = aLightIter.Value();
10015           aViewer->DelLight (aLight);
10016           aLightIter = aView->ActiveLightIterator();
10017         }
10018       }
10019     }
10020     else if (anArgCase.IsEqual ("AMB")
10021           || anArgCase.IsEqual ("AMBIENT")
10022           || anArgCase.IsEqual ("AMBLIGHT"))
10023     {
10024       if (!toCreate)
10025       {
10026         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10027         return 1;
10028       }
10029
10030       addLight (aLightNew, aLayer, isGlobal);
10031       toCreate  = Standard_False;
10032       aLightNew = new V3d_AmbientLight();
10033     }
10034     else if (anArgCase.IsEqual ("DIRECTIONAL")
10035           || anArgCase.IsEqual ("DIRLIGHT"))
10036     {
10037       if (!toCreate)
10038       {
10039         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10040         return 1;
10041       }
10042
10043       addLight (aLightNew, aLayer, isGlobal);
10044       toCreate  = Standard_False;
10045       aLightNew = new V3d_DirectionalLight();
10046     }
10047     else if (anArgCase.IsEqual ("SPOT")
10048           || anArgCase.IsEqual ("SPOTLIGHT"))
10049     {
10050       if (!toCreate)
10051       {
10052         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10053         return 1;
10054       }
10055
10056       addLight (aLightNew, aLayer, isGlobal);
10057       toCreate  = Standard_False;
10058       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10059     }
10060     else if (anArgCase.IsEqual ("POSLIGHT")
10061           || anArgCase.IsEqual ("POSITIONAL"))
10062     {
10063       if (!toCreate)
10064       {
10065         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10066         return 1;
10067       }
10068
10069       addLight (aLightNew, aLayer, isGlobal);
10070       toCreate  = Standard_False;
10071       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10072     }
10073     else if (anArgCase.IsEqual ("CHANGE")
10074           || anArgCase.IsEqual ("-CHANGE"))
10075     {
10076       if (++anArgIt >= theArgsNb)
10077       {
10078         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10079         return 1;
10080       }
10081
10082       addLight (aLightNew, aLayer, isGlobal);
10083       aLightNew.Nullify();
10084       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10085       Standard_Integer aLightIt = 0;
10086       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10087       {
10088         if (aLightIt == aLightId)
10089         {
10090           aLightOld = aLightIter.Value();
10091           break;
10092         }
10093       }
10094
10095       if (aLightOld.IsNull())
10096       {
10097         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10098         return 1;
10099       }
10100     }
10101     else if (anArgCase.IsEqual ("DEL")
10102           || anArgCase.IsEqual ("DELETE")
10103           || anArgCase.IsEqual ("-DEL")
10104           || anArgCase.IsEqual ("-DELETE"))
10105     {
10106       Handle(V3d_Light) aLightDel;
10107       if (++anArgIt >= theArgsNb)
10108       {
10109         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10110         return 1;
10111       }
10112
10113       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10114       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10115       Standard_Integer aLightIt = 0;
10116       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10117       {
10118         aLightDel = aLightIter.Value();
10119         if (aLightIt == aLightDelId)
10120         {
10121           break;
10122         }
10123       }
10124       if (aLightDel.IsNull())
10125       {
10126         continue;
10127       }
10128
10129       TColStd_SequenceOfInteger aLayers;
10130       aViewer->GetAllZLayers (aLayers);
10131       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10132       {
10133         if (aLayeriter.Value() == aLayer
10134          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10135         {
10136           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10137           if (!aSettings.Lights().IsNull())
10138           {
10139             aSettings.Lights()->Remove (aLightDel);
10140             if (aSettings.Lights()->IsEmpty())
10141             {
10142               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10143             }
10144           }
10145           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10146           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10147           {
10148             break;
10149           }
10150         }
10151       }
10152
10153       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10154       {
10155         aViewer->DelLight (aLightDel);
10156       }
10157     }
10158     else if (anArgCase.IsEqual ("COLOR")
10159           || anArgCase.IsEqual ("COLOUR")
10160           || anArgCase.IsEqual ("-COLOR")
10161           || anArgCase.IsEqual ("-COLOUR"))
10162     {
10163       if (++anArgIt >= theArgsNb
10164        || aLightCurr.IsNull())
10165       {
10166         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10167         return 1;
10168       }
10169
10170       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10171       anArgNext.UpperCase();
10172       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
10173       aLightCurr->SetColor (aColor);
10174     }
10175     else if (anArgCase.IsEqual ("POS")
10176           || anArgCase.IsEqual ("POSITION")
10177           || anArgCase.IsEqual ("-POS")
10178           || anArgCase.IsEqual ("-POSITION"))
10179     {
10180       if ((anArgIt + 3) >= theArgsNb
10181        || aLightCurr.IsNull()
10182        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10183         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10184       {
10185         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10186         return 1;
10187       }
10188
10189       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10190       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10191       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10192       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
10193     }
10194     else if (anArgCase.IsEqual ("DIR")
10195           || anArgCase.IsEqual ("DIRECTION")
10196           || anArgCase.IsEqual ("-DIR")
10197           || anArgCase.IsEqual ("-DIRECTION"))
10198     {
10199       if ((anArgIt + 3) >= theArgsNb
10200        || aLightCurr.IsNull()
10201        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
10202         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10203       {
10204         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10205         return 1;
10206       }
10207
10208       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10209       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10210       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10211       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
10212     }
10213     else if (anArgCase.IsEqual ("SM")
10214           || anArgCase.IsEqual ("SMOOTHNESS")
10215           || anArgCase.IsEqual ("-SM")
10216           || anArgCase.IsEqual ("-SMOOTHNESS"))
10217     {
10218       if (++anArgIt >= theArgsNb
10219        || aLightCurr.IsNull())
10220       {
10221         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10222         return 1;
10223       }
10224
10225       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10226       if (Abs (aSmoothness) <= ShortRealEpsilon())
10227       {
10228         aLightCurr->SetIntensity (1.f);
10229       }
10230       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
10231       {
10232         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
10233       }
10234       else
10235       {
10236         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
10237         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
10238       }
10239
10240       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
10241       {
10242         aLightCurr->SetSmoothRadius (aSmoothness);
10243       }
10244       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
10245       {
10246         aLightCurr->SetSmoothAngle (aSmoothness);
10247       }
10248     }
10249     else if (anArgCase.IsEqual ("INT")
10250           || anArgCase.IsEqual ("INTENSITY")
10251           || anArgCase.IsEqual ("-INT")
10252           || anArgCase.IsEqual ("-INTENSITY"))
10253     {
10254       if (++anArgIt >= theArgsNb
10255        || aLightCurr.IsNull())
10256       {
10257         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10258         return 1;
10259       }
10260
10261       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10262       aLightCurr->SetIntensity (aIntensity);
10263     }
10264     else if (anArgCase.IsEqual ("ANG")
10265           || anArgCase.IsEqual ("ANGLE")
10266           || anArgCase.IsEqual ("-ANG")
10267           || anArgCase.IsEqual ("-ANGLE"))
10268     {
10269       if (++anArgIt >= theArgsNb
10270        || aLightCurr.IsNull()
10271        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10272       {
10273         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10274         return 1;
10275       }
10276
10277       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10278       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
10279     }
10280     else if (anArgCase.IsEqual ("CONSTATTEN")
10281           || anArgCase.IsEqual ("CONSTATTENUATION")
10282           || anArgCase.IsEqual ("-CONSTATTEN")
10283           || anArgCase.IsEqual ("-CONSTATTENUATION"))
10284     {
10285       if (++anArgIt >= theArgsNb
10286        || aLightCurr.IsNull()
10287        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10288         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10289       {
10290         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10291         return 1;
10292       }
10293
10294       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10295       anAtten[0] = Atof (theArgVec[anArgIt]);
10296       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10297     }
10298     else if (anArgCase.IsEqual ("LINATTEN")
10299           || anArgCase.IsEqual ("LINEARATTEN")
10300           || anArgCase.IsEqual ("LINEARATTENUATION")
10301           || anArgCase.IsEqual ("-LINATTEN")
10302           || anArgCase.IsEqual ("-LINEARATTEN")
10303           || anArgCase.IsEqual ("-LINEARATTENUATION"))
10304     {
10305       if (++anArgIt >= theArgsNb
10306        || aLightCurr.IsNull()
10307        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10308         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10309       {
10310         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10311         return 1;
10312       }
10313
10314       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10315       anAtten[1] = Atof (theArgVec[anArgIt]);
10316       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10317     }
10318     else if (anArgCase.IsEqual ("EXP")
10319           || anArgCase.IsEqual ("EXPONENT")
10320           || anArgCase.IsEqual ("SPOTEXP")
10321           || anArgCase.IsEqual ("SPOTEXPONENT")
10322           || anArgCase.IsEqual ("-EXP")
10323           || anArgCase.IsEqual ("-EXPONENT")
10324           || anArgCase.IsEqual ("-SPOTEXP")
10325           || anArgCase.IsEqual ("-SPOTEXPONENT"))
10326     {
10327       if (++anArgIt >= theArgsNb
10328        || aLightCurr.IsNull()
10329        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10330       {
10331         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10332         return 1;
10333       }
10334
10335       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
10336     }
10337     else if (anArgCase.IsEqual ("HEAD")
10338           || anArgCase.IsEqual ("HEADLIGHT")
10339           || anArgCase.IsEqual ("-HEAD")
10340           || anArgCase.IsEqual ("-HEADLIGHT"))
10341     {
10342       if (aLightCurr.IsNull()
10343        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
10344       {
10345         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10346         return 1;
10347       }
10348
10349       Standard_Boolean isHeadLight = Standard_True;
10350       if (anArgIt + 1 < theArgsNb
10351        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
10352       {
10353         ++anArgIt;
10354       }
10355       aLightCurr->SetHeadlight (isHeadLight);
10356     }
10357     else
10358     {
10359       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
10360     }
10361   }
10362
10363   addLight (aLightNew, aLayer, isGlobal);
10364   return 0;
10365 }
10366
10367 //! Read Graphic3d_RenderingParams::PerfCounters flag.
10368 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10369                                             Standard_Boolean& theToReset,
10370                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10371                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10372 {
10373   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10374   TCollection_AsciiString aVal = theValue;
10375   Standard_Boolean toReverse = Standard_False;
10376   if (aVal == "none")
10377   {
10378     theToReset = Standard_True;
10379     return Standard_True;
10380   }
10381   else if (aVal.StartsWith ("-"))
10382   {
10383     toReverse = Standard_True;
10384     aVal = aVal.SubString (2, aVal.Length());
10385   }
10386   else if (aVal.StartsWith ("no"))
10387   {
10388     toReverse = Standard_True;
10389     aVal = aVal.SubString (3, aVal.Length());
10390   }
10391   else if (aVal.StartsWith ("+"))
10392   {
10393     aVal = aVal.SubString (2, aVal.Length());
10394   }
10395   else
10396   {
10397     theToReset = Standard_True;
10398   }
10399
10400   if (     aVal == "fps"
10401         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
10402   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
10403   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
10404   else if (aVal == "structs"
10405         || aVal == "structures"
10406         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
10407   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
10408   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
10409   else if (aVal == "tris"
10410         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
10411   else if (aVal == "pnts"
10412         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
10413   else if (aVal == "mem"
10414         || aVal == "gpumem"
10415         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
10416   else if (aVal == "skipimmediate"
10417         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
10418   else if (aVal == "frametime"
10419         || aVal == "frametimers"
10420         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
10421   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
10422   else if (aVal == "extended"
10423         || aVal == "verbose"
10424         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
10425   else if (aVal == "full"
10426         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
10427   else
10428   {
10429     return Standard_False;
10430   }
10431
10432   if (toReverse)
10433   {
10434     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
10435   }
10436   else
10437   {
10438     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
10439   }
10440   return Standard_True;
10441 }
10442
10443 //! Read Graphic3d_RenderingParams::PerfCounters flags.
10444 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
10445                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
10446 {
10447   TCollection_AsciiString aValue = theValue;
10448   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
10449   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
10450   Standard_Boolean toReset = Standard_False;
10451   for (;;)
10452   {
10453     Standard_Integer aSplitPos = aValue.Search ("|");
10454     if (aSplitPos <= 0)
10455     {
10456       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
10457       {
10458         return Standard_False;
10459       }
10460       if (toReset)
10461       {
10462         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
10463       }
10464       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
10465       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
10466       return Standard_True;
10467     }
10468
10469     if (aSplitPos > 1)
10470     {
10471       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
10472       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
10473       {
10474         return Standard_False;
10475       }
10476     }
10477     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
10478   }
10479 }
10480
10481 //=======================================================================
10482 //function : VRenderParams
10483 //purpose  : Enables/disables rendering features
10484 //=======================================================================
10485
10486 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
10487                                        Standard_Integer  theArgNb,
10488                                        const char**      theArgVec)
10489 {
10490   Handle(V3d_View) aView = ViewerTest::CurrentView();
10491   if (aView.IsNull())
10492   {
10493     std::cerr << "Error: no active viewer!\n";
10494     return 1;
10495   }
10496
10497   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
10498   TCollection_AsciiString aCmdName (theArgVec[0]);
10499   aCmdName.LowerCase();
10500   if (aCmdName == "vraytrace")
10501   {
10502     if (theArgNb == 1)
10503     {
10504       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
10505       return 0;
10506     }
10507     else if (theArgNb == 2)
10508     {
10509       TCollection_AsciiString aValue (theArgVec[1]);
10510       aValue.LowerCase();
10511       if (aValue == "on"
10512        || aValue == "1")
10513       {
10514         aParams.Method = Graphic3d_RM_RAYTRACING;
10515         aView->Redraw();
10516         return 0;
10517       }
10518       else if (aValue == "off"
10519             || aValue == "0")
10520       {
10521         aParams.Method = Graphic3d_RM_RASTERIZATION;
10522         aView->Redraw();
10523         return 0;
10524       }
10525       else
10526       {
10527         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
10528         return 1;
10529       }
10530     }
10531     else
10532     {
10533       std::cout << "Error: wrong number of arguments\n";
10534       return 1;
10535     }
10536   }
10537
10538   if (theArgNb < 2)
10539   {
10540     theDI << "renderMode:  ";
10541     switch (aParams.Method)
10542     {
10543       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10544       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
10545     }
10546     theDI << "\n";
10547     theDI << "transparency:  ";
10548     switch (aParams.TransparencyMethod)
10549     {
10550       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
10551       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
10552                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
10553     }
10554     theDI << "\n";
10555     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
10556     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
10557     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
10558     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
10559     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
10560     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
10561     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
10562     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
10563     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
10564     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
10565     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
10566     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
10567     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
10568     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
10569     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
10570     theDI << "shadingModel: ";
10571     switch (aView->ShadingModel())
10572     {
10573       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
10574       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
10575       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
10576       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
10577       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
10578     }
10579     {
10580       theDI << "perfCounters:";
10581       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
10582       {
10583         theDI << " fps";
10584       }
10585       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
10586       {
10587         theDI << " cpu";
10588       }
10589       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
10590       {
10591         theDI << " structs";
10592       }
10593       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
10594       {
10595         theDI << " groups";
10596       }
10597       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
10598       {
10599         theDI << " arrays";
10600       }
10601       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
10602       {
10603         theDI << " tris";
10604       }
10605       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
10606       {
10607         theDI << " pnts";
10608       }
10609       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
10610       {
10611         theDI << " gpumem";
10612       }
10613       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
10614       {
10615         theDI << " frameTime";
10616       }
10617       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
10618       {
10619         theDI << " skipimmediate";
10620       }
10621       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
10622       {
10623         theDI << " none";
10624       }
10625       theDI << "\n";
10626     }
10627     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
10628     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
10629     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
10630                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
10631                                                                                                                     "noUpdate") << "\n";
10632     theDI << "\n";
10633     return 0;
10634   }
10635
10636   Standard_Boolean toPrint = Standard_False;
10637   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10638   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10639   {
10640     Standard_CString        anArg (theArgVec[anArgIter]);
10641     TCollection_AsciiString aFlag (anArg);
10642     aFlag.LowerCase();
10643     if (anUpdateTool.parseRedrawMode (aFlag))
10644     {
10645       continue;
10646     }
10647     else if (aFlag == "-echo"
10648           || aFlag == "-print")
10649     {
10650       toPrint = Standard_True;
10651       anUpdateTool.Invalidate();
10652     }
10653     else if (aFlag == "-mode"
10654           || aFlag == "-rendermode"
10655           || aFlag == "-render_mode")
10656     {
10657       if (toPrint)
10658       {
10659         switch (aParams.Method)
10660         {
10661           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10662           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
10663         }
10664         continue;
10665       }
10666       else
10667       {
10668         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10669         return 1;
10670       }
10671     }
10672     else if (aFlag == "-ray"
10673           || aFlag == "-raytrace")
10674     {
10675       if (toPrint)
10676       {
10677         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
10678         continue;
10679       }
10680
10681       aParams.Method = Graphic3d_RM_RAYTRACING;
10682     }
10683     else if (aFlag == "-rast"
10684           || aFlag == "-raster"
10685           || aFlag == "-rasterization")
10686     {
10687       if (toPrint)
10688       {
10689         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
10690         continue;
10691       }
10692
10693       aParams.Method = Graphic3d_RM_RASTERIZATION;
10694     }
10695     else if (aFlag == "-msaa")
10696     {
10697       if (toPrint)
10698       {
10699         theDI << aParams.NbMsaaSamples << " ";
10700         continue;
10701       }
10702       else if (++anArgIter >= theArgNb)
10703       {
10704         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10705         return 1;
10706       }
10707
10708       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
10709       if (aNbSamples < 0)
10710       {
10711         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
10712         return 1;
10713       }
10714       else
10715       {
10716         aParams.NbMsaaSamples = aNbSamples;
10717       }
10718     }
10719     else if (aFlag == "-linefeather"
10720           || aFlag == "-edgefeather"
10721           || aFlag == "-feather")
10722     {
10723       if (toPrint)
10724       {
10725         theDI << " " << aParams.LineFeather << " ";
10726         continue;
10727       }
10728       else if (++anArgIter >= theArgNb)
10729       {
10730         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10731         return 1;
10732       }
10733
10734       TCollection_AsciiString aParam = theArgVec[anArgIter];
10735       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10736       if (aFeather <= 0.0f)
10737       {
10738         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
10739         return 1;
10740       }
10741       aParams.LineFeather = aFeather;
10742     }
10743     else if (aFlag == "-oit")
10744     {
10745       if (toPrint)
10746       {
10747         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
10748         {
10749           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
10750         }
10751         else
10752         {
10753           theDI << "off" << " ";
10754         }
10755         continue;
10756       }
10757       else if (++anArgIter >= theArgNb)
10758       {
10759         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10760         return 1;
10761       }
10762
10763       TCollection_AsciiString aParam = theArgVec[anArgIter];
10764       aParam.LowerCase();
10765       if (aParam.IsRealValue())
10766       {
10767         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10768         if (aWeight < 0.f || aWeight > 1.f)
10769         {
10770           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
10771           return 1;
10772         }
10773
10774         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
10775         aParams.OitDepthFactor     = aWeight;
10776       }
10777       else if (aParam == "off")
10778       {
10779         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
10780       }
10781       else
10782       {
10783         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10784         return 1;
10785       }
10786     }
10787     else if (aFlag == "-depthprepass")
10788     {
10789       if (toPrint)
10790       {
10791         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
10792         continue;
10793       }
10794       aParams.ToEnableDepthPrepass = Standard_True;
10795       if (anArgIter + 1 < theArgNb
10796        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
10797       {
10798         ++anArgIter;
10799       }
10800     }
10801     else if (aFlag == "-samplealphatocoverage"
10802           || aFlag == "-alphatocoverage")
10803     {
10804       if (toPrint)
10805       {
10806         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
10807         continue;
10808       }
10809       aParams.ToEnableAlphaToCoverage = Standard_True;
10810       if (anArgIter + 1 < theArgNb
10811        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
10812       {
10813         ++anArgIter;
10814       }
10815     }
10816     else if (aFlag == "-rendscale"
10817           || aFlag == "-renderscale"
10818           || aFlag == "-renderresolutionscale")
10819     {
10820       if (toPrint)
10821       {
10822         theDI << aParams.RenderResolutionScale << " ";
10823         continue;
10824       }
10825       else if (++anArgIter >= theArgNb)
10826       {
10827         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10828         return 1;
10829       }
10830
10831       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
10832       if (aScale < 0.01)
10833       {
10834         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
10835         return 1;
10836       }
10837       else
10838       {
10839         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
10840       }
10841     }
10842     else if (aFlag == "-raydepth"
10843           || aFlag == "-ray_depth")
10844     {
10845       if (toPrint)
10846       {
10847         theDI << aParams.RaytracingDepth << " ";
10848         continue;
10849       }
10850       else if (++anArgIter >= theArgNb)
10851       {
10852         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10853         return 1;
10854       }
10855
10856       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
10857
10858       // We allow RaytracingDepth be more than 10 in case of GI enabled
10859       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
10860       {
10861         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
10862         return 1;
10863       }
10864       else
10865       {
10866         aParams.RaytracingDepth = aDepth;
10867       }
10868     }
10869     else if (aFlag == "-shad"
10870           || aFlag == "-shadows")
10871     {
10872       if (toPrint)
10873       {
10874         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
10875         continue;
10876       }
10877
10878       Standard_Boolean toEnable = Standard_True;
10879       if (++anArgIter < theArgNb
10880       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10881       {
10882         --anArgIter;
10883       }
10884       aParams.IsShadowEnabled = toEnable;
10885     }
10886     else if (aFlag == "-refl"
10887           || aFlag == "-reflections")
10888     {
10889       if (toPrint)
10890       {
10891         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10892         continue;
10893       }
10894
10895       Standard_Boolean toEnable = Standard_True;
10896       if (++anArgIter < theArgNb
10897       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10898       {
10899         --anArgIter;
10900       }
10901       aParams.IsReflectionEnabled = toEnable;
10902     }
10903     else if (aFlag == "-fsaa")
10904     {
10905       if (toPrint)
10906       {
10907         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10908         continue;
10909       }
10910
10911       Standard_Boolean toEnable = Standard_True;
10912       if (++anArgIter < theArgNb
10913       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10914       {
10915         --anArgIter;
10916       }
10917       aParams.IsAntialiasingEnabled = toEnable;
10918     }
10919     else if (aFlag == "-gleam")
10920     {
10921       if (toPrint)
10922       {
10923         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10924         continue;
10925       }
10926
10927       Standard_Boolean toEnable = Standard_True;
10928       if (++anArgIter < theArgNb
10929       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10930       {
10931         --anArgIter;
10932       }
10933       aParams.IsTransparentShadowEnabled = toEnable;
10934     }
10935     else if (aFlag == "-gi")
10936     {
10937       if (toPrint)
10938       {
10939         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10940         continue;
10941       }
10942
10943       Standard_Boolean toEnable = Standard_True;
10944       if (++anArgIter < theArgNb
10945       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10946       {
10947         --anArgIter;
10948       }
10949       aParams.IsGlobalIlluminationEnabled = toEnable;
10950       if (!toEnable)
10951       {
10952         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10953       }
10954     }
10955     else if (aFlag == "-blockedrng"
10956           || aFlag == "-brng")
10957     {
10958       if (toPrint)
10959       {
10960         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10961         continue;
10962       }
10963
10964       Standard_Boolean toEnable = Standard_True;
10965       if (++anArgIter < theArgNb
10966         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10967       {
10968         --anArgIter;
10969       }
10970       aParams.CoherentPathTracingMode = toEnable;
10971     }
10972     else if (aFlag == "-maxrad")
10973     {
10974       if (toPrint)
10975       {
10976         theDI << aParams.RadianceClampingValue << " ";
10977         continue;
10978       }
10979       else if (++anArgIter >= theArgNb)
10980       {
10981         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10982         return 1;
10983       }
10984
10985       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10986       if (!aMaxRadStr.IsRealValue())
10987       {
10988         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10989         return 1;
10990       }
10991
10992       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10993       if (aMaxRadiance <= 0.0)
10994       {
10995         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10996         return 1;
10997       }
10998       else
10999       {
11000         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11001       }
11002     }
11003     else if (aFlag == "-iss")
11004     {
11005       if (toPrint)
11006       {
11007         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11008         continue;
11009       }
11010
11011       Standard_Boolean toEnable = Standard_True;
11012       if (++anArgIter < theArgNb
11013         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11014       {
11015         --anArgIter;
11016       }
11017       aParams.AdaptiveScreenSampling = toEnable;
11018     }
11019     else if (aFlag == "-issatomic")
11020     {
11021       if (toPrint)
11022       {
11023         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11024         continue;
11025       }
11026
11027       Standard_Boolean toEnable = Standard_True;
11028       if (++anArgIter < theArgNb
11029       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11030       {
11031         --anArgIter;
11032       }
11033       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11034     }
11035     else if (aFlag == "-issd")
11036     {
11037       if (toPrint)
11038       {
11039         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11040         continue;
11041       }
11042
11043       Standard_Boolean toEnable = Standard_True;
11044       if (++anArgIter < theArgNb
11045         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11046       {
11047         --anArgIter;
11048       }
11049       aParams.ShowSamplingTiles = toEnable;
11050     }
11051     else if (aFlag == "-tilesize")
11052     {
11053       if (toPrint)
11054       {
11055         theDI << aParams.RayTracingTileSize << " ";
11056         continue;
11057       }
11058       else if (++anArgIter >= theArgNb)
11059       {
11060         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11061         return 1;
11062       }
11063
11064       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11065       if (aTileSize < 1)
11066       {
11067         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11068         return 1;
11069       }
11070       aParams.RayTracingTileSize = aTileSize;
11071     }
11072     else if (aFlag == "-nbtiles")
11073     {
11074       if (toPrint)
11075       {
11076         theDI << aParams.NbRayTracingTiles << " ";
11077         continue;
11078       }
11079       else if (++anArgIter >= theArgNb)
11080       {
11081         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11082         return 1;
11083       }
11084
11085       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11086       if (aNbTiles < -1)
11087       {
11088         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11089         return 1;
11090       }
11091       else if (aNbTiles > 0
11092             && (aNbTiles < 64
11093              || aNbTiles > 1024))
11094       {
11095         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
11096       }
11097       aParams.NbRayTracingTiles = aNbTiles;
11098     }
11099     else if (aFlag == "-env")
11100     {
11101       if (toPrint)
11102       {
11103         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11104         continue;
11105       }
11106
11107       Standard_Boolean toEnable = Standard_True;
11108       if (++anArgIter < theArgNb
11109         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11110       {
11111         --anArgIter;
11112       }
11113       aParams.UseEnvironmentMapBackground = toEnable;
11114     }
11115     else if (aFlag == "-twoside")
11116     {
11117       if (toPrint)
11118       {
11119         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
11120         continue;
11121       }
11122
11123       Standard_Boolean toEnable = Standard_True;
11124       if (++anArgIter < theArgNb
11125         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11126       {
11127         --anArgIter;
11128       }
11129       aParams.TwoSidedBsdfModels = toEnable;
11130     }
11131     else if (aFlag == "-shademodel"
11132           || aFlag == "-shadingmodel"
11133           || aFlag == "-shading")
11134     {
11135       if (toPrint)
11136       {
11137         switch (aView->ShadingModel())
11138         {
11139           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
11140           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
11141           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
11142           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
11143           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
11144         }
11145         continue;
11146       }
11147
11148       if (++anArgIter >= theArgNb)
11149       {
11150         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11151       }
11152
11153       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
11154       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
11155        && aModel != Graphic3d_TOSM_DEFAULT)
11156       {
11157         aView->SetShadingModel (aModel);
11158       }
11159       else
11160       {
11161         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
11162         return 1;
11163       }
11164     }
11165     else if (aFlag == "-resolution")
11166     {
11167       if (++anArgIter >= theArgNb)
11168       {
11169         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11170         return 1;
11171       }
11172
11173       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
11174       if (aResolution.IsIntegerValue())
11175       {
11176         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
11177       }
11178       else
11179       {
11180         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11181         return 1;
11182       }
11183     }
11184     else if (aFlag == "-rebuildglsl"
11185           || aFlag == "-rebuild")
11186     {
11187       if (toPrint)
11188       {
11189         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
11190         continue;
11191       }
11192
11193       Standard_Boolean toEnable = Standard_True;
11194       if (++anArgIter < theArgNb
11195           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11196       {
11197         --anArgIter;
11198       }
11199       aParams.RebuildRayTracingShaders = toEnable;
11200     }
11201     else if (aFlag == "-focal")
11202     {
11203       if (++anArgIter >= theArgNb)
11204       {
11205         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11206         return 1;
11207       }
11208
11209       TCollection_AsciiString aParam (theArgVec[anArgIter]);
11210       if (aParam.IsRealValue())
11211       {
11212         float aFocalDist = static_cast<float> (aParam.RealValue());
11213         if (aFocalDist < 0)
11214         {
11215           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11216           return 1;
11217         }
11218         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
11219       }
11220       else
11221       {
11222         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11223         return 1;
11224       }
11225     }
11226     else if (aFlag == "-aperture")
11227     {
11228       if (++anArgIter >= theArgNb)
11229       {
11230         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11231         return 1;
11232       }
11233
11234       TCollection_AsciiString aParam(theArgVec[anArgIter]);
11235       if (aParam.IsRealValue())
11236       {
11237         float aApertureSize = static_cast<float> (aParam.RealValue());
11238         if (aApertureSize < 0)
11239         {
11240           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11241           return 1;
11242         }
11243         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
11244       }
11245       else
11246       {
11247         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11248         return 1;
11249       }
11250     }
11251     else if (aFlag == "-exposure")
11252     {
11253       if (++anArgIter >= theArgNb)
11254       {
11255         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11256         return 1;
11257       }
11258
11259       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
11260       if (anExposure.IsRealValue())
11261       {
11262         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
11263       }
11264       else
11265       {
11266         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11267         return 1;
11268       }
11269     }
11270     else if (aFlag == "-whitepoint")
11271     {
11272       if (++anArgIter >= theArgNb)
11273       {
11274         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11275         return 1;
11276       }
11277
11278       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
11279       if (aWhitePoint.IsRealValue())
11280       {
11281         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
11282       }
11283       else
11284       {
11285         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11286         return 1;
11287       }
11288     }
11289     else if (aFlag == "-tonemapping")
11290     {
11291       if (++anArgIter >= theArgNb)
11292       {
11293         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11294         return 1;
11295       }
11296
11297       TCollection_AsciiString aMode (theArgVec[anArgIter]);
11298       aMode.LowerCase();
11299
11300       if (aMode == "disabled")
11301       {
11302         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
11303       }
11304       else if (aMode == "filmic")
11305       {
11306         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
11307       }
11308       else
11309       {
11310         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11311         return 1;
11312       }
11313     }
11314     else if (aFlag == "-performancestats"
11315           || aFlag == "-performancecounters"
11316           || aFlag == "-perfstats"
11317           || aFlag == "-perfcounters"
11318           || aFlag == "-stats")
11319     {
11320       if (++anArgIter >= theArgNb)
11321       {
11322         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11323         return 1;
11324       }
11325
11326       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
11327       aFlagsStr.LowerCase();
11328       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
11329       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
11330       {
11331         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11332         return 1;
11333       }
11334       aView->ChangeRenderingParams().CollectedStats = aFlags;
11335       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
11336     }
11337     else if (aFlag == "-perfupdateinterval"
11338           || aFlag == "-statsupdateinterval")
11339     {
11340       if (++anArgIter >= theArgNb)
11341       {
11342         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11343         return 1;
11344       }
11345       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11346     }
11347     else if (aFlag == "-perfchart"
11348           || aFlag == "-statschart")
11349     {
11350       if (++anArgIter >= theArgNb)
11351       {
11352         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11353         return 1;
11354       }
11355       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
11356     }
11357     else if (aFlag == "-perfchartmax"
11358           || aFlag == "-statschartmax")
11359     {
11360       if (++anArgIter >= theArgNb)
11361       {
11362         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11363         return 1;
11364       }
11365       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11366     }
11367     else if (aFlag == "-frustumculling"
11368           || aFlag == "-culling")
11369     {
11370       if (toPrint)
11371       {
11372         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
11373                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
11374                                                                                                    "noUpdate") << " ";
11375         continue;
11376       }
11377
11378       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
11379       if (++anArgIter < theArgNb)
11380       {
11381         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
11382         aStateStr.LowerCase();
11383         bool toEnable = true;
11384         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
11385         {
11386           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
11387         }
11388         else if (aStateStr == "noupdate"
11389               || aStateStr == "freeze")
11390         {
11391           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
11392         }
11393         else
11394         {
11395           --anArgIter;
11396         }
11397       }
11398       aParams.FrustumCullingState = aState;
11399     }
11400     else
11401     {
11402       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
11403       return 1;
11404     }
11405   }
11406
11407   return 0;
11408 }
11409
11410 //=======================================================================
11411 //function : searchInfo
11412 //purpose  :
11413 //=======================================================================
11414 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
11415                                            const TCollection_AsciiString&              theKey)
11416 {
11417   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
11418   {
11419     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
11420     {
11421       return anIter.Value();
11422     }
11423   }
11424   return TCollection_AsciiString();
11425 }
11426
11427 //=======================================================================
11428 //function : VStatProfiler
11429 //purpose  :
11430 //=======================================================================
11431 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
11432                                        Standard_Integer  theArgNb,
11433                                        const char**      theArgVec)
11434 {
11435   Handle(V3d_View) aView = ViewerTest::CurrentView();
11436   if (aView.IsNull())
11437   {
11438     std::cerr << "Error: no active viewer!\n";
11439     return 1;
11440   }
11441
11442   Standard_Boolean toRedraw = Standard_True;
11443   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
11444   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
11445   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
11446   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11447   {
11448     Standard_CString        anArg (theArgVec[anArgIter]);
11449     TCollection_AsciiString aFlag (anArg);
11450     aFlag.LowerCase();
11451     if (aFlag == "-noredraw")
11452     {
11453       toRedraw = Standard_False;
11454     }
11455     else
11456     {
11457       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
11458       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11459       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
11460       else if (aFlag == "alllayers"
11461             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
11462       else if (aFlag == "allstructs"
11463             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
11464       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
11465       else if (aFlag == "allarrays"
11466             || aFlag == "fillarrays"
11467             || aFlag == "linearrays"
11468             || aFlag == "pointarrays"
11469             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11470       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
11471       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
11472       else if (aFlag == "geommem"
11473             || aFlag == "texturemem"
11474             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11475       else if (aFlag == "elapsedframe"
11476             || aFlag == "cpuframeaverage"
11477             || aFlag == "cpupickingaverage"
11478             || aFlag == "cpucullingaverage"
11479             || aFlag == "cpudynaverage"
11480             || aFlag == "cpuframemax"
11481             || aFlag == "cpupickingmax"
11482             || aFlag == "cpucullingmax"
11483             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11484       else
11485       {
11486         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
11487         continue;
11488       }
11489
11490       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
11491     }
11492   }
11493
11494   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
11495   {
11496     aView->ChangeRenderingParams().CollectedStats =
11497       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
11498
11499     if (toRedraw)
11500     {
11501       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
11502       aView->Redraw();
11503       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
11504     }
11505
11506     TColStd_IndexedDataMapOfStringString aDict;
11507     aView->StatisticInformation (aDict);
11508
11509     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
11510
11511     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11512     {
11513       Standard_CString        anArg(theArgVec[anArgIter]);
11514       TCollection_AsciiString aFlag(anArg);
11515       aFlag.LowerCase();
11516       if (aFlag == "fps")
11517       {
11518         theDI << searchInfo (aDict, "FPS") << " ";
11519       }
11520       else if (aFlag == "cpu")
11521       {
11522         theDI << searchInfo (aDict, "CPU FPS") << " ";
11523       }
11524       else if (aFlag == "alllayers")
11525       {
11526         theDI << searchInfo (aDict, "Layers") << " ";
11527       }
11528       else if (aFlag == "layers")
11529       {
11530         theDI << searchInfo (aDict, "Rendered layers") << " ";
11531       }
11532       else if (aFlag == "allstructs")
11533       {
11534         theDI << searchInfo (aDict, "Structs") << " ";
11535       }
11536       else if (aFlag == "structs")
11537       {
11538         theDI << searchInfo (aDict, "Rendered structs") << " ";
11539       }
11540       else if (aFlag == "groups")
11541       {
11542         theDI << searchInfo (aDict, "Rendered groups") << " ";
11543       }
11544       else if (aFlag == "allarrays")
11545       {
11546         theDI << searchInfo (aDict, "Rendered arrays") << " ";
11547       }
11548       else if (aFlag == "fillarrays")
11549       {
11550         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
11551       }
11552       else if (aFlag == "linearrays")
11553       {
11554         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
11555       }
11556       else if (aFlag == "pointarrays")
11557       {
11558         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
11559       }
11560       else if (aFlag == "textarrays")
11561       {
11562         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
11563       }
11564       else if (aFlag == "triangles")
11565       {
11566         theDI << searchInfo (aDict, "Rendered triangles") << " ";
11567       }
11568       else if (aFlag == "points")
11569       {
11570         theDI << searchInfo (aDict, "Rendered points") << " ";
11571       }
11572       else if (aFlag == "geommem")
11573       {
11574         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
11575       }
11576       else if (aFlag == "texturemem")
11577       {
11578         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
11579       }
11580       else if (aFlag == "framemem")
11581       {
11582         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
11583       }
11584       else if (aFlag == "elapsedframe")
11585       {
11586         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
11587       }
11588       else if (aFlag == "cpuframe_average")
11589       {
11590         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
11591       }
11592       else if (aFlag == "cpupicking_average")
11593       {
11594         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
11595       }
11596       else if (aFlag == "cpuculling_average")
11597       {
11598         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
11599       }
11600       else if (aFlag == "cpudyn_average")
11601       {
11602         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
11603       }
11604       else if (aFlag == "cpuframe_max")
11605       {
11606         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
11607       }
11608       else if (aFlag == "cpupicking_max")
11609       {
11610         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
11611       }
11612       else if (aFlag == "cpuculling_max")
11613       {
11614         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
11615       }
11616       else if (aFlag == "cpudyn_max")
11617       {
11618         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
11619       }
11620     }
11621   }
11622   else
11623   {
11624     if (toRedraw)
11625     {
11626       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
11627       aView->Redraw();
11628       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
11629     }
11630     theDI << "Statistic info:\n" << aView->StatisticInformation();
11631   }
11632   return 0;
11633 }
11634
11635 //=======================================================================
11636 //function : VProgressiveMode
11637 //purpose  :
11638 //=======================================================================
11639 #if defined(_WIN32)
11640 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
11641                                           Standard_Integer  /*theNbArgs*/,
11642                                           const char**      /*theArgs*/)
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   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
11652
11653   for (;;)
11654   {
11655     aView->Redraw();
11656
11657     Standard_Boolean toExit = Standard_False;
11658
11659     MSG aMsg;
11660     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
11661     {
11662       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
11663       {
11664         toExit = Standard_True;
11665       }
11666
11667       TranslateMessage (&aMsg);
11668       DispatchMessageW (&aMsg);
11669     }
11670
11671     if (toExit)
11672     {
11673       break;
11674     }
11675   }
11676
11677   return 0;
11678 }
11679 #endif
11680
11681 //=======================================================================
11682 //function : VXRotate
11683 //purpose  :
11684 //=======================================================================
11685 static Standard_Integer VXRotate (Draw_Interpretor& di,
11686                                    Standard_Integer argc,
11687                                    const char ** argv)
11688 {
11689   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
11690   if (aContext.IsNull())
11691   {
11692     di << argv[0] << "ERROR : use 'vinit' command before \n";
11693     return 1;
11694   }
11695   
11696   if (argc != 3)
11697   {
11698     di << "ERROR : Usage : " << argv[0] << " name angle\n";
11699     return 1;
11700   }
11701
11702   TCollection_AsciiString aName (argv[1]);
11703   Standard_Real anAngle = Draw::Atof (argv[2]);
11704
11705   // find object
11706   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
11707   Handle(AIS_InteractiveObject) anIObj;
11708   if (!aMap.Find2 (aName, anIObj))
11709   {
11710     di << "Use 'vdisplay' before\n";
11711     return 1;
11712   }
11713
11714   gp_Trsf aTransform;
11715   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
11716   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
11717
11718   aContext->SetLocation (anIObj, aTransform);
11719   aContext->UpdateCurrentViewer();
11720   return 0;
11721 }
11722
11723 //===============================================================================================
11724 //class   : ViewerTest_AISManipulator
11725 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
11726 //===============================================================================================
11727 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11728
11729 class ViewerTest_AISManipulator : public AIS_Manipulator
11730 {
11731 public:
11732
11733   ViewerTest_AISManipulator() : AIS_Manipulator()
11734   {
11735     GetMapOfAISManipulators().Add (this);
11736   }
11737
11738   virtual ~ViewerTest_AISManipulator()
11739   {
11740     GetMapOfAISManipulators().Remove (this);
11741   }
11742
11743   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11744 };
11745
11746 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11747 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11748
11749 //===============================================================================================
11750 //function : VManipulator
11751 //purpose  :
11752 //===============================================================================================
11753 static int VManipulator (Draw_Interpretor& theDi,
11754                          Standard_Integer  theArgsNb,
11755                          const char**      theArgVec)
11756 {
11757   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
11758   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
11759   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
11760   if (aView.IsNull()
11761    || aViewer.IsNull())
11762   {
11763     std::cerr << "No active viewer!\n";
11764     return 1;
11765   }
11766
11767   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
11768   Standard_Integer anArgIter = 1;
11769   for (; anArgIter < theArgsNb; ++anArgIter)
11770   {
11771     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
11772   }
11773
11774   ViewerTest_CmdParser aCmd;
11775   aCmd.AddDescription ("Manages manipulator for interactive objects:");
11776   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
11777   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
11778   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
11779   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
11780   aCmd.AddOption ("detach",         "...       - detach manipulator");
11781
11782   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
11783   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
11784   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
11785
11786   aCmd.AddOption ("move",   "... x y z - move object");
11787   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
11788   aCmd.AddOption ("scale",  "... factor - scale object");
11789
11790   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
11791   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
11792   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
11793   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
11794   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
11795   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
11796   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
11797   aCmd.AddOption ("size",              "... size - set size of manipulator");
11798   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
11799
11800   aCmd.Parse (theArgsNb, theArgVec);
11801
11802   if (aCmd.HasOption ("help"))
11803   {
11804     theDi.PrintHelp (theArgVec[0]);
11805     return 0;
11806   }
11807
11808   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
11809
11810   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
11811
11812   if (aName.IsEmpty())
11813   {
11814     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
11815     return 1;
11816   }
11817
11818   // ----------------------------------
11819   // detach existing manipulator object
11820   // ----------------------------------
11821
11822   if (aCmd.HasOption ("detach"))
11823   {
11824     if (!aMapAIS.IsBound2 (aName))
11825     {
11826       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
11827       return 1;
11828     }
11829
11830     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11831     if (aManipulator.IsNull())
11832     {
11833       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11834       return 1;
11835     }
11836
11837     aManipulator->Detach();
11838     aMapAIS.UnBind2 (aName);
11839     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
11840
11841     return 0;
11842   }
11843
11844   // -----------------------------------------------
11845   // find or create manipulator if it does not exist
11846   // -----------------------------------------------
11847
11848   Handle(AIS_Manipulator) aManipulator;
11849   if (!aMapAIS.IsBound2 (aName))
11850   {
11851     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
11852
11853     aManipulator = new ViewerTest_AISManipulator();
11854     aMapAIS.Bind (aManipulator, aName);
11855   }
11856   else
11857   {
11858     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11859     if (aManipulator.IsNull())
11860     {
11861       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11862       return 1;
11863     }
11864   }
11865
11866   // -----------------------------------------
11867   // change properties of manipulator instance
11868   // -----------------------------------------
11869
11870   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
11871   {
11872     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
11873   }
11874   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
11875   {
11876     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
11877   }
11878   if (aCmd.HasOption ("followRotation", 1, Standard_True))
11879   {
11880     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
11881   }
11882   if (aCmd.HasOption("followDragging", 1, Standard_True))
11883   {
11884     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
11885   }
11886   if (aCmd.HasOption ("gap", 1, Standard_True))
11887   {
11888     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
11889   }
11890   if (aCmd.HasOption ("part", 3, Standard_True))
11891   {
11892     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
11893     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
11894     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
11895     if (aMode < 1 || aMode > 4)
11896     {
11897       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
11898       return 1;
11899     }
11900
11901     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
11902   }
11903   if (aCmd.HasOption ("pos", 3, Standard_True))
11904   {
11905     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
11906     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
11907     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
11908
11909     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
11910   }
11911   if (aCmd.HasOption ("size", 1, Standard_True))
11912   {
11913     aManipulator->SetSize (aCmd.ArgFloat ("size"));
11914   }
11915   if (aCmd.HasOption ("zoomable", 1, Standard_True))
11916   {
11917     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
11918
11919     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
11920     {
11921       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
11922       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
11923     }
11924   }
11925
11926   // ---------------------------------------------------
11927   // attach, detach or access manipulator from an object
11928   // ---------------------------------------------------
11929
11930   if (aCmd.HasOption ("attach"))
11931   {
11932     // Find an object and attach manipulator to it
11933     if (!aCmd.HasOption ("attach", 1, Standard_True))
11934     {
11935       return 1;
11936     }
11937
11938     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
11939     Handle(AIS_InteractiveObject) anObject;
11940     if (!aMapAIS.Find2 (anObjName, anObject))
11941     {
11942       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
11943       return 1;
11944     }
11945
11946     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
11947     {
11948       if (anIt.Value()->IsAttached()
11949        && anIt.Value()->Object() == anObject)
11950       {
11951         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
11952         return 1;
11953       }
11954     }
11955
11956     AIS_Manipulator::OptionsForAttach anOptions;
11957     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
11958     {
11959       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
11960     }
11961     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
11962     {
11963       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
11964     }
11965     if (aCmd.HasOption ("enableModes", 1, Standard_True))
11966     {
11967       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
11968     }
11969
11970     aManipulator->Attach (anObject, anOptions);
11971   }
11972
11973   // --------------------------------------
11974   // apply transformation using manipulator
11975   // --------------------------------------
11976
11977   if (aCmd.HasOption ("startTransform", 2, Standard_True))
11978   {
11979     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
11980   }
11981   if (aCmd.HasOption ("transform", 2, Standard_True))
11982   {
11983     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
11984   }
11985   if (aCmd.HasOption ("stopTransform"))
11986   {
11987     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
11988
11989     aManipulator->StopTransform (toApply);
11990   }
11991
11992   gp_Trsf aT;
11993   if (aCmd.HasOption ("move", 3, Standard_True))
11994   {
11995     aT.SetTranslationPart (aCmd.ArgVec ("move"));
11996   }
11997   if (aCmd.HasOption ("rotate", 7, Standard_True))
11998   {
11999     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
12000   }
12001   if (aCmd.HasOption ("scale", 1))
12002   {
12003     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
12004   }
12005
12006   if (aT.Form() != gp_Identity)
12007   {
12008     aManipulator->Transform (aT);
12009   }
12010
12011   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
12012
12013   return 0;
12014 }
12015
12016 //===============================================================================================
12017 //function : VSelectionProperties
12018 //purpose  :
12019 //===============================================================================================
12020 static int VSelectionProperties (Draw_Interpretor& theDi,
12021                                  Standard_Integer  theArgsNb,
12022                                  const char**      theArgVec)
12023 {
12024   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12025   if (aCtx.IsNull())
12026   {
12027     std::cerr << "No active viewer!\n";
12028     return 1;
12029   }
12030
12031   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
12032   {
12033     // handle obsolete alias
12034     bool toEnable = true;
12035     if (theArgsNb < 2)
12036     {
12037       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
12038       return 0;
12039     }
12040     else if (theArgsNb != 2
12041          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
12042     {
12043       std::cout << "Syntax error: wrong number of parameters.";
12044       return 1;
12045     }
12046     if (toEnable != aCtx->ToHilightSelected())
12047     {
12048       aCtx->ClearDetected();
12049       aCtx->SetToHilightSelected (toEnable);
12050     }
12051     return 0;
12052   }
12053
12054   Standard_Boolean toPrint  = theArgsNb == 1;
12055   Standard_Boolean toRedraw = Standard_False;
12056   Standard_Integer anArgIter = 1;
12057   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
12058   if (anArgIter < theArgsNb)
12059   {
12060     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
12061     anArgFirst.LowerCase();
12062     ++anArgIter;
12063     if (anArgFirst == "dynhighlight"
12064      || anArgFirst == "dynhilight"
12065      || anArgFirst == "dynamichighlight"
12066      || anArgFirst == "dynamichilight")
12067     {
12068       aType = Prs3d_TypeOfHighlight_Dynamic;
12069     }
12070     else if (anArgFirst == "localdynhighlight"
12071           || anArgFirst == "localdynhilight"
12072           || anArgFirst == "localdynamichighlight"
12073           || anArgFirst == "localdynamichilight")
12074     {
12075       aType = Prs3d_TypeOfHighlight_LocalDynamic;
12076     }
12077     else if (anArgFirst == "selhighlight"
12078           || anArgFirst == "selhilight"
12079           || anArgFirst == "selectedhighlight"
12080           || anArgFirst == "selectedhilight")
12081     {
12082       aType = Prs3d_TypeOfHighlight_Selected;
12083     }
12084     else if (anArgFirst == "localselhighlight"
12085           || anArgFirst == "localselhilight"
12086           || anArgFirst == "localselectedhighlight"
12087           || anArgFirst == "localselectedhilight")
12088     {
12089       aType = Prs3d_TypeOfHighlight_LocalSelected;
12090     }
12091     else
12092     {
12093       --anArgIter;
12094     }
12095   }
12096   for (; anArgIter < theArgsNb; ++anArgIter)
12097   {
12098     TCollection_AsciiString anArg (theArgVec[anArgIter]);
12099     anArg.LowerCase();
12100     if (anArg == "-help")
12101     {
12102       theDi.PrintHelp (theArgVec[0]);
12103       return 0;
12104     }
12105     else if (anArg == "-print")
12106     {
12107       toPrint = Standard_True;
12108     }
12109     else if (anArg == "-autoactivate")
12110     {
12111       Standard_Boolean toEnable = Standard_True;
12112       if (anArgIter + 1 < theArgsNb
12113        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12114       {
12115         ++anArgIter;
12116       }
12117       aCtx->SetAutoActivateSelection (toEnable);
12118     }
12119     else if (anArg == "-automatichighlight"
12120           || anArg == "-automatichilight"
12121           || anArg == "-autohighlight"
12122           || anArg == "-autohilight")
12123     {
12124       Standard_Boolean toEnable = Standard_True;
12125       if (anArgIter + 1 < theArgsNb
12126        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12127       {
12128         ++anArgIter;
12129       }
12130       aCtx->ClearSelected (false);
12131       aCtx->ClearDetected();
12132       aCtx->SetAutomaticHilight (toEnable);
12133       toRedraw = true;
12134     }
12135     else if (anArg == "-highlightselected"
12136           || anArg == "-hilightselected")
12137     {
12138       Standard_Boolean toEnable = Standard_True;
12139       if (anArgIter + 1 < theArgsNb
12140        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12141       {
12142         ++anArgIter;
12143       }
12144       aCtx->ClearDetected();
12145       aCtx->SetToHilightSelected (toEnable);
12146       toRedraw = true;
12147     }
12148     else if (anArg == "-pickstrategy"
12149           || anArg == "-pickingstrategy")
12150     {
12151       if (++anArgIter >= theArgsNb)
12152       {
12153         std::cout << "Syntax error: type of highlighting is undefined\n";
12154         return 1;
12155       }
12156
12157       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12158       TCollection_AsciiString aVal (theArgVec[anArgIter]);
12159       aVal.LowerCase();
12160       if (aVal == "first"
12161        || aVal == "firstaccepted"
12162        || aVal == "firstacceptable")
12163       {
12164         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12165       }
12166       else if (aVal == "topmost"
12167             || aVal == "onlyTopmost")
12168       {
12169         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
12170       }
12171       else
12172       {
12173         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
12174         return 1;
12175       }
12176
12177       aCtx->SetPickingStrategy (aStrategy);
12178     }
12179     else if (anArg == "-pixtol"
12180           && anArgIter + 1 < theArgsNb)
12181     {
12182       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
12183     }
12184     else if ((anArg == "-mode"
12185            || anArg == "-dispmode")
12186           && anArgIter + 1 < theArgsNb)
12187     {
12188       if (aType == Prs3d_TypeOfHighlight_None)
12189       {
12190         std::cout << "Syntax error: type of highlighting is undefined\n";
12191         return 1;
12192       }
12193
12194       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
12195       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12196       aStyle->SetDisplayMode (aDispMode);
12197       toRedraw = Standard_True;
12198     }
12199     else if (anArg == "-layer"
12200           && anArgIter + 1 < theArgsNb)
12201     {
12202       if (aType == Prs3d_TypeOfHighlight_None)
12203       {
12204         std::cout << "Syntax error: type of highlighting is undefined\n";
12205         return 1;
12206       }
12207
12208       ++anArgIter;
12209       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
12210       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
12211       {
12212         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
12213         return 1;
12214       }
12215
12216       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12217       aStyle->SetZLayer (aNewLayer);
12218       toRedraw = Standard_True;
12219     }
12220     else if (anArg == "-hicolor"
12221           || anArg == "-selcolor"
12222           || anArg == "-color")
12223     {
12224       if (anArg.StartsWith ("-hi"))
12225       {
12226         aType = Prs3d_TypeOfHighlight_Dynamic;
12227       }
12228       else if (anArg.StartsWith ("-sel"))
12229       {
12230         aType = Prs3d_TypeOfHighlight_Selected;
12231       }
12232       else if (aType == Prs3d_TypeOfHighlight_None)
12233       {
12234         std::cout << "Syntax error: type of highlighting is undefined\n";
12235         return 1;
12236       }
12237
12238       Quantity_Color aColor;
12239       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
12240                                                            theArgVec + anArgIter + 1,
12241                                                            aColor);
12242       if (aNbParsed == 0)
12243       {
12244         std::cout << "Syntax error: need more arguments.\n";
12245         return 1;
12246       }
12247       anArgIter += aNbParsed;
12248
12249       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12250       aStyle->SetColor (aColor);
12251       toRedraw = Standard_True;
12252     }
12253     else if ((anArg == "-transp"
12254            || anArg == "-transparency"
12255            || anArg == "-hitransp"
12256            || anArg == "-seltransp"
12257            || anArg == "-hitransplocal"
12258            || anArg == "-seltransplocal")
12259           && anArgIter + 1 < theArgsNb)
12260     {
12261       if (anArg.StartsWith ("-hi"))
12262       {
12263         aType = Prs3d_TypeOfHighlight_Dynamic;
12264       }
12265       else if (anArg.StartsWith ("-sel"))
12266       {
12267         aType = Prs3d_TypeOfHighlight_Selected;
12268       }
12269       else if (aType == Prs3d_TypeOfHighlight_None)
12270       {
12271         std::cout << "Syntax error: type of highlighting is undefined\n";
12272         return 1;
12273       }
12274
12275       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
12276       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12277       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
12278       toRedraw = Standard_True;
12279     }
12280     else if ((anArg == "-mat"
12281            || anArg == "-material")
12282           && anArgIter + 1 < theArgsNb)
12283     {
12284       if (aType == Prs3d_TypeOfHighlight_None)
12285       {
12286         std::cout << "Syntax error: type of highlighting is undefined\n";
12287         return 1;
12288       }
12289
12290       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12291       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
12292       if (aMatName != Graphic3d_NOM_DEFAULT)
12293       {
12294         ++anArgIter;
12295         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
12296         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
12297         Graphic3d_MaterialAspect aMat (aMatName);
12298         aMat.SetColor (aStyle->Color());
12299         aMat.SetTransparency (aStyle->Transparency());
12300         anAspect->SetFrontMaterial (aMat);
12301         anAspect->SetInteriorColor (aStyle->Color());
12302         aStyle->SetBasicFillAreaAspect (anAspect);
12303       }
12304       else
12305       {
12306         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
12307       }
12308       toRedraw = Standard_True;
12309     }
12310     else
12311     {
12312       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
12313     }
12314   }
12315
12316   if (toPrint)
12317   {
12318     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
12319     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
12320     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
12321     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
12322     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
12323     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
12324     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
12325     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
12326     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
12327     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
12328     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
12329     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
12330     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
12331     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
12332   }
12333
12334   if (aCtx->NbSelected() != 0 && toRedraw)
12335   {
12336     aCtx->HilightSelected (Standard_True);
12337   }
12338
12339   return 0;
12340 }
12341
12342 //===============================================================================================
12343 //function : VDumpSelectionImage
12344 //purpose  :
12345 //===============================================================================================
12346 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
12347                                 Standard_Integer  theArgsNb,
12348                                 const char**      theArgVec)
12349 {
12350   if (theArgsNb < 2)
12351   {
12352     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
12353     return 1;
12354   }
12355
12356   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
12357   if (aContext.IsNull())
12358   {
12359     std::cout << "Error: no active view.\n";
12360     return 1;
12361   }
12362
12363   TCollection_AsciiString aFile;
12364   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12365   Image_Format anImgFormat = Image_Format_BGR;
12366   Standard_Integer aPickedIndex = 1;
12367   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
12368   {
12369     TCollection_AsciiString aParam (theArgVec[anArgIter]);
12370     aParam.LowerCase();
12371     if (aParam == "-type")
12372     {
12373       if (++anArgIter >= theArgsNb)
12374       {
12375         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
12376         return 1;
12377       }
12378
12379       TCollection_AsciiString aValue (theArgVec[anArgIter]);
12380       aValue.LowerCase();
12381       if (aValue == "depth"
12382        || aValue == "normdepth"
12383        || aValue == "normalizeddepth")
12384       {
12385         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12386         anImgFormat = Image_Format_GrayF;
12387       }
12388       if (aValue == "depthinverted"
12389        || aValue == "normdepthinverted"
12390        || aValue == "normalizeddepthinverted"
12391        || aValue == "inverted")
12392       {
12393         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
12394         anImgFormat = Image_Format_GrayF;
12395       }
12396       else if (aValue == "unnormdepth"
12397             || aValue == "unnormalizeddepth")
12398       {
12399         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
12400         anImgFormat = Image_Format_GrayF;
12401       }
12402       else if (aValue == "objectcolor"
12403             || aValue == "object"
12404             || aValue == "color")
12405       {
12406         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
12407       }
12408       else if (aValue == "entitycolor"
12409             || aValue == "entity")
12410       {
12411         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
12412       }
12413       else if (aValue == "ownercolor"
12414             || aValue == "owner")
12415       {
12416         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
12417       }
12418       else if (aValue == "selectionmodecolor"
12419             || aValue == "selectionmode"
12420             || aValue == "selmodecolor"
12421             || aValue == "selmode")
12422       {
12423         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
12424       }
12425     }
12426     else if (aParam == "-picked"
12427           || aParam == "-pickeddepth"
12428           || aParam == "-pickedindex")
12429     {
12430       if (++anArgIter >= theArgsNb)
12431       {
12432         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
12433         return 1;
12434       }
12435
12436       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
12437     }
12438     else if (aFile.IsEmpty())
12439     {
12440       aFile = theArgVec[anArgIter];
12441     }
12442     else
12443     {
12444       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
12445       return 1;
12446     }
12447   }
12448   if (aFile.IsEmpty())
12449   {
12450     std::cout << "Syntax error: image file name is missing.\n";
12451     return 1;
12452   }
12453
12454   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
12455   Standard_Integer aWidth = 0, aHeight = 0;
12456   aView->Window()->Size (aWidth, aHeight);
12457
12458   Image_AlienPixMap aPixMap;
12459   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
12460   {
12461     std::cout << "Error: can't allocate image.\n";
12462     return 1;
12463   }
12464   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
12465   {
12466     std::cout << "Error: can't generate selection image.\n";
12467     return 1;
12468   }
12469   if (!aPixMap.Save (aFile))
12470   {
12471     std::cout << "Error: can't save selection image.\n";
12472     return 0;
12473   }
12474   return 0;
12475 }
12476
12477 //=======================================================================
12478 //function : ViewerCommands
12479 //purpose  :
12480 //=======================================================================
12481
12482 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
12483 {
12484
12485   const char *group = "ZeViewer";
12486   theCommands.Add("vinit",
12487           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
12488     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
12489   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
12490     "\n\t\t:     [-display displayName]"
12491   #endif
12492     "\n\t\t: Creates new View window with specified name viewName."
12493     "\n\t\t: By default the new view is created in the viewer and in"
12494     "\n\t\t: graphic driver shared with active view."
12495     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
12496     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
12497     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
12498 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
12499     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
12500     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
12501 #endif
12502     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
12503     "\n\t\t:  -width, -height width and heigth of window respectively."
12504     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
12505     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
12506     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
12507     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
12508     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
12509     __FILE__,VInit,group);
12510   theCommands.Add("vclose" ,
12511     "[view_id [keep_context=0|1]]\n"
12512     "or vclose ALL - to remove all created views\n"
12513     " - removes view(viewer window) defined by its view_id.\n"
12514     " - keep_context: by default 0; if 1 and the last view is deleted"
12515     " the current context is not removed.",
12516     __FILE__,VClose,group);
12517   theCommands.Add("vactivate" ,
12518     "vactivate view_id [-noUpdate]"
12519     " - activates view(viewer window) defined by its view_id",
12520     __FILE__,VActivate,group);
12521   theCommands.Add("vviewlist",
12522     "vviewlist [format={tree, long}]"
12523     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
12524     " - format: format of result output, if tree the output is a tree view;"
12525     "otherwise it's a list of full view names. By default format = tree",
12526     __FILE__,VViewList,group);
12527   theCommands.Add("vhelp" ,
12528     "vhelp            : display help on the viewer commands",
12529     __FILE__,VHelp,group);
12530   theCommands.Add("vtop" ,
12531     "vtop or <T>      : Top view. Orientation +X+Y" ,
12532     __FILE__,VTop,group);
12533   theCommands.Add("vbottom" ,
12534     "vbottom          : Bottom view. Orientation +X-Y" ,
12535     __FILE__,VBottom,group);
12536   theCommands.Add("vleft" ,
12537     "vleft            : Left view. Orientation -Y+Z" ,
12538     __FILE__,VLeft,group);
12539   theCommands.Add("vright" ,
12540     "vright           : Right view. Orientation +Y+Z" ,
12541     __FILE__,VRight,group);
12542   theCommands.Add("vaxo" ,
12543     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
12544     __FILE__,VAxo,group);
12545   theCommands.Add("vfront" ,
12546     "vfront           : Front view. Orientation +X+Z" ,
12547     __FILE__,VFront,group);
12548   theCommands.Add("vback" ,
12549     "vback            : Back view. Orientation -X+Z" ,
12550     __FILE__,VBack,group);
12551   theCommands.Add("vpick" ,
12552     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
12553     VPick,group);
12554   theCommands.Add("vfit",
12555     "vfit or <F> [-selected] [-noupdate]"
12556     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
12557     __FILE__,VFit,group);
12558   theCommands.Add ("vfitarea",
12559     "vfitarea x1 y1 x2 y2"
12560     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
12561     "\n\t\t: Fit view to show area located between two points"
12562     "\n\t\t: given in world 2D or 3D corrdinates.",
12563     __FILE__, VFitArea, group);
12564   theCommands.Add ("vzfit", "vzfit [scale]\n"
12565     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
12566     "   \"scale\" - specifies factor to scale computed z range.\n",
12567     __FILE__, VZFit, group);
12568   theCommands.Add("vrepaint",
12569             "vrepaint [-immediate]"
12570     "\n\t\t: force redraw",
12571     __FILE__,VRepaint,group);
12572   theCommands.Add("vclear",
12573     "vclear          : vclear"
12574     "\n\t\t: remove all the object from the viewer",
12575     __FILE__,VClear,group);
12576   theCommands.Add("vsetbg",
12577     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
12578     __FILE__,VSetBg,group);
12579   theCommands.Add("vsetbgmode",
12580     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
12581     __FILE__,VSetBgMode,group);
12582   theCommands.Add("vsetgradientbg",
12583     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
12584     __FILE__,VSetGradientBg,group);
12585   theCommands.Add("vsetgrbgmode",
12586     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
12587     __FILE__,VSetGradientBgMode,group);
12588   theCommands.Add("vsetcolorbg",
12589     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
12590     __FILE__,VSetColorBg,group);
12591   theCommands.Add("vsetdefaultbg",
12592     "vsetdefaultbg r g b\n"
12593     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
12594     "\n\t\t: Set default viewer background fill color (flat/gradient).",
12595     __FILE__,VSetDefaultBg,group);
12596   theCommands.Add("vscale",
12597     "vscale          : vscale X Y Z",
12598     __FILE__,VScale,group);
12599   theCommands.Add("vzbufftrihedron",
12600             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
12601     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
12602     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
12603     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
12604     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
12605     "\n\t\t: Displays a trihedron",
12606     __FILE__,VZBuffTrihedron,group);
12607   theCommands.Add("vrotate",
12608     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
12609     "\n                : Option -mouseStart starts rotation according to the mouse position"
12610     "\n                : Option -mouseMove continues rotation with angle computed"
12611     "\n                : from last and new mouse position."
12612     "\n                : vrotate AX AY AZ [X Y Z]",
12613     __FILE__,VRotate,group);
12614   theCommands.Add("vzoom",
12615     "vzoom           : vzoom coef",
12616     __FILE__,VZoom,group);
12617   theCommands.Add("vpan",
12618     "vpan            : vpan dx dy",
12619     __FILE__,VPan,group);
12620   theCommands.Add("vcolorscale",
12621     "vcolorscale name [-noupdate|-update] [-demo]"
12622     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
12623     "\n\t\t:       [-font HeightFont=20]"
12624     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
12625     "\n\t\t:       [-smoothTransition {on|off}=off]"
12626     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
12627     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
12628     "\n\t\t:       [-textpos {left|right|center|none}=right]"
12629     "\n\t\t:       [-labelAtBorder {on|off}=on]"
12630     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
12631     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
12632     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
12633     "\n\t\t:       [-xy Left=0 Bottom=0]"
12634     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
12635     "\n\t\t:  -colors   - set colors for all intervals"
12636     "\n\t\t:  -color    - set color for specific interval"
12637     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
12638     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
12639     "\n\t\t:              at border means the value inbetween neighbor intervals,"
12640     "\n\t\t:              at center means the center value within current interval"
12641     "\n\t\t:  -labels   - set labels for all intervals"
12642     "\n\t\t:  -freeLabels - same as -labels but does not require"
12643     "\n\t\t:              matching the number of intervals"
12644     "\n\t\t:  -label    - set label for specific interval"
12645     "\n\t\t:  -title    - set title"
12646     "\n\t\t:  -reversed - setup smooth color transition between intervals"
12647     "\n\t\t:  -smoothTransition - swap colorscale direction"
12648     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
12649     __FILE__, VColorScale, group);
12650   theCommands.Add("vgraduatedtrihedron",
12651     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
12652     "\t[-namefont Name] [-valuesfont Name]\n"
12653     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
12654     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
12655     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
12656     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
12657     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
12658     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
12659     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
12660     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
12661     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
12662     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
12663     " - Displays or erases graduated trihedron"
12664     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
12665     " - namefont - font of axes names. Default: Arial\n"
12666     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
12667     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
12668     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
12669     " - valuesfont - font of axes values. Default: Arial\n"
12670     " - xcolor, ycolor, zcolor - color of axis and values\n"
12671     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
12672     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
12673     __FILE__,VGraduatedTrihedron,group);
12674   theCommands.Add("vtile" ,
12675             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
12676     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
12677     "\n\t\t:  -totalSize the size of virtual bigger viewport"
12678     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
12679     "\n\t\t:  -lowerLeft tile offset as lower left corner"
12680     "\n\t\t:  -upperLeft tile offset as upper left corner",
12681     __FILE__, VTile, group);
12682   theCommands.Add("vzlayer",
12683               "vzlayer [layerId]"
12684       "\n\t\t:         [-add|-delete|-get|-settings]"
12685       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
12686       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
12687       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
12688       "\n\t\t: ZLayer list management:"
12689       "\n\t\t:   -add      add new z layer to viewer and print its id"
12690       "\n\t\t:   -delete   delete z layer"
12691       "\n\t\t:   -get      print sequence of z layers"
12692       "\n\t\t:   -settings print status of z layer settings"
12693       "\n\t\t:   -disable  disables given setting"
12694       "\n\t\t:   -enable   enables  given setting",
12695     __FILE__,VZLayer,group);
12696   theCommands.Add("vlayerline",
12697     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
12698     __FILE__,VLayerLine,group);
12699   theCommands.Add("vgrid",
12700               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
12701       "\n\t\t:       [-step X Y] [-size DX DY]"
12702       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
12703     __FILE__, VGrid, group);
12704   theCommands.Add ("vpriviledgedplane",
12705     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
12706     "\n\t\t:   Ox, Oy, Oz - plane origin"
12707     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
12708     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
12709     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
12710     __FILE__, VPriviledgedPlane, group);
12711   theCommands.Add ("vconvert",
12712     "vconvert v [Mode={window|view}]"
12713     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
12714     "\n\t\t: vconvert x y z [Mode={window|grid}]"
12715     "\n\t\t:   window - convert to window coordinates, pixels"
12716     "\n\t\t:   view   - convert to view projection plane"
12717     "\n\t\t:   grid   - convert to model coordinates, given on grid"
12718     "\n\t\t:   ray    - convert projection ray to model coordiantes"
12719     "\n\t\t: - vconvert v window : convert view to window;"
12720     "\n\t\t: - vconvert v view   : convert window to view;"
12721     "\n\t\t: - vconvert x y window : convert view to window;"
12722     "\n\t\t: - vconvert x y view : convert window to view;"
12723     "\n\t\t: - vconvert x y : convert window to model;"
12724     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
12725     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
12726     "\n\t\t: - vconvert x y z window : convert model to window;"
12727     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
12728     "\n\t\t: Converts the given coordinates to window/view/model space.",
12729     __FILE__, VConvert, group);
12730   theCommands.Add ("vfps",
12731     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
12732     __FILE__, VFps, group);
12733   theCommands.Add ("vgldebug",
12734             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
12735     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
12736     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
12737     "\n\t\t: Debug context can be requested only on Windows"
12738     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
12739     "\n\t\t:  -sync     - request synchronized debug GL context"
12740     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
12741     "\n\t\t:              which are suppressed by default,"
12742     "\n\t\t:  -glslCode - log GLSL program source code,"
12743     "\n\t\t:              which are suppressed by default,"
12744     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
12745     "\n\t\t:              which are suppressed by default",
12746     __FILE__, VGlDebug, group);
12747   theCommands.Add ("vvbo",
12748     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
12749     __FILE__, VVbo, group);
12750   theCommands.Add ("vstereo",
12751             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
12752     "\n\t\t:         [-anaglyph Filter]"
12753     "\n\t\t: Control stereo output mode. Available modes for -mode:"
12754     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
12755     "\n\t\t:                     requires driver support."
12756     "\n\t\t:                     Should be called BEFORE vinit!"
12757     "\n\t\t:  anaglyph         - Anaglyph glasses"
12758     "\n\t\t:  rowInterlaced    - row-interlaced display"
12759     "\n\t\t:  columnInterlaced - column-interlaced display"
12760     "\n\t\t:  chessBoard       - chess-board output"
12761     "\n\t\t:  sideBySide       - horizontal pair"
12762     "\n\t\t:  overUnder        - vertical   pair"
12763     "\n\t\t: Available Anaglyph filters for -anaglyph:"
12764     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
12765     "\n\t\t:  greenMagentaSimple",
12766     __FILE__, VStereo, group);
12767   theCommands.Add ("vcaps",
12768             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
12769     "\n\t\t:       [-compatibleProfile {0|1}]"
12770     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
12771     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
12772     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
12773     "\n\t\t: Modify particular graphic driver options:"
12774     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
12775     "\n\t\t:             built-in GLSL programs"
12776     "\n\t\t:            (requires compatible profile)"
12777     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
12778     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
12779     "\n\t\t:             arrays to GPU memory)"
12780     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
12781     "\n\t\t:  vsync    - switch VSync on or off"
12782     "\n\t\t:  winBuffer - allow using window buffer for rendering"
12783     "\n\t\t: Context creation options:"
12784     "\n\t\t:  softMode          - software OpenGL implementation"
12785     "\n\t\t:  compatibleProfile - backward-compatible profile"
12786     "\n\t\t:  quadbuffer        - QuadBuffer"
12787     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
12788     "\n\t\t: rendering paths producing the same visual result when"
12789     "\n\t\t: possible."
12790     "\n\t\t: Command is intended for testing old hardware compatibility.",
12791     __FILE__, VCaps, group);
12792   theCommands.Add ("vmemgpu",
12793     "vmemgpu [f]: print system-dependent GPU memory information if available;"
12794     " with f option returns free memory in bytes",
12795     __FILE__, VMemGpu, group);
12796   theCommands.Add ("vreadpixel",
12797     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
12798     " : Read pixel value for active view",
12799     __FILE__, VReadPixel, group);
12800   theCommands.Add("diffimage",
12801             "diffimage imageFile1 imageFile2 [diffImageFile]"
12802     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
12803     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
12804     "\n\t\t: Compare two images by content and generate difference image."
12805     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
12806     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
12807     __FILE__, VDiffImage, group);
12808   theCommands.Add ("vselect",
12809     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
12810     "- emulates different types of selection:\n"
12811     "- 1) single click selection\n"
12812     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
12813     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
12814     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
12815     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
12816     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
12817     " (partial inclusion - overlap - is not allowed by default)\n"
12818     "- 5) any of these selections with shift button pressed",
12819     __FILE__, VSelect, group);
12820   theCommands.Add ("vmoveto",
12821     "vmoveto [x y] [-reset]"
12822     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
12823     "\n\t\t:   -reset resets current highlighting",
12824     __FILE__, VMoveTo, group);
12825   theCommands.Add ("vviewparams",
12826               "vviewparams [-args] [-scale [s]]"
12827       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
12828       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
12829       "\n\t\t: Manage current view parameters or prints all"
12830       "\n\t\t: current values when called without argument."
12831       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
12832       "\n\t\t:   -eye  [x y z] prints or sets eye location"
12833       "\n\t\t:   -at   [x y z] prints or sets center of look"
12834       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
12835       "\n\t\t:   -proj [x y z] prints or sets direction of look"
12836       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
12837       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
12838       "\n\t\t:                 or changes the size of its maximum dimension"
12839       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
12840     __FILE__, VViewParams, group);
12841
12842   theCommands.Add("v2dmode",
12843     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
12844     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
12845     "\n\t\t:   mode   - switches On/Off rotation mode"
12846     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
12847     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
12848     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
12849     "\n\t\t: View camera position might be changed only by commands.",
12850     __FILE__, V2DMode, group);
12851
12852   theCommands.Add("vanimation", "Alias for vanim",
12853     __FILE__, VAnimation, group);
12854
12855   theCommands.Add("vanim",
12856             "List existing animations:"
12857     "\n\t\t:  vanim"
12858     "\n\t\t: Animation playback:"
12859     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
12860     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
12861     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
12862     "\n\t\t:   -freeLook skip camera animations"
12863     "\n\t\t:   -lockLoop disable any interactions"
12864     "\n\t\t:"
12865     "\n\t\t: Animation definition:"
12866     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
12867     "\n\t\t:        [start TimeSec] [duration TimeSec]"
12868     "\n\t\t:"
12869     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
12870     "\n\t\t: specifies nested animations."
12871     "\n\t\t: There is no syntax to explicitly add new animation,"
12872     "\n\t\t: and all non-existing animations within the name will be"
12873     "\n\t\t: implicitly created on first use (including parents)."
12874     "\n\t\t:"
12875     "\n\t\t: Each animation might define the SINGLE action (see below),"
12876     "\n\t\t: like camera transition, object transformation or custom callback."
12877     "\n\t\t: Child animations can be used for defining concurrent actions."
12878     "\n\t\t:"
12879     "\n\t\t: Camera animation:"
12880     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
12881     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
12882     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
12883     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
12884     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
12885     "\n\t\t:   -atX    camera Center positions pair"
12886     "\n\t\t:   -upX    camera Up directions pair"
12887     "\n\t\t:   -scaleX camera Scale factors pair"
12888     "\n\t\t: Object animation:"
12889     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
12890     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
12891     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
12892     "\n\t\t:   -locX   object Location points pair (translation)"
12893     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
12894     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
12895     "\n\t\t: Custom callback:"
12896     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
12897     "\n\t\t:   %Pts        overall animation presentation timestamp"
12898     "\n\t\t:   %LocalPts   local animation timestamp"
12899     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
12900     "\n\t\t:"
12901     "\n\t\t: Video recording:"
12902     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
12903     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
12904     "\n\t\t:             [-crf Value] [-preset Preset]"
12905     "\n\t\t:   -fps     video framerate"
12906     "\n\t\t:   -format  file format, container (matroska, etc.)"
12907     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
12908     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
12909     "\n\t\t:   -crf     constant rate factor (specific to codec)"
12910     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
12911     __FILE__, VAnimation, group);
12912
12913   theCommands.Add("vchangeselected",
12914     "vchangeselected shape"
12915     "- adds to shape to selection or remove one from it",
12916                 __FILE__, VChangeSelected, group);
12917   theCommands.Add ("vnbselected",
12918     "vnbselected"
12919     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
12920   theCommands.Add ("vcamera",
12921               "vcamera [PrsName] [-ortho] [-projtype]"
12922       "\n\t\t:         [-persp]"
12923       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
12924       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
12925       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
12926       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
12927       "\n\t\t: Manages camera parameters."
12928       "\n\t\t: Displays frustum when presntation name PrsName is specified."
12929       "\n\t\t: Prints current value when option called without argument."
12930       "\n\t\t: Orthographic camera:"
12931       "\n\t\t:   -ortho      activate orthographic projection"
12932       "\n\t\t: Perspective camera:"
12933       "\n\t\t:   -persp      activate perspective  projection (mono)"
12934       "\n\t\t:   -fovy       field of view in y axis, in degrees"
12935       "\n\t\t:   -distance   distance of eye from camera center"
12936       "\n\t\t: Stereoscopic camera:"
12937       "\n\t\t:   -stereo     perspective  projection (stereo)"
12938       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
12939       "\n\t\t:   -rightEye   perspective  projection (right eye)"
12940       "\n\t\t:   -iod        intraocular distance value"
12941       "\n\t\t:   -iodType    distance type, absolute or relative"
12942       "\n\t\t:   -zfocus     stereographic focus value"
12943       "\n\t\t:   -zfocusType focus type, absolute or relative",
12944     __FILE__, VCamera, group);
12945   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
12946     "- vautozfit [on={1|0}] [scale]\n"
12947     "    Prints or changes parameters of automatic z-fit mode:\n"
12948     "   \"on\" - turns automatic z-fit on or off\n"
12949     "   \"scale\" - specifies factor to scale computed z range.\n",
12950     __FILE__, VAutoZFit, group);
12951   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
12952     "   vzrange                - without parameters shows current values\n"
12953     "   vzrange [znear] [zfar] - applies provided values to view",
12954     __FILE__,VZRange, group);
12955   theCommands.Add ("vpurgedisplay",
12956     "vpurgedisplay"
12957     "- removes structures which don't belong to objects displayed in neutral point",
12958     __FILE__, VPurgeDisplay, group);
12959   theCommands.Add("vsetviewsize",
12960     "vsetviewsize size",
12961     __FILE__,VSetViewSize,group);
12962   theCommands.Add("vmoveview",
12963     "vmoveview Dx Dy Dz [Start = 1|0]",
12964     __FILE__,VMoveView,group);
12965   theCommands.Add("vtranslateview",
12966     "vtranslateview Dx Dy Dz [Start = 1|0)]",
12967     __FILE__,VTranslateView,group);
12968   theCommands.Add("vturnview",
12969     "vturnview Ax Ay Az [Start = 1|0]",
12970     __FILE__,VTurnView,group);
12971   theCommands.Add("vtextureenv",
12972     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
12973     "or user-defined file and optionally applying texture mapping parameters\n"
12974     "                  Usage:\n"
12975     "                  vtextureenv off - disables environment mapping\n"
12976     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
12977     "                              std_texture = (0..7)\n"
12978     "                              rep         = {clamp|repeat}\n"
12979     "                              mod         = {decal|modulate}\n"
12980     "                              flt         = {nearest|bilinear|trilinear}\n"
12981     "                              ss, st      - scale factors for s and t texture coordinates\n"
12982     "                              ts, tt      - translation for s and t texture coordinates\n"
12983     "                              rot         - texture rotation angle in degrees",
12984     __FILE__, VTextureEnv, group);
12985   theCommands.Add("vhlr",
12986             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
12987       "\n\t\t: Hidden Line Removal algorithm."
12988       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
12989       "\n\t\t:   -algoType   type of HLR algorithm.\n",
12990     __FILE__,VHLR,group);
12991   theCommands.Add("vhlrtype",
12992               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
12993       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
12994       "\n\t\t:   'algo' - exact HLR algorithm is applied"
12995       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
12996       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
12997     __FILE__,VHLRType,group);
12998   theCommands.Add("vclipplane",
12999               "vclipplane planeName [{0|1}]"
13000       "\n\t\t:   [-equation1 A B C D]"
13001       "\n\t\t:   [-equation2 A B C D]"
13002       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
13003       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
13004       "\n\t\t:   [-maxPlanes]"
13005       "\n\t\t:   [-capping {0|1}]"
13006       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
13007       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
13008       "\n\t\t:       [-texRotate Angle]"
13009       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
13010       "\n\t\t:       [-useObjShader {0|1}]"
13011       "\n\t\t: Clipping planes management:"
13012       "\n\t\t:   -maxPlanes   print plane limit for view"
13013       "\n\t\t:   -delete      delete plane with given name"
13014       "\n\t\t:   {off|on|0|1} turn clipping on/off"
13015       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
13016       "\n\t\t:                applied to active View when list is omitted"
13017       "\n\t\t:   -equation A B C D change plane equation"
13018       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
13019       "\n\t\t: Capping options:"
13020       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
13021       "\n\t\t:   -color R G B          set capping color"
13022       "\n\t\t:   -transparency Value   set capping transparency 0..1"
13023       "\n\t\t:   -texName Texture      set capping texture"
13024       "\n\t\t:   -texScale SX SY       set capping tex scale"
13025       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
13026       "\n\t\t:   -texRotate Angle      set capping tex rotation"
13027       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
13028       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
13029       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
13030       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
13031       __FILE__, VClipPlane, group);
13032   theCommands.Add("vdefaults",
13033                "vdefaults [-absDefl value]"
13034        "\n\t\t:           [-devCoeff value]"
13035        "\n\t\t:           [-angDefl value]"
13036        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
13037     , __FILE__, VDefaults, group);
13038   theCommands.Add("vlight",
13039     "tool to manage light sources, without arguments shows list of lights."
13040     "\n    Main commands: "
13041     "\n      '-clear' to clear lights"
13042     "\n      '-{def}aults' to load deafault lights"
13043     "\n      '-add' <type> to add any light source"
13044     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
13045     "\n      'change' <lightId> to edit light source with specified lightId"
13046     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
13047     "\n        -layer Id"
13048     "\n        -{pos}ition X Y Z"
13049     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
13050     "\n        -color colorName"
13051     "\n        -{head}light 0|1"
13052     "\n        -{sm}oothness value"
13053     "\n        -{int}ensity value"
13054     "\n        -{constAtten}uation value"
13055     "\n        -{linearAtten}uation value"
13056     "\n        -angle angleDeg"
13057     "\n        -{spotexp}onent value"
13058     "\n        -local|-global"
13059     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
13060     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
13061     __FILE__, VLight, group);
13062   theCommands.Add("vraytrace",
13063             "vraytrace [0|1]"
13064     "\n\t\t: Turns on/off ray-tracing renderer."
13065     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
13066     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
13067     __FILE__, VRenderParams, group);
13068   theCommands.Add("vrenderparams",
13069     "\n    Manages rendering parameters: "
13070     "\n      '-raster'                   Disables GPU ray-tracing"
13071     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
13072     "\n      '-lineFeather  > 0'         Sets line feather factor"
13073     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
13074     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
13075     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
13076     "\n      '-rendScale    value        Rendering resolution scale factor"
13077     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
13078     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
13079     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
13080     "\n      '-reflections  on|off'      Enables/disables specular reflections"
13081     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
13082     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
13083     "\n      '-gi           on|off'      Enables/disables global illumination effects"
13084     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
13085     "\n      '-env          on|off'      Enables/disables environment map background"
13086     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
13087     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
13088     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
13089     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
13090     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
13091     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
13092     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
13093     "\n      '-shadingModel model'       Controls shading model from enumeration"
13094     "\n                                  color, flat, gouraud, phong"
13095     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
13096     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
13097     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
13098     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
13099     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
13100     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
13101     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
13102     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
13103     "\n                                  Show/hide performance counters (flags can be combined)"
13104     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
13105     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
13106     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
13107     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
13108     "\n                                        set state to check structures culled previously."
13109     "\n    Unlike vcaps, these parameters dramatically change visual properties."
13110     "\n    Command is intended to control presentation quality depending on"
13111     "\n    hardware capabilities and performance.",
13112     __FILE__, VRenderParams, group);
13113   theCommands.Add("vstatprofiler",
13114     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
13115     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
13116     "\n                |triagles|points|geomMem|textureMem|frameMem"
13117     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
13118     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
13119     "\n                [-noredraw]"
13120     "\n\t\t: Prints rendering statistics."
13121     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
13122     "\n\t\t:   else - print all performance counters set previously."
13123     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
13124     __FILE__, VStatProfiler, group);
13125   theCommands.Add ("vplace",
13126             "vplace dx dy"
13127     "\n\t\t: Places the point (in pixels) at the center of the window",
13128     __FILE__, VPlace, group);
13129   theCommands.Add("vxrotate",
13130     "vxrotate",
13131     __FILE__,VXRotate,group);
13132
13133     theCommands.Add("vmanipulator",
13134       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
13135       "\n    tool to create and manage AIS manipulators."
13136       "\n    Options: "
13137       "\n      '-attach AISObject'                 attach manipulator to AISObject"
13138       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
13139       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
13140       "\n      '-enableModes    {0|1}'             enable modes when attaching"
13141       "\n      '-detach'                           detach manipulator"
13142       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
13143       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
13144       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
13145       "\n      '-move x y z'                     - move attached object"
13146       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
13147       "\n      '-scale factor'                   - scale attached object"
13148       "\n      '-autoActivate      {0|1}'        - set activation on detection"
13149       "\n      '-followTranslation {0|1}'        - set following translation transform"
13150       "\n      '-followRotation    {0|1}'        - set following rotation transform"
13151       "\n      '-followDragging    {0|1}'        - set following dragging transform"
13152       "\n      '-gap value'                      - set gap between sub-parts"
13153       "\n      '-part axis mode    {0|1}'        - set visual part"
13154       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
13155       "\n      '-size value'                     - set size of manipulator"
13156       "\n      '-zoomable {0|1}'                 - set zoom persistence",
13157     __FILE__, VManipulator, group);
13158
13159   theCommands.Add("vselprops",
13160     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
13161     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
13162     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
13163     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
13164     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
13165     "\n    -pickStrategy {first|topmost} : defines picking strategy"
13166     "\n                            'first'   to pick first acceptable (default)"
13167     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
13168     "\n    -pixTol    value        : sets up pixel tolerance"
13169     "\n    -dispMode  dispMode     : sets display mode for highlighting"
13170     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
13171     "\n    -color     {name|r g b} : sets highlight color"
13172     "\n    -transp    value        : sets transparency coefficient for highlight"
13173     "\n    -material  material     : sets highlight material"
13174     "\n    -print                  : prints current state of all mentioned parameters",
13175     __FILE__, VSelectionProperties, group);
13176   theCommands.Add ("vhighlightselected",
13177                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
13178                    __FILE__, VSelectionProperties, group);
13179
13180   theCommands.Add ("vseldump",
13181                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
13182                    "\n\t\t: Generate an image based on detection results:"
13183                    "\n\t\t:   depth       normalized depth values"
13184                    "\n\t\t:   unnormDepth unnormalized depth values"
13185                    "\n\t\t:   object      color of detected object"
13186                    "\n\t\t:   owner       color of detected owner"
13187                    "\n\t\t:   selMode     color of selection mode"
13188                    "\n\t\t:   entity      color of etected entity",
13189                    __FILE__, VDumpSelectionImage, group);
13190
13191 #if defined(_WIN32)
13192   theCommands.Add("vprogressive",
13193     "vprogressive",
13194     __FILE__, VProgressiveMode, group);
13195 #endif
13196 }