0029740: Draw Harness - eliminate redundant casts to AIS_InteractiveObject
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_ColorScale.hxx>
23 #include <AIS_Manipulator.hxx>
24 #include <AIS_RubberBand.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_InteractiveObject.hxx>
27 #include <AIS_ListOfInteractive.hxx>
28 #include <AIS_ListIteratorOfListOfInteractive.hxx>
29 #include <Aspect_Grid.hxx>
30 #include <DBRep.hxx>
31 #include <Draw_ProgressIndicator.hxx>
32 #include <Graphic3d_ArrayOfPolylines.hxx>
33 #include <Graphic3d_AspectMarker3d.hxx>
34 #include <Graphic3d_NameOfTextureEnv.hxx>
35 #include <Graphic3d_GraduatedTrihedron.hxx>
36 #include <Graphic3d_TextureEnv.hxx>
37 #include <Graphic3d_TextureParams.hxx>
38 #include <Graphic3d_TypeOfTextureFilter.hxx>
39 #include <Graphic3d_AspectFillArea3d.hxx>
40 #include <ViewerTest.hxx>
41 #include <ViewerTest_AutoUpdater.hxx>
42 #include <ViewerTest_EventManager.hxx>
43 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
45 #include <ViewerTest_CmdParser.hxx>
46 #include <V3d_AmbientLight.hxx>
47 #include <V3d_DirectionalLight.hxx>
48 #include <V3d_PositionalLight.hxx>
49 #include <V3d_SpotLight.hxx>
50 #include <Message_ProgressSentry.hxx>
51 #include <NCollection_DoubleMap.hxx>
52 #include <NCollection_List.hxx>
53 #include <NCollection_Vector.hxx>
54 #include <AIS_InteractiveContext.hxx>
55 #include <Draw_Interpretor.hxx>
56 #include <Draw.hxx>
57 #include <Draw_Appli.hxx>
58 #include <Image_AlienPixMap.hxx>
59 #include <Image_VideoRecorder.hxx>
60 #include <OpenGl_GraphicDriver.hxx>
61 #include <OSD_Timer.hxx>
62 #include <TColStd_HSequenceOfAsciiString.hxx>
63 #include <TColStd_SequenceOfInteger.hxx>
64 #include <TColStd_HSequenceOfReal.hxx>
65 #include <TColgp_Array1OfPnt2d.hxx>
66 #include <TColStd_MapOfAsciiString.hxx>
67 #include <Aspect_TypeOfLine.hxx>
68 #include <Image_Diff.hxx>
69 #include <Aspect_DisplayConnection.hxx>
70 #include <gp_Pnt.hxx>
71 #include <gp_Dir.hxx>
72 #include <gp_Pln.hxx>
73 #include <PrsMgr_PresentableObject.hxx>
74 #include <Graphic3d_ClipPlane.hxx>
75 #include <NCollection_DataMap.hxx>
76 #include <Graphic3d_Texture2Dmanual.hxx>
77 #include <Prs3d_ShadingAspect.hxx>
78 #include <Prs3d_Drawer.hxx>
79 #include <Prs3d_LineAspect.hxx>
80 #include <Prs3d_Root.hxx>
81 #include <Prs3d_Text.hxx>
82 #include <Select3D_SensitivePrimitiveArray.hxx>
83
84 #ifdef _WIN32
85 #undef DrawText
86 #endif
87
88 #include <cstdlib>
89
90 #if defined(_WIN32)
91   #include <WNT_WClass.hxx>
92   #include <WNT_Window.hxx>
93 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
94   #include <Cocoa_Window.hxx>
95 #else
96   #include <Xw_Window.hxx>
97   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
98   #include <X11/Xutil.h>
99   #include <tk.h>
100 #endif
101
102 // Auxiliary definitions
103 static const char THE_KEY_DELETE = 127;
104 static const char THE_KEY_ESCAPE = 27;
105
106 //==============================================================================
107 //  VIEWER GLOBAL VARIABLES
108 //==============================================================================
109
110 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
111 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
112
113 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
114 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
115
116 extern int VErase (Draw_Interpretor& theDI,
117                    Standard_Integer  theArgNb,
118                    const char**      theArgVec);
119
120 #if defined(_WIN32)
121 static Handle(WNT_Window)& VT_GetWindow() {
122   static Handle(WNT_Window) WNTWin;
123   return WNTWin;
124 }
125 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
126 static Handle(Cocoa_Window)& VT_GetWindow()
127 {
128   static Handle(Cocoa_Window) aWindow;
129   return aWindow;
130 }
131 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
132 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
133 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
134
135 #else
136 static Handle(Xw_Window)& VT_GetWindow(){
137   static Handle(Xw_Window) XWWin;
138   return XWWin;
139 }
140
141 static void VProcessEvents(ClientData,int);
142 #endif
143
144 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
145 {
146   static Handle(Aspect_DisplayConnection) aDisplayConnection;
147   return aDisplayConnection;
148 }
149
150 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
151 {
152   GetDisplayConnection() = theDisplayConnection;
153 }
154
155 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
156 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
157 {
158   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
159 #if defined(_WIN32)
160   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
161   if (!aWindow.IsNull())
162     return aWindow->HWindow();
163 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
164   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
165   if (!aWindow.IsNull())
166   return aWindow->XWindow();
167 #endif
168   return aWindowHandle;
169 }
170 #endif
171
172 //! Setting additional flag to store 2D mode of the View to avoid scene rotation by mouse/key events
173 class ViewerTest_V3dView : public V3d_View
174 {
175   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_V3dView, V3d_View)
176 public:
177   //! Initializes the view.
178   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType = V3d_ORTHOGRAPHIC,
179                       bool theIs2dMode = false)
180   : V3d_View (theViewer, theType), myIs2dMode (theIs2dMode) {}
181
182   //! Initializes the view by copying.
183   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
184   : V3d_View (theViewer, theView), myIs2dMode (false)
185   {
186     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (theView))
187     {
188       myIs2dMode = aV3dView->IsViewIn2DMode();
189     }
190   }
191
192   //! Returns true if 2D mode is set for the view
193   bool IsViewIn2DMode() const { return myIs2dMode; }
194
195   //! Sets 2D mode for the view
196   void SetView2DMode (bool the2dMode) { myIs2dMode = the2dMode; }
197
198 public:
199
200   //! Returns true if active view in 2D mode.
201   static bool IsCurrentViewIn2DMode()
202   {
203     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
204     {
205       return aV3dView->IsViewIn2DMode();
206     }
207     return false;
208   }
209
210   //! Set if active view in 2D mode.
211   static void SetCurrentView2DMode (bool theIs2d)
212   {
213     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
214     {
215       aV3dView->SetView2DMode (theIs2d);
216     }
217   }
218
219 private:
220
221   Standard_Boolean myIs2dMode; //!< 2D mode flag
222
223 };
224
225 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
226 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
227 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
228 static OpenGl_Caps ViewerTest_myDefaultCaps;
229
230 static void OSWindowSetup();
231
232 static struct
233 {
234   Quantity_Color FlatColor;
235   Quantity_Color GradientColor1;
236   Quantity_Color GradientColor2;
237   Aspect_GradientFillMethod FillMethod;
238 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
239
240 //==============================================================================
241 //  EVENT GLOBAL VARIABLES
242 //==============================================================================
243
244 static int Start_Rot = 0;
245 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
246 int X_Motion = 0; // Current cursor position
247 int Y_Motion = 0;
248 int X_ButtonPress = 0; // Last ButtonPress position
249 int Y_ButtonPress = 0;
250 Standard_Boolean IsDragged = Standard_False;
251 Standard_Boolean DragFirst = Standard_False;
252 Standard_Boolean TheIsAnimating = Standard_False;
253 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
254 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
255
256
257 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
258 {
259   static Handle(AIS_RubberBand) aBand;
260   if (aBand.IsNull())
261   {
262     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
263     aBand->SetDisplayMode (0);
264   }
265   return aBand;
266 }
267
268 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
269
270 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
271 {
272   static ViewerTest_MapOfAISManipulators aMap;
273   return aMap;
274 }
275
276 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
277 {
278   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
279   for (; anIt.More(); anIt.Next())
280   {
281     if (anIt.Value()->HasActiveMode())
282     {
283       return anIt.Value();
284     }
285   }
286   return NULL;
287 }
288
289 //==============================================================================
290
291 #ifdef _WIN32
292 static LRESULT WINAPI ViewerWindowProc(
293                                        HWND hwnd,
294                                        UINT uMsg,
295                                        WPARAM wParam,
296                                        LPARAM lParam );
297 static LRESULT WINAPI AdvViewerWindowProc(
298   HWND hwnd,
299   UINT uMsg,
300   WPARAM wParam,
301   LPARAM lParam );
302 #endif
303
304
305 //==============================================================================
306 //function : WClass
307 //purpose  :
308 //==============================================================================
309
310 const Handle(Standard_Transient)& ViewerTest::WClass()
311 {
312   static Handle(Standard_Transient) theWClass;
313 #if defined(_WIN32)
314   if (theWClass.IsNull())
315   {
316     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
317                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
318                                 ::LoadCursor (NULL, IDC_ARROW));
319   }
320 #endif
321   return theWClass;
322 }
323
324 //==============================================================================
325 //function : CreateName
326 //purpose  : Create numerical name for new object in theMap
327 //==============================================================================
328 template <typename ObjectType>
329 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
330                                     const TCollection_AsciiString& theDefaultString)
331 {
332   if (theObjectMap.IsEmpty())
333     return theDefaultString + TCollection_AsciiString(1);
334
335   Standard_Integer aNextKey = 1;
336   Standard_Boolean isFound = Standard_False;
337   while (!isFound)
338   {
339     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
340     // Look for objects with default names
341     if (theObjectMap.IsBound1(aStringKey))
342     {
343       aNextKey++;
344     }
345     else
346       isFound = Standard_True;
347   }
348
349   return theDefaultString + TCollection_AsciiString(aNextKey);
350 }
351
352 //==============================================================================
353 //structure : ViewerTest_Names
354 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
355 //==============================================================================
356 struct ViewerTest_Names
357 {
358 private:
359   TCollection_AsciiString myDriverName;
360   TCollection_AsciiString myViewerName;
361   TCollection_AsciiString myViewName;
362
363 public:
364
365   const TCollection_AsciiString& GetDriverName () const
366   {
367     return myDriverName;
368   }
369   void SetDriverName (const TCollection_AsciiString& theDriverName)
370   {
371     myDriverName = theDriverName;
372   }
373   const TCollection_AsciiString& GetViewerName () const
374   {
375     return myViewerName;
376   }
377   void SetViewerName (const TCollection_AsciiString& theViewerName)
378   {
379     myViewerName = theViewerName;
380   }
381   const TCollection_AsciiString& GetViewName () const
382   {
383     return myViewName;
384   }
385   void SetViewName (const TCollection_AsciiString& theViewName)
386   {
387     myViewName = theViewName;
388   }
389
390   //===========================================================================
391   //function : Constructor for ViewerTest_Names
392   //purpose  : Get view, viewer, driver names from custom string
393   //===========================================================================
394
395   ViewerTest_Names (const TCollection_AsciiString& theInputString)
396   {
397     TCollection_AsciiString aName(theInputString);
398     if (theInputString.IsEmpty())
399     {
400       // Get current configuration
401       if (ViewerTest_myDrivers.IsEmpty())
402         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
403           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
404       else
405         myDriverName = ViewerTest_myDrivers.Find2
406         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
407
408       if(ViewerTest_myContexts.IsEmpty())
409       {
410         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
411           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
412       }
413       else
414       {
415         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
416       }
417
418       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
419     }
420     else
421     {
422       // There is at least view name
423       Standard_Integer aParserNumber = 0;
424       for (Standard_Integer i = 0; i < 3; ++i)
425       {
426         Standard_Integer aParserPos = aName.SearchFromEnd("/");
427         if(aParserPos != -1)
428         {
429           aParserNumber++;
430           aName.Split(aParserPos-1);
431         }
432         else
433           break;
434       }
435       if (aParserNumber == 0)
436       {
437         // Only view name
438         if (!ViewerTest::GetAISContext().IsNull())
439         {
440           myDriverName = ViewerTest_myDrivers.Find2
441           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
442           myViewerName = ViewerTest_myContexts.Find2
443           (ViewerTest::GetAISContext());
444         }
445         else
446         {
447           // There is no opened contexts here, need to create names for viewer and driver
448           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
449             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
450
451           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
452             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
453         }
454         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
455       }
456       else if (aParserNumber == 1)
457       {
458         // Here is viewerName/viewName
459         if (!ViewerTest::GetAISContext().IsNull())
460           myDriverName = ViewerTest_myDrivers.Find2
461           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
462         else
463         {
464           // There is no opened contexts here, need to create name for driver
465           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
466             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
467         }
468         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
469
470         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
471       }
472       else
473       {
474         //Here is driverName/viewerName/viewName
475         myDriverName = TCollection_AsciiString(aName);
476
477         TCollection_AsciiString aViewerName(theInputString);
478         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
479         myViewerName = TCollection_AsciiString(aViewerName);
480
481         myViewName = TCollection_AsciiString(theInputString);
482       }
483     }
484   }
485 };
486
487 //==============================================================================
488 //function : FindContextByView
489 //purpose  : Find AIS_InteractiveContext by View
490 //==============================================================================
491
492 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
493 {
494   Handle(AIS_InteractiveContext) anAISContext;
495
496   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
497        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
498   {
499     if (anIter.Value()->CurrentViewer() == theView->Viewer())
500        return anIter.Key2();
501   }
502   return anAISContext;
503 }
504
505
506 //==============================================================================
507 //function : SetWindowTitle
508 //purpose  : Set window title
509 //==============================================================================
510
511 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
512                      Standard_CString theTitle)
513 {
514 #if defined(_WIN32)
515   const TCollection_ExtendedString theTitleW (theTitle);
516   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
517 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
518   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
519 #else
520   if(GetDisplayConnection()->GetDisplay())
521   {
522     Window aWindow =
523       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
524     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
525   }
526 #endif
527 }
528
529 //==============================================================================
530 //function : IsWindowOverlapped
531 //purpose  : Check if theWindow overlapp another view
532 //==============================================================================
533
534 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
535                                      const Standard_Integer thePxTop,
536                                      const Standard_Integer thePxRight,
537                                      const Standard_Integer thePxBottom,
538                                      TCollection_AsciiString& theViewId)
539 {
540   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
541       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
542   {
543     Standard_Integer aTop = 0,
544       aLeft = 0,
545       aRight = 0,
546       aBottom = 0;
547     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
548     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
549         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
550         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
551         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
552     {
553       theViewId = anIter.Key1();
554       return Standard_True;
555     }
556   }
557   return Standard_False;
558 }
559
560 // Workaround: to create and delete non-orthographic views outside ViewerTest
561 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
562 {
563   ViewerTest_myViews.UnBind1 (theName);
564 }
565
566 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
567                                const Handle(V3d_View)& theView)
568 {
569   ViewerTest_myViews.Bind (theName, theView);
570 }
571
572 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
573 {
574   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
575 }
576 //==============================================================================
577 //function : ViewerInit
578 //purpose  : Create the window viewer and initialize all the global variable
579 //==============================================================================
580
581 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
582                                                 const Standard_Integer thePxTop,
583                                                 const Standard_Integer thePxWidth,
584                                                 const Standard_Integer thePxHeight,
585                                                 const TCollection_AsciiString& theViewName,
586                                                 const TCollection_AsciiString& theDisplayName,
587                                                 const Handle(V3d_View)& theViewToClone)
588 {
589   // Default position and dimension of the viewer window.
590   // Note that left top corner is set to be sufficiently small to have
591   // window fit in the small screens (actual for remote desktops, see #23003).
592   // The position corresponds to the window's client area, thus some
593   // gap is added for window frame to be visible.
594   Standard_Integer aPxLeft   = 20;
595   Standard_Integer aPxTop    = 40;
596   Standard_Integer aPxWidth  = 409;
597   Standard_Integer aPxHeight = 409;
598   Standard_Boolean toCreateViewer = Standard_False;
599   if (!theViewToClone.IsNull())
600   {
601     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
602   }
603
604   Handle(OpenGl_GraphicDriver) aGraphicDriver;
605   ViewerTest_Names aViewNames(theViewName);
606   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
607     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
608
609   if (thePxLeft != 0)
610     aPxLeft = thePxLeft;
611   if (thePxTop != 0)
612     aPxTop = thePxTop;
613   if (thePxWidth != 0)
614     aPxWidth = thePxWidth;
615   if (thePxHeight != 0)
616     aPxHeight = thePxHeight;
617
618   // Get graphic driver (create it or get from another view)
619   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
620   {
621     // Get connection string
622   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
623     TCollection_AsciiString aDisplayName(theDisplayName);
624     if (!aDisplayName.IsEmpty())
625       SetDisplayConnection (new Aspect_DisplayConnection ());
626     else
627       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
628   #else
629     (void)theDisplayName; // avoid warning on unused argument
630     SetDisplayConnection (new Aspect_DisplayConnection ());
631   #endif
632
633     if (Draw_VirtualWindows)
634     {
635       // don't waste the time waiting for VSync when window is not displayed on the screen
636       ViewerTest_myDefaultCaps.swapInterval = 0;
637       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
638       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
639     }
640     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
641     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
642
643     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
644     toCreateViewer = Standard_True;
645   }
646   else
647   {
648     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
649   }
650
651   //Dispose the window if input parameters are default
652   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
653   {
654     Standard_Integer aTop = 0,
655                      aLeft = 0,
656                      aRight = 0,
657                      aBottom = 0,
658                      aScreenWidth = 0,
659                      aScreenHeight = 0;
660
661     // Get screen resolution
662 #if defined(_WIN32) || defined(__WIN32__)
663     RECT aWindowSize;
664     GetClientRect(GetDesktopWindow(), &aWindowSize);
665     aScreenHeight = aWindowSize.bottom;
666     aScreenWidth = aWindowSize.right;
667 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
668     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
669 #else
670     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
671     aScreenWidth = WidthOfScreen(aScreen);
672     aScreenHeight = HeightOfScreen(aScreen);
673 #endif
674
675     TCollection_AsciiString anOverlappedViewId("");
676
677     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
678     {
679       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
680
681       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
682         && aRight + 2*aPxWidth + 40 > aScreenWidth)
683       {
684         if (aBottom + aPxHeight + 40 > aScreenHeight)
685         {
686           aPxLeft = 20;
687           aPxTop = 40;
688           break;
689         }
690         aPxLeft = 20;
691         aPxTop = aBottom + 40;
692       }
693       else
694         aPxLeft = aRight + 20;
695     }
696   }
697
698   // Get viewer name
699   TCollection_AsciiString aTitle("3D View - ");
700   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
701
702   // Change name of current active window
703   if (!ViewerTest::CurrentView().IsNull())
704   {
705     TCollection_AsciiString anActiveWindowTitle("3D View - ");
706     anActiveWindowTitle = anActiveWindowTitle
707       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
708     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
709   }
710
711   // Create viewer
712   Handle(V3d_Viewer) a3DViewer;
713   // If it's the single view, we first look for empty context
714   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
715   {
716     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
717       anIter(ViewerTest_myContexts);
718     if (anIter.More())
719       ViewerTest::SetAISContext (anIter.Value());
720     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
721   }
722   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
723   {
724     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
725     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
726   }
727   else if (a3DViewer.IsNull())
728   {
729     toCreateViewer = Standard_True;
730     a3DViewer = new V3d_Viewer(aGraphicDriver);
731     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
732     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
733                                            ViewerTest_DefaultBackground.GradientColor2,
734                                            ViewerTest_DefaultBackground.FillMethod);
735   }
736
737   // AIS context setup
738   if (ViewerTest::GetAISContext().IsNull() ||
739       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
740   {
741     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
742     ViewerTest::SetAISContext (aContext);
743     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
744   }
745   else
746   {
747     ViewerTest::ResetEventManager();
748   }
749
750   // Create window
751 #if defined(_WIN32)
752   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
753                                     Handle(WNT_WClass)::DownCast (WClass()),
754                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
755                                     aPxLeft, aPxTop,
756                                     aPxWidth, aPxHeight,
757                                     Quantity_NOC_BLACK);
758 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
759   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
760                                      aPxLeft, aPxTop,
761                                      aPxWidth, aPxHeight);
762   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
763 #else
764   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
765                                   aTitle.ToCString(),
766                                   aPxLeft, aPxTop,
767                                   aPxWidth, aPxHeight);
768 #endif
769   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
770
771   // View setup
772   Handle(V3d_View) aView;
773   if (!theViewToClone.IsNull())
774   {
775     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
776   }
777   else
778   {
779     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
780   }
781
782   aView->SetWindow (VT_GetWindow());
783   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
784
785   ViewerTest::CurrentView(aView);
786   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
787
788   // Setup for X11 or NT
789   OSWindowSetup();
790
791   // Set parameters for V3d_View and V3d_Viewer
792   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
793   aV3dView->SetComputedMode(Standard_False);
794
795   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
796   if (toCreateViewer)
797   {
798     a3DViewer->SetDefaultLights();
799     a3DViewer->SetLightOn();
800   }
801
802   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
803   #if TCL_MAJOR_VERSION  < 8
804   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
805       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
806   #else
807   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
808       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
809   #endif
810   #endif
811
812   VT_GetWindow()->Map();
813
814   // Set the handle of created view in the event manager
815   ViewerTest::ResetEventManager();
816
817   ViewerTest::CurrentView()->Redraw();
818
819   aView.Nullify();
820   a3DViewer.Nullify();
821
822   return aViewNames.GetViewName();
823 }
824
825 //==============================================================================
826 //function : RedrawAllViews
827 //purpose  : Redraw all created views
828 //==============================================================================
829 void ViewerTest::RedrawAllViews()
830 {
831   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
832   for (; aViewIt.More(); aViewIt.Next())
833   {
834     const Handle(V3d_View)& aView = aViewIt.Key2();
835     aView->Redraw();
836   }
837 }
838
839 //==============================================================================
840 //function : Vinit
841 //purpose  : Create the window viewer and initialize all the global variable
842 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
843 //==============================================================================
844
845 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
846 {
847   TCollection_AsciiString aViewName, aDisplayName;
848   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
849   Handle(V3d_View) aCopyFrom;
850   TCollection_AsciiString aName, aValue;
851   int is2dMode = -1;
852   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
853   {
854     const TCollection_AsciiString anArg = theArgVec[anArgIt];
855     TCollection_AsciiString anArgCase = anArg;
856     anArgCase.LowerCase();
857     if (anArgIt + 1 < theArgsNb
858      && anArgCase == "-name")
859     {
860       aViewName = theArgVec[++anArgIt];
861     }
862     else if (anArgIt + 1 < theArgsNb
863           && (anArgCase == "-left"
864            || anArgCase == "-l"))
865     {
866       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
867     }
868     else if (anArgIt + 1 < theArgsNb
869           && (anArgCase == "-top"
870            || anArgCase == "-t"))
871     {
872       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
873     }
874     else if (anArgIt + 1 < theArgsNb
875           && (anArgCase == "-width"
876            || anArgCase == "-w"))
877     {
878       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
879     }
880     else if (anArgIt + 1 < theArgsNb
881           && (anArgCase == "-height"
882            || anArgCase == "-h"))
883     {
884       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
885     }
886     else if (anArgCase == "-exitonclose")
887     {
888       Draw_ToExitOnCloseView = true;
889       if (anArgIt + 1 < theArgsNb
890        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
891       {
892         ++anArgIt;
893       }
894     }
895     else if (anArgCase == "-closeonescape"
896           || anArgCase == "-closeonesc")
897     {
898       Draw_ToCloseViewOnEsc = true;
899       if (anArgIt + 1 < theArgsNb
900        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
901       {
902         ++anArgIt;
903       }
904     }
905     else if (anArgCase == "-2d_mode"
906           || anArgCase == "-2dmode"
907           || anArgCase == "-2d")
908     {
909       bool toEnable = true;
910       if (anArgIt + 1 < theArgsNb
911        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
912       {
913         ++anArgIt;
914       }
915       is2dMode = toEnable ? 1 : 0;
916     }
917     else if (anArgIt + 1 < theArgsNb
918           && (anArgCase == "-disp"
919            || anArgCase == "-display"))
920     {
921       aDisplayName = theArgVec[++anArgIt];
922     }
923     else if (!ViewerTest::CurrentView().IsNull()
924           &&  aCopyFrom.IsNull()
925           && (anArgCase == "-copy"
926            || anArgCase == "-clone"
927            || anArgCase == "-cloneactive"
928            || anArgCase == "-cloneactiveview"))
929     {
930       aCopyFrom = ViewerTest::CurrentView();
931     }
932     // old syntax
933     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
934     {
935       aName.LowerCase();
936       if (aName == "name")
937       {
938         aViewName = aValue;
939       }
940       else if (aName == "l"
941             || aName == "left")
942       {
943         aPxLeft = aValue.IntegerValue();
944       }
945       else if (aName == "t"
946             || aName == "top")
947       {
948         aPxTop = aValue.IntegerValue();
949       }
950       else if (aName == "disp"
951             || aName == "display")
952       {
953         aDisplayName = aValue;
954       }
955       else if (aName == "w"
956             || aName == "width")
957       {
958         aPxWidth = aValue.IntegerValue();
959       }
960       else if (aName == "h"
961             || aName == "height")
962       {
963         aPxHeight = aValue.IntegerValue();
964       }
965       else
966       {
967         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
968         return 1;
969       }
970     }
971     else if (aViewName.IsEmpty())
972     {
973       aViewName = anArg;
974     }
975     else
976     {
977       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
978       return 1;
979     }
980   }
981
982 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
983   if (!aDisplayName.IsEmpty())
984   {
985     aDisplayName.Clear();
986     std::cout << "Warning: display parameter will be ignored.\n";
987   }
988 #endif
989
990   ViewerTest_Names aViewNames (aViewName);
991   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
992   {
993     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
994     theDi.Eval (aCommand.ToCString());
995     if (is2dMode != -1)
996     {
997       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
998     }
999     return 0;
1000   }
1001
1002   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
1003                                                             aViewName, aDisplayName, aCopyFrom);
1004   if (is2dMode != -1)
1005   {
1006     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1007   }
1008   theDi << aViewId;
1009   return 0;
1010 }
1011
1012 //! Parse HLR algo type.
1013 static Standard_Boolean parseHlrAlgoType (const char* theName,
1014                                           Prs3d_TypeOfHLR& theType)
1015 {
1016   TCollection_AsciiString aName (theName);
1017   aName.LowerCase();
1018   if (aName == "polyalgo")
1019   {
1020     theType = Prs3d_TOH_PolyAlgo;
1021   }
1022   else if (aName == "algo")
1023   {
1024     theType = Prs3d_TOH_Algo;
1025   }
1026   else
1027   {
1028     return Standard_False;
1029   }
1030   return Standard_True;
1031 }
1032
1033 //==============================================================================
1034 //function : VHLR
1035 //purpose  : hidden lines removal algorithm
1036 //==============================================================================
1037
1038 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1039 {
1040   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1041   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1042   if (aView.IsNull())
1043   {
1044     std::cerr << "Error: No opened viewer!\n";
1045     return 1;
1046   }
1047
1048   Standard_Boolean hasHlrOnArg = Standard_False;
1049   Standard_Boolean hasShowHiddenArg = Standard_False;
1050   Standard_Boolean isHLROn = Standard_False;
1051   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
1052   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
1053   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1054   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1055   {
1056     TCollection_AsciiString anArg (argv[anArgIter]);
1057     anArg.LowerCase();
1058     if (anUpdateTool.parseRedrawMode (anArg))
1059     {
1060       continue;
1061     }
1062     else if (anArg == "-showhidden"
1063           && anArgIter + 1 < argc
1064           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
1065     {
1066       ++anArgIter;
1067       hasShowHiddenArg = Standard_True;
1068       continue;
1069     }
1070     else if ((anArg == "-type"
1071            || anArg == "-algo"
1072            || anArg == "-algotype")
1073           && anArgIter + 1 < argc
1074           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1075     {
1076       ++anArgIter;
1077       continue;
1078     }
1079     else if (!hasHlrOnArg
1080           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
1081     {
1082       hasHlrOnArg = Standard_True;
1083       continue;
1084     }
1085     // old syntax
1086     else if (!hasShowHiddenArg
1087           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
1088     {
1089       hasShowHiddenArg = Standard_True;
1090       continue;
1091     }
1092     else
1093     {
1094       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
1095       return 1;
1096     }
1097   }
1098   if (!hasHlrOnArg)
1099   {
1100     di << "HLR:        " << aView->ComputedMode() << "\n";
1101     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1102     di << "HlrAlgo:    ";
1103     switch (aCtx->DefaultDrawer()->TypeOfHLR())
1104     {
1105       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
1106       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1107       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
1108     }
1109     anUpdateTool.Invalidate();
1110     return 0;
1111   }
1112
1113   Standard_Boolean toRecompute = Standard_False;
1114   if (aTypeOfHLR != Prs3d_TOH_NotSet
1115    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
1116   {
1117     toRecompute = Standard_True;
1118     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1119   }
1120   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1121   {
1122     toRecompute = Standard_True;
1123     if (toShowHidden)
1124     {
1125       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
1126     }
1127     else
1128     {
1129       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
1130     }
1131   }
1132
1133   // redisplay shapes
1134   if (aView->ComputedMode() && isHLROn && toRecompute)
1135   {
1136     AIS_ListOfInteractive aListOfShapes;
1137     aCtx->DisplayedObjects (aListOfShapes);
1138     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
1139     {
1140       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
1141       {
1142         aCtx->Redisplay (aShape, Standard_False);
1143       }
1144     }
1145   }
1146
1147   aView->SetComputedMode (isHLROn);
1148   return 0;
1149 }
1150
1151 //==============================================================================
1152 //function : VHLRType
1153 //purpose  : change type of using HLR algorithm
1154 //==============================================================================
1155
1156 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1157 {
1158   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1159   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1160   if (aView.IsNull())
1161   {
1162     std::cerr << "Error: No opened viewer!\n";
1163     return 1;
1164   }
1165
1166   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1167   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1168   AIS_ListOfInteractive aListOfShapes;
1169   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1170   {
1171     TCollection_AsciiString anArg (argv[anArgIter]);
1172     anArg.LowerCase();
1173     if (anUpdateTool.parseRedrawMode (anArg))
1174     {
1175       continue;
1176     }
1177     else if ((anArg == "-type"
1178            || anArg == "-algo"
1179            || anArg == "-algotype")
1180           && anArgIter + 1 < argc
1181           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1182     {
1183       ++anArgIter;
1184       continue;
1185     }
1186     // old syntax
1187     else if (aTypeOfHLR == Prs3d_TOH_NotSet
1188           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1189     {
1190       continue;
1191     }
1192     else
1193     {
1194       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1195       TCollection_AsciiString aName (argv[anArgIter]);
1196       if (!aMap.IsBound2 (aName))
1197       {
1198         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
1199         return 1;
1200       }
1201
1202       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1203       if (aShape.IsNull())
1204       {
1205         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
1206         return 1;
1207       }
1208       aListOfShapes.Append (aShape);
1209       continue;
1210     }
1211   }
1212   if (aTypeOfHLR == Prs3d_TOH_NotSet)
1213   {
1214     std::cout << "Syntax error: wrong number of arguments!\n";
1215     return 1;
1216   }
1217
1218   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1219   if (isGlobal)
1220   {
1221     aCtx->DisplayedObjects (aListOfShapes);
1222     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1223   }
1224
1225   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1226   {
1227     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1228     if (aShape.IsNull())
1229     {
1230       continue;
1231     }
1232
1233     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1234                             && aView->ComputedMode();
1235     if (!isGlobal
1236      || aShape->TypeOfHLR() != aTypeOfHLR)
1237     {
1238       aShape->SetTypeOfHLR (aTypeOfHLR);
1239     }
1240     if (toUpdateShape)
1241     {
1242       aCtx->Redisplay (aShape, Standard_False);
1243     }
1244   }
1245   return 0;
1246 }
1247
1248 //==============================================================================
1249 //function : FindViewIdByWindowHandle
1250 //purpose  : Find theView Id in the map of views by window handle
1251 //==============================================================================
1252 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1253 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1254 {
1255   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1256        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1257   {
1258     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1259     if (aWindowHandle == theWindowHandle)
1260       return anIter.Key1();
1261   }
1262   return TCollection_AsciiString("");
1263 }
1264 #endif
1265
1266 //==============================================================================
1267 //function : ActivateView
1268 //purpose  : Make the view active
1269 //==============================================================================
1270
1271 void ActivateView (const TCollection_AsciiString& theViewName)
1272 {
1273   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1274   if (!aView.IsNull())
1275   {
1276     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1277     if (!anAISContext.IsNull())
1278     {
1279       if (!ViewerTest::CurrentView().IsNull())
1280       {
1281         TCollection_AsciiString aTitle("3D View - ");
1282         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1283         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1284       }
1285
1286       ViewerTest::CurrentView (aView);
1287       ViewerTest::SetAISContext (anAISContext);
1288       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
1289       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1290 #if defined(_WIN32)
1291       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1292 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1293       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1294 #else
1295       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1296 #endif
1297       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1298       ViewerTest::CurrentView()->Redraw();
1299     }
1300   }
1301 }
1302
1303 //==============================================================================
1304 //function : RemoveView
1305 //purpose  :
1306 //==============================================================================
1307 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1308                              const Standard_Boolean  theToRemoveContext)
1309 {
1310   if (!ViewerTest_myViews.IsBound2 (theView))
1311   {
1312     return;
1313   }
1314
1315   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1316   RemoveView (aViewName, theToRemoveContext);
1317 }
1318
1319 //==============================================================================
1320 //function : RemoveView
1321 //purpose  : Close and remove view from display, clear maps if neccessary
1322 //==============================================================================
1323 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1324 {
1325   if (!ViewerTest_myViews.IsBound1(theViewName))
1326   {
1327     cout << "Wrong view name\n";
1328     return;
1329   }
1330
1331   // Activate another view if it's active now
1332   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1333   {
1334     if (ViewerTest_myViews.Extent() > 1)
1335     {
1336       TCollection_AsciiString aNewViewName;
1337       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1338            anIter.More(); anIter.Next())
1339       {
1340         if (anIter.Key1() != theViewName)
1341         {
1342           aNewViewName = anIter.Key1();
1343           break;
1344         }
1345       }
1346       ActivateView (aNewViewName);
1347     }
1348     else
1349     {
1350       Handle(V3d_View) anEmptyView;
1351 #if defined(_WIN32) || defined(__WIN32__)
1352       Handle(WNT_Window) anEmptyWindow;
1353 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1354       Handle(Cocoa_Window) anEmptyWindow;
1355 #else
1356       Handle(Xw_Window) anEmptyWindow;
1357 #endif
1358       VT_GetWindow() = anEmptyWindow;
1359       ViewerTest::CurrentView (anEmptyView);
1360       if (isContextRemoved)
1361       {
1362         Handle(AIS_InteractiveContext) anEmptyContext;
1363         ViewerTest::SetAISContext(anEmptyContext);
1364       }
1365     }
1366   }
1367
1368   // Delete view
1369   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1370   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1371
1372   // Remove view resources
1373   ViewerTest_myViews.UnBind1(theViewName);
1374   aView->Window()->Unmap();
1375   aView->Remove();
1376
1377 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1378   XFlush (GetDisplayConnection()->GetDisplay());
1379 #endif
1380
1381   // Keep context opened only if the closed view is last to avoid
1382   // unused empty contexts
1383   if (!aCurrentContext.IsNull())
1384   {
1385     // Check if there are more difined views in the viewer
1386     aCurrentContext->CurrentViewer()->InitDefinedViews();
1387     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1388     {
1389       // Remove driver if there is no viewers that use it
1390       Standard_Boolean isRemoveDriver = Standard_True;
1391       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1392           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1393       {
1394         if (aCurrentContext != anIter.Key2() &&
1395           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1396         {
1397           isRemoveDriver = Standard_False;
1398           break;
1399         }
1400       }
1401
1402       aCurrentContext->RemoveAll (Standard_False);
1403       if(isRemoveDriver)
1404       {
1405         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1406       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1407         #if TCL_MAJOR_VERSION  < 8
1408         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1409         #else
1410         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1411         #endif
1412       #endif
1413       }
1414
1415       ViewerTest_myContexts.UnBind2(aCurrentContext);
1416     }
1417   }
1418   cout << "3D View - " << theViewName << " was deleted.\n";
1419   if (Draw_ToExitOnCloseView)
1420   {
1421     Draw_Interprete ("exit");
1422   }
1423 }
1424
1425 //==============================================================================
1426 //function : VClose
1427 //purpose  : Remove the view defined by its name
1428 //==============================================================================
1429
1430 static int VClose (Draw_Interpretor& /*theDi*/,
1431                    Standard_Integer  theArgsNb,
1432                    const char**      theArgVec)
1433 {
1434   NCollection_List<TCollection_AsciiString> aViewList;
1435   if (theArgsNb > 1)
1436   {
1437     TCollection_AsciiString anArg (theArgVec[1]);
1438     anArg.UpperCase();
1439     if (anArg.IsEqual ("ALL")
1440      || anArg.IsEqual ("*"))
1441     {
1442       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1443            anIter.More(); anIter.Next())
1444       {
1445         aViewList.Append (anIter.Key1());
1446       }
1447       if (aViewList.IsEmpty())
1448       {
1449         std::cout << "No view to close\n";
1450         return 0;
1451       }
1452     }
1453     else
1454     {
1455       ViewerTest_Names aViewName (theArgVec[1]);
1456       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1457       {
1458         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1459         return 1;
1460       }
1461       aViewList.Append (aViewName.GetViewName());
1462     }
1463   }
1464   else
1465   {
1466     // close active view
1467     if (ViewerTest::CurrentView().IsNull())
1468     {
1469       std::cerr << "No active view!\n";
1470       return 1;
1471     }
1472     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1473   }
1474
1475   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1476   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1477        anIter.More(); anIter.Next())
1478   {
1479     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1480   }
1481
1482   return 0;
1483 }
1484
1485 //==============================================================================
1486 //function : VActivate
1487 //purpose  : Activate the view defined by its ID
1488 //==============================================================================
1489
1490 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1491 {
1492   if (theArgsNb > 2)
1493   {
1494     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1495     << "Usage: " << theArgVec[0] << " ViewID\n";
1496     return 1;
1497   }
1498   if(theArgsNb == 1)
1499   {
1500     theDi.Eval("vviewlist");
1501     return 0;
1502   }
1503
1504   TCollection_AsciiString aNameString(theArgVec[1]);
1505   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1506   {
1507     TCollection_AsciiString aTitle("3D View - ");
1508     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1509     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1510     Handle(V3d_View) anEmptyView;
1511 #if defined(_WIN32) || defined(__WIN32__)
1512     Handle(WNT_Window) anEmptyWindow;
1513 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1514     Handle(Cocoa_Window) anEmptyWindow;
1515 #else
1516     Handle(Xw_Window) anEmptyWindow;
1517 #endif
1518     VT_GetWindow() = anEmptyWindow;
1519     ViewerTest::CurrentView (anEmptyView);
1520     ViewerTest::ResetEventManager();
1521     theDi << theArgVec[0] << ": all views are inactive\n";
1522     return 0;
1523   }
1524
1525   ViewerTest_Names aViewNames(aNameString);
1526
1527   // Check if this view exists in the viewer with the driver
1528   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1529   {
1530     theDi << "Wrong view name\n";
1531     return 1;
1532   }
1533
1534   // Check if it is active already
1535   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1536   {
1537     theDi << theArgVec[0] << ": the view is active already\n";
1538     return 0;
1539   }
1540
1541   ActivateView (aViewNames.GetViewName());
1542   return 0;
1543 }
1544
1545 //==============================================================================
1546 //function : VViewList
1547 //purpose  : Print current list of views per viewer and graphic driver ID
1548 //           shared between viewers
1549 //==============================================================================
1550
1551 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1552 {
1553   if (theArgsNb > 2)
1554   {
1555     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1556           << "Usage: " << theArgVec[0] << " name";
1557     return 1;
1558   }
1559   if (ViewerTest_myContexts.Size() < 1)
1560     return 0;
1561
1562   Standard_Boolean isTreeView =
1563     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1564
1565   if (isTreeView)
1566   {
1567     theDi << theArgVec[0] <<":\n";
1568   }
1569
1570   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1571        aDriverIter.More(); aDriverIter.Next())
1572   {
1573     if (isTreeView)
1574       theDi << aDriverIter.Key1() << ":\n";
1575
1576     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1577       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1578     {
1579       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1580       {
1581         if (isTreeView)
1582         {
1583           TCollection_AsciiString aContextName(aContextIter.Key1());
1584           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1585         }
1586
1587         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1588              aViewIter.More(); aViewIter.Next())
1589         {
1590           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1591           {
1592             TCollection_AsciiString aViewName(aViewIter.Key1());
1593             if (isTreeView)
1594             {
1595               if (aViewIter.Value() == ViewerTest::CurrentView())
1596                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1597               else
1598                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1599             }
1600             else
1601             {
1602               theDi << aViewName << " ";
1603             }
1604           }
1605         }
1606       }
1607     }
1608   }
1609   return 0;
1610 }
1611
1612 //==============================================================================
1613 //function : VT_ProcessKeyPress
1614 //purpose  : Handle KeyPress event from a CString
1615 //==============================================================================
1616 void VT_ProcessKeyPress (const char* buf_ret)
1617 {
1618   //cout << "KeyPress" << endl;
1619   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1620   // Letter in alphabetic order
1621
1622   if (!strcasecmp (buf_ret, "A")
1623    && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1624   {
1625     // AXO
1626     aView->SetProj(V3d_XposYnegZpos);
1627   }
1628   else if (!strcasecmp (buf_ret, "D")
1629         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1630   {
1631     // Reset
1632     aView->Reset();
1633   }
1634   else if (!strcasecmp (buf_ret, "F"))
1635   {
1636     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1637     {
1638       ViewerTest::GetAISContext()->FitSelected (aView);
1639     }
1640     else
1641     {
1642       // FitAll
1643       aView->FitAll();
1644     }
1645   }
1646   else if (!strcasecmp (buf_ret, "H"))
1647   {
1648     // HLR
1649     std::cout << "HLR" << std::endl;
1650     aView->SetComputedMode (!aView->ComputedMode());
1651     aView->Redraw();
1652   }
1653   else if (!strcasecmp (buf_ret, "P"))
1654   {
1655     // Type of HLR
1656     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1657     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1658       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1659     else
1660       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1661     if (aContext->NbSelected()==0)
1662     {
1663       AIS_ListOfInteractive aListOfShapes;
1664       aContext->DisplayedObjects(aListOfShapes);
1665       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1666         anIter.More(); anIter.Next())
1667       {
1668         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1669         if (aShape.IsNull())
1670           continue;
1671         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1672           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1673         else
1674           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1675         aContext->Redisplay (aShape, Standard_False);
1676       }
1677     }
1678     else
1679     {
1680       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1681       {
1682         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1683         if (aShape.IsNull())
1684           continue;
1685         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1686           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1687         else
1688           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1689         aContext->Redisplay (aShape, Standard_False);
1690       }
1691     }
1692
1693     aContext->UpdateCurrentViewer();
1694
1695   }
1696   else if (!strcasecmp (buf_ret, "S"))
1697   {
1698     std::cout << "setup Shaded display mode" << std::endl;
1699
1700     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1701     if(Ctx->NbSelected()==0)
1702       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1703     else{
1704       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1705         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1706       Ctx->UpdateCurrentViewer();
1707     }
1708   }
1709   else if (!strcasecmp (buf_ret, "U"))
1710   {
1711     // Unset display mode
1712     std::cout << "reset display mode to defaults" << std::endl;
1713
1714     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1715     if(Ctx->NbSelected()==0)
1716       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1717     else{
1718       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1719         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1720       Ctx->UpdateCurrentViewer();
1721     }
1722
1723   }
1724   else if (!strcasecmp (buf_ret, "T")
1725         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1726   {
1727     // Top
1728     aView->SetProj(V3d_Zpos);
1729   }
1730   else if (!strcasecmp (buf_ret, "B")
1731         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1732   {
1733     // Bottom
1734     aView->SetProj(V3d_Zneg);
1735   }
1736   else if (!strcasecmp (buf_ret, "L")
1737         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1738   {
1739     // Left
1740     aView->SetProj(V3d_Xneg);
1741   }
1742   else if (!strcasecmp (buf_ret, "R")
1743         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1744   {
1745     // Right
1746     aView->SetProj(V3d_Xpos);
1747   }
1748   else if (!strcasecmp (buf_ret, "W"))
1749   {
1750     std::cout << "setup WireFrame display mode" << std::endl;
1751     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1752     if(Ctx->NbSelected()==0)
1753       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1754     else{
1755       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1756         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1757       Ctx->UpdateCurrentViewer();
1758     }
1759   }
1760   else if (!strcasecmp (buf_ret, ","))
1761   {
1762     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1763   }
1764   else if (!strcasecmp (buf_ret, "."))
1765   {
1766     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1767   }
1768   else if (!strcasecmp (buf_ret, "/"))
1769   {
1770     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1771     if (aCamera->IsStereo())
1772     {
1773       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1774       aView->Redraw();
1775     }
1776   }
1777   else if (!strcasecmp (buf_ret, "*"))
1778   {
1779     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1780     if (aCamera->IsStereo())
1781     {
1782       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1783       aView->Redraw();
1784     }
1785   }
1786   else if (*buf_ret == THE_KEY_DELETE)
1787   {
1788     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1789     if (!aCtx.IsNull()
1790      && aCtx->NbSelected() > 0)
1791     {
1792       Draw_Interprete ("verase");
1793     }
1794   }
1795   else if (*buf_ret == THE_KEY_ESCAPE)
1796   {
1797     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1798     if (!aCtx.IsNull()
1799      && Draw_ToCloseViewOnEsc)
1800     {
1801       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
1802     }
1803   }
1804   else
1805   {
1806     // Number
1807     const Standard_Integer aSelMode = Draw::Atoi(buf_ret);
1808     if (aSelMode >= 0 && aSelMode <= 7)
1809     {
1810       bool toEnable = true;
1811       if (const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext())
1812       {
1813         AIS_ListOfInteractive aPrsList;
1814         aCtx->DisplayedObjects (aPrsList);
1815         for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
1816         {
1817           TColStd_ListOfInteger aModes;
1818           aCtx->ActivatedModes (aPrsIter.Value(), aModes);
1819           for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
1820           {
1821             if (aModeIter.Value() == aSelMode)
1822             {
1823               toEnable = false;
1824             }
1825           }
1826         }
1827       }
1828       TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
1829       Draw_Interprete (aCmd.ToCString());
1830     }
1831   }
1832 }
1833
1834 //==============================================================================
1835 //function : VT_ProcessExpose
1836 //purpose  : Redraw the View on an Expose Event
1837 //==============================================================================
1838 void VT_ProcessExpose()
1839 {
1840   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1841   if (!aView3d.IsNull())
1842   {
1843     aView3d->Redraw();
1844   }
1845 }
1846
1847 //==============================================================================
1848 //function : VT_ProcessConfigure
1849 //purpose  : Resize the View on an Configure Event
1850 //==============================================================================
1851 void VT_ProcessConfigure()
1852 {
1853   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1854   if (aView3d.IsNull())
1855   {
1856     return;
1857   }
1858
1859   aView3d->MustBeResized();
1860   aView3d->Update();
1861   aView3d->Redraw();
1862 }
1863
1864 //==============================================================================
1865 //function : VT_ProcessButton1Press
1866 //purpose  : Picking
1867 //==============================================================================
1868 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1869                                          const char**     theArgVec,
1870                                          Standard_Boolean theToPick,
1871                                          Standard_Boolean theIsShift)
1872 {
1873   if (TheIsAnimating)
1874   {
1875     TheIsAnimating = Standard_False;
1876     return Standard_False;
1877   }
1878
1879   if (theToPick)
1880   {
1881     Standard_Real X, Y, Z;
1882     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1883
1884     Draw::Set (theArgVec[1], X);
1885     Draw::Set (theArgVec[2], Y);
1886     Draw::Set (theArgVec[3], Z);
1887   }
1888
1889   if (theIsShift)
1890   {
1891     ViewerTest::CurrentEventManager()->ShiftSelect();
1892   }
1893   else
1894   {
1895     ViewerTest::CurrentEventManager()->Select();
1896   }
1897
1898   return Standard_False;
1899 }
1900
1901 //==============================================================================
1902 //function : VT_ProcessButton1Release
1903 //purpose  : End selecting
1904 //==============================================================================
1905 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1906 {
1907   if (IsDragged)
1908   {
1909     IsDragged = Standard_False;
1910     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1911     if (theIsShift)
1912     {
1913       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1914                        X_Motion, Y_Motion);
1915     }
1916     else
1917     {
1918       EM->Select (X_ButtonPress, Y_ButtonPress,
1919                   X_Motion, Y_Motion);
1920     }
1921   }
1922 }
1923
1924 //==============================================================================
1925 //function : VT_ProcessButton3Press
1926 //purpose  : Start Rotation
1927 //==============================================================================
1928 void VT_ProcessButton3Press()
1929 {
1930   if (ViewerTest_V3dView::IsCurrentViewIn2DMode())
1931   {
1932     return;
1933   }
1934
1935   Start_Rot = 1;
1936   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
1937   if (HasHlrOnBeforeRotation)
1938   {
1939     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1940   }
1941   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1942 }
1943
1944 //==============================================================================
1945 //function : VT_ProcessButton3Release
1946 //purpose  : End rotation
1947 //==============================================================================
1948 void VT_ProcessButton3Release()
1949 {
1950   if (Start_Rot)
1951   {
1952     Start_Rot = 0;
1953     if (HasHlrOnBeforeRotation)
1954     {
1955       HasHlrOnBeforeRotation = Standard_False;
1956       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1957       ViewerTest::CurrentView()->Redraw();
1958     }
1959   }
1960 }
1961
1962 //==============================================================================
1963 //function : ProcessControlButton1Motion
1964 //purpose  : Zoom
1965 //==============================================================================
1966
1967 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1968 static void ProcessControlButton1Motion()
1969 {
1970   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1971
1972   X_ButtonPress = X_Motion;
1973   Y_ButtonPress = Y_Motion;
1974 }
1975 #endif
1976
1977 //==============================================================================
1978 //function : VT_ProcessControlButton2Motion
1979 //purpose  : Panning
1980 //==============================================================================
1981 void VT_ProcessControlButton2Motion()
1982 {
1983   Standard_Integer aDx = X_Motion - X_ButtonPress;
1984   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1985
1986   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1987
1988   ViewerTest::CurrentView()->Pan (aDx, aDy);
1989
1990   X_ButtonPress = X_Motion;
1991   Y_ButtonPress = Y_Motion;
1992 }
1993
1994 //==============================================================================
1995 //function : VT_ProcessControlButton3Motion
1996 //purpose  : Rotation
1997 //==============================================================================
1998 void VT_ProcessControlButton3Motion()
1999 {
2000   if (Start_Rot)
2001   {
2002     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
2003   }
2004 }
2005
2006 //==============================================================================
2007 //function : VT_ProcessMotion
2008 //purpose  :
2009 //==============================================================================
2010 void VT_ProcessMotion()
2011 {
2012   //pre-hilights detected objects at mouse position
2013
2014   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
2015   EM->MoveTo(X_Motion, Y_Motion);
2016 }
2017
2018
2019 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
2020 {
2021   Xpix = X_Motion;Ypix=Y_Motion;
2022 }
2023
2024 //==============================================================================
2025 //function : ViewProject: implements VAxo, VTop, VLeft, ...
2026 //purpose  : Switches to an axonometric, top, left and other views
2027 //==============================================================================
2028
2029 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
2030 {
2031   if ( ViewerTest::CurrentView().IsNull() )
2032   {
2033     di<<"Call vinit before this command, please\n";
2034     return 1;
2035   }
2036
2037   ViewerTest::CurrentView()->SetProj(ori);
2038   return 0;
2039 }
2040
2041 //==============================================================================
2042 //function : VAxo
2043 //purpose  : Switch to an Axonometric view
2044 //Draw arg : No args
2045 //==============================================================================
2046
2047 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
2048 {
2049   return ViewProject(di, V3d_XposYnegZpos);
2050 }
2051
2052 //==============================================================================
2053 //function : VTop
2054 //purpose  : Switch to a Top View
2055 //Draw arg : No args
2056 //==============================================================================
2057
2058 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
2059 {
2060   return ViewProject(di, V3d_Zpos);
2061 }
2062
2063 //==============================================================================
2064 //function : VBottom
2065 //purpose  : Switch to a Bottom View
2066 //Draw arg : No args
2067 //==============================================================================
2068
2069 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
2070 {
2071   return ViewProject(di, V3d_Zneg);
2072 }
2073
2074 //==============================================================================
2075 //function : VLeft
2076 //purpose  : Switch to a Left View
2077 //Draw arg : No args
2078 //==============================================================================
2079
2080 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
2081 {
2082   return ViewProject(di, V3d_Xneg);
2083 }
2084
2085 //==============================================================================
2086 //function : VRight
2087 //purpose  : Switch to a Right View
2088 //Draw arg : No args
2089 //==============================================================================
2090
2091 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
2092 {
2093   return ViewProject(di, V3d_Xpos);
2094 }
2095
2096 //==============================================================================
2097 //function : VFront
2098 //purpose  : Switch to a Front View
2099 //Draw arg : No args
2100 //==============================================================================
2101
2102 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
2103 {
2104   return ViewProject(di, V3d_Yneg);
2105 }
2106
2107 //==============================================================================
2108 //function : VBack
2109 //purpose  : Switch to a Back View
2110 //Draw arg : No args
2111 //==============================================================================
2112
2113 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
2114 {
2115   return ViewProject(di, V3d_Ypos);
2116 }
2117
2118 //==============================================================================
2119 //function : VHelp
2120 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
2121 //Draw arg : No args
2122 //==============================================================================
2123
2124 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
2125 {
2126
2127   di << "Q : Quit the application\n";
2128
2129   di << "=========================\n";
2130   di << "F : FitAll\n";
2131   di << "T : TopView\n";
2132   di << "B : BottomView\n";
2133   di << "R : RightView\n";
2134   di << "L : LeftView\n";
2135   di << "A : AxonometricView\n";
2136   di << "D : ResetView\n";
2137
2138   di << "=========================\n";
2139   di << "S : Shading\n";
2140   di << "W : Wireframe\n";
2141   di << "H : HidelLineRemoval\n";
2142   di << "U : Unset display mode\n";
2143   di << "Delete : Remove selection from viewer\n";
2144
2145   di << "=========================\n";
2146   di << "Selection mode \n";
2147   di << "0 : Shape\n";
2148   di << "1 : Vertex\n";
2149   di << "2 : Edge\n";
2150   di << "3 : Wire\n";
2151   di << "4 : Face\n";
2152   di << "5 : Shell\n";
2153   di << "6 : Solid\n";
2154   di << "7 : Compound\n";
2155
2156   di << "=========================\n";
2157   di << "Z : Switch Z clipping On/Off\n";
2158   di << ", : Hilight next detected\n";
2159   di << ". : Hilight previous detected\n";
2160
2161   return 0;
2162 }
2163
2164 #ifdef _WIN32
2165
2166 static Standard_Boolean Ppick = 0;
2167 static Standard_Integer Pargc = 0;
2168 static const char**           Pargv = NULL;
2169
2170
2171 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
2172                                           UINT Msg,
2173                                           WPARAM wParam,
2174                                           LPARAM lParam )
2175 {
2176   if (!ViewerTest_myViews.IsEmpty()) {
2177
2178     WPARAM fwKeys = wParam;
2179
2180     switch( Msg ) {
2181     case WM_CLOSE:
2182        {
2183          // Delete view from map of views
2184          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
2185          return 0;
2186        }
2187        break;
2188     case WM_ACTIVATE:
2189       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
2190         || ViewerTest::CurrentView().IsNull())
2191       {
2192         // Activate inactive window
2193         if(GetWindowHandle(VT_GetWindow()) != hwnd)
2194         {
2195           ActivateView (FindViewIdByWindowHandle(hwnd));
2196         }
2197       }
2198       break;
2199
2200     case WM_LBUTTONUP:
2201       if (IsDragged && !DragFirst)
2202       {
2203         if (!GetActiveAISManipulator().IsNull())
2204         {
2205           GetActiveAISManipulator()->StopTransform();
2206           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2207         }
2208
2209         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2210         {
2211           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2212           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2213         }
2214
2215         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
2216       }
2217       IsDragged = Standard_False;
2218       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2219
2220     case WM_RBUTTONUP:
2221       if (IsDragged && !DragFirst)
2222       {
2223         if (!GetActiveAISManipulator().IsNull())
2224         {
2225           GetActiveAISManipulator()->StopTransform (Standard_False);
2226           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2227         }
2228         IsDragged = Standard_False;
2229       }
2230       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
2231
2232     case WM_LBUTTONDOWN:
2233       if (!GetActiveAISManipulator().IsNull())
2234       {
2235         IsDragged = ( fwKeys == MK_LBUTTON );
2236       }
2237       else
2238       {
2239         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
2240       }
2241
2242       if (IsDragged)
2243       {
2244         DragFirst = Standard_True;
2245         X_ButtonPress = LOWORD(lParam);
2246         Y_ButtonPress = HIWORD(lParam);
2247       }
2248       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2249
2250     case WM_MOUSEMOVE:
2251       if (IsDragged)
2252       {
2253         X_Motion = LOWORD (lParam);
2254         Y_Motion = HIWORD (lParam);
2255         if (!GetActiveAISManipulator().IsNull())
2256         {
2257           if (DragFirst)
2258           {
2259             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
2260           }
2261           else
2262           {
2263             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
2264             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
2265           }
2266         }
2267         else
2268         {
2269           bool toRedraw = false;
2270           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2271           {
2272             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2273             toRedraw = true;
2274           }
2275
2276           RECT aRect;
2277           if (GetClientRect (hwnd, &aRect))
2278           {
2279             int aHeight = aRect.bottom - aRect.top;
2280             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2281             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2282             toRedraw = true;
2283           }
2284           if (toRedraw)
2285           {
2286             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2287           }
2288         }
2289
2290         DragFirst = Standard_False;
2291       }
2292       else
2293         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2294       break;
2295
2296     default:
2297       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2298     }
2299     return 0;
2300   }
2301   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2302 }
2303
2304
2305 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2306                                        UINT Msg,
2307                                        WPARAM wParam,
2308                                        LPARAM lParam )
2309 {
2310   static int Up = 1;
2311   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2312   if (aView.IsNull())
2313   {
2314     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2315   }
2316
2317     PAINTSTRUCT    ps;
2318
2319     switch( Msg ) {
2320     case WM_PAINT:
2321       BeginPaint(hwnd, &ps);
2322       EndPaint(hwnd, &ps);
2323       VT_ProcessExpose();
2324       break;
2325
2326     case WM_SIZE:
2327       VT_ProcessConfigure();
2328       break;
2329     case WM_MOVE:
2330     case WM_MOVING:
2331     case WM_SIZING:
2332       switch (aView->RenderingParams().StereoMode)
2333       {
2334         case Graphic3d_StereoMode_RowInterlaced:
2335         case Graphic3d_StereoMode_ColumnInterlaced:
2336         case Graphic3d_StereoMode_ChessBoard:
2337           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2338           break;
2339         default:
2340           break;
2341       }
2342       break;
2343
2344     case WM_KEYDOWN:
2345       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2346       {
2347         char c[2];
2348         c[0] = (char) wParam;
2349         c[1] = '\0';
2350         if (wParam == VK_DELETE)
2351         {
2352           c[0] = THE_KEY_DELETE;
2353         }
2354         else if (wParam == VK_ESCAPE)
2355         {
2356           c[0] = THE_KEY_ESCAPE;
2357         }
2358         // comma
2359         else if (wParam == VK_OEM_COMMA)
2360         {
2361           c[0] = ',';
2362         }
2363         // dot
2364         else if (wParam == VK_OEM_PERIOD)
2365         {
2366           c[0] = '.';
2367         }
2368         else if (wParam == VK_DIVIDE)
2369         {
2370           c[0] = '/';
2371         }
2372         // dot
2373         else if (wParam == VK_MULTIPLY)
2374         {
2375           c[0] = '*';
2376         }
2377         VT_ProcessKeyPress (c);
2378       }
2379       break;
2380
2381     case WM_LBUTTONUP:
2382     case WM_MBUTTONUP:
2383     case WM_RBUTTONUP:
2384       Up = 1;
2385       VT_ProcessButton3Release();
2386       break;
2387
2388     case WM_LBUTTONDOWN:
2389     case WM_MBUTTONDOWN:
2390     case WM_RBUTTONDOWN:
2391       {
2392         WPARAM fwKeys = wParam;
2393
2394         Up = 0;
2395
2396         X_ButtonPress = LOWORD(lParam);
2397         Y_ButtonPress = HIWORD(lParam);
2398
2399         if (Msg == WM_LBUTTONDOWN)
2400         {
2401           if ((fwKeys & MK_CONTROL) != 0)
2402           {
2403             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2404           }
2405           else
2406           {
2407             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2408           }
2409         }
2410         else if (Msg == WM_RBUTTONDOWN)
2411         {
2412           // Start rotation
2413           VT_ProcessButton3Press();
2414         }
2415       }
2416       break;
2417
2418     case WM_MOUSEWHEEL:
2419     {
2420       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2421       if (wParam & MK_CONTROL)
2422       {
2423         if (aView->Camera()->IsStereo())
2424         {
2425           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2426           if (aFocus > 0.2
2427            && aFocus < 2.0)
2428           {
2429             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2430             aView->Redraw();
2431           }
2432         }
2433       }
2434       else
2435       {
2436         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2437       }
2438       break;
2439     }
2440
2441     case WM_MOUSEMOVE:
2442       {
2443         //cout << "\t WM_MOUSEMOVE" << endl;
2444         WPARAM fwKeys = wParam;
2445         X_Motion = LOWORD(lParam);
2446         Y_Motion = HIWORD(lParam);
2447
2448         if ( Up &&
2449           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2450           {
2451             Up = 0;
2452             X_ButtonPress = LOWORD(lParam);
2453             Y_ButtonPress = HIWORD(lParam);
2454
2455             if ((fwKeys & MK_RBUTTON) != 0) {
2456               // Start rotation
2457               VT_ProcessButton3Press();
2458             }
2459           }
2460
2461           if ((fwKeys & MK_CONTROL) != 0)
2462           {
2463             if ((fwKeys & MK_LBUTTON) != 0)
2464             {
2465               ProcessControlButton1Motion();
2466             }
2467             else if ((fwKeys & MK_MBUTTON) != 0
2468                  || ((fwKeys & MK_LBUTTON) != 0
2469                   && (fwKeys & MK_RBUTTON) != 0))
2470             {
2471               VT_ProcessControlButton2Motion();
2472             }
2473             else if ((fwKeys & MK_RBUTTON) != 0)
2474             {
2475               VT_ProcessControlButton3Motion();
2476             }
2477           }
2478           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2479           {
2480             VT_ProcessMotion();
2481           }
2482       }
2483       break;
2484
2485     default:
2486       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2487     }
2488     return 0L;
2489 }
2490
2491 //==============================================================================
2492 //function : ViewerMainLoop
2493 //purpose  : Get a Event on the view and dispatch it
2494 //==============================================================================
2495
2496
2497 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2498 {
2499   Ppick = (argc > 0)? 1 : 0;
2500   Pargc = argc;
2501   Pargv = argv;
2502
2503   if ( Ppick ) {
2504     MSG msg;
2505     msg.wParam = 1;
2506
2507     cout << "Start picking" << endl;
2508
2509     while ( Ppick == 1 ) {
2510       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2511       if (GetMessageW (&msg, NULL, 0, 0))
2512       {
2513         TranslateMessage (&msg);
2514         DispatchMessageW (&msg);
2515       }
2516     }
2517
2518     cout << "Picking done" << endl;
2519   }
2520
2521   return Ppick;
2522 }
2523
2524 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2525
2526 int min( int a, int b )
2527 {
2528   if( a<b )
2529     return a;
2530   else
2531     return b;
2532 }
2533
2534 int max( int a, int b )
2535 {
2536   if( a>b )
2537     return a;
2538   else
2539     return b;
2540 }
2541
2542 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2543
2544 {
2545   static XEvent aReport;
2546   Standard_Boolean pick = argc > 0;
2547   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2548   XNextEvent (aDisplay, &aReport);
2549
2550   // Handle event for the chosen display connection
2551   switch (aReport.type) {
2552       case ClientMessage:
2553         {
2554           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2555           {
2556             // Close the window
2557             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2558           }
2559         }
2560         return 0;
2561      case FocusIn:
2562       {
2563          // Activate inactive view
2564          Window aWindow = GetWindowHandle(VT_GetWindow());
2565          if(aWindow != aReport.xfocus.window)
2566          {
2567            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2568          }
2569       }
2570       break;
2571       case Expose:
2572         {
2573           VT_ProcessExpose();
2574         }
2575         break;
2576       case ConfigureNotify:
2577         {
2578           VT_ProcessConfigure();
2579         }
2580         break;
2581       case KeyPress:
2582         {
2583
2584           KeySym ks_ret ;
2585           char buf_ret[11] ;
2586           int ret_len ;
2587           XComposeStatus status_in_out;
2588
2589           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2590             (char *) buf_ret , 10 ,
2591             &ks_ret , &status_in_out ) ;
2592
2593
2594           buf_ret[ret_len] = '\0' ;
2595
2596           if (ret_len)
2597           {
2598             VT_ProcessKeyPress (buf_ret);
2599           }
2600         }
2601         break;
2602       case ButtonPress:
2603         {
2604           X_ButtonPress = aReport.xbutton.x;
2605           Y_ButtonPress = aReport.xbutton.y;
2606
2607           if (aReport.xbutton.button == Button1)
2608           {
2609             if (aReport.xbutton.state & ControlMask)
2610             {
2611               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2612             }
2613             else
2614             {
2615               IsDragged = Standard_True;
2616               DragFirst = Standard_True;
2617             }
2618           }
2619           else if (aReport.xbutton.button == Button3)
2620           {
2621             // Start rotation
2622             VT_ProcessButton3Press();
2623           }
2624         }
2625         break;
2626       case ButtonRelease:
2627         {
2628           if( IsDragged )
2629           {
2630             if( !DragFirst )
2631             {
2632               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2633               {
2634                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2635                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2636               }
2637             }
2638
2639             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2640             if( aContext.IsNull() )
2641             {
2642               cout << "The context is null. Please use vinit before createmesh" << endl;
2643               return 0;
2644             }
2645
2646             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2647             if( aReport.xbutton.button==1 )
2648               if( DragFirst )
2649                 if( ShiftPressed )
2650                 {
2651                   aContext->ShiftSelect (Standard_True);
2652                 }
2653                 else
2654                 {
2655                   aContext->Select (Standard_True);
2656                 }
2657               else
2658                 if( ShiftPressed )
2659                 {
2660                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2661                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2662                                         ViewerTest::CurrentView(), Standard_True);
2663                 }
2664                 else
2665                 {
2666                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2667                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2668                                    ViewerTest::CurrentView(), Standard_True);
2669                 }
2670             else
2671               VT_ProcessButton3Release();
2672
2673             IsDragged = Standard_False;
2674           }
2675           else
2676             VT_ProcessButton3Release();
2677         }
2678         break;
2679       case MotionNotify:
2680         {
2681           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2682           {
2683             break;
2684           }
2685           if( IsDragged )
2686           {
2687             if( !DragFirst )
2688             {
2689               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2690               {
2691                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2692               }
2693             }
2694
2695             X_Motion = aReport.xmotion.x;
2696             Y_Motion = aReport.xmotion.y;
2697             DragFirst = Standard_False;
2698
2699             Window aWindow = GetWindowHandle(VT_GetWindow());
2700             Window aRoot;
2701             int anX, anY;
2702             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2703             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2704             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2705             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2706             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2707           }
2708           else
2709           {
2710             X_Motion = aReport.xmotion.x;
2711             Y_Motion = aReport.xmotion.y;
2712
2713             // remove all the ButtonMotionMaskr
2714             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2715
2716             if ( aReport.xmotion.state & ControlMask ) {
2717               if ( aReport.xmotion.state & Button1Mask ) {
2718                 ProcessControlButton1Motion();
2719               }
2720               else if ( aReport.xmotion.state & Button2Mask ) {
2721                 VT_ProcessControlButton2Motion();
2722               }
2723               else if ( aReport.xmotion.state & Button3Mask ) {
2724                 VT_ProcessControlButton3Motion();
2725               }
2726             }
2727             else
2728             {
2729               VT_ProcessMotion();
2730             }
2731           }
2732         }
2733         break;
2734 }
2735 return pick;
2736 }
2737
2738 //==============================================================================
2739 //function : VProcessEvents
2740 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2741 //       event in the Viewer window
2742 //==============================================================================
2743
2744 static void VProcessEvents(ClientData,int)
2745 {
2746   NCollection_Vector<int> anEventNumbers;
2747   // Get number of messages from every display
2748   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2749        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2750   {
2751     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2752   }
2753     // Handle events for every display
2754   int anEventIter = 0;
2755   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2756        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2757   {
2758     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2759          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2760     {
2761       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2762       int anEventResult = ViewerMainLoop( 0, NULL);
2763       // If window is closed or context was not found finish current event processing loop
2764       if (!anEventResult)
2765         return;
2766     }
2767   }
2768
2769   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2770
2771 }
2772 #endif
2773
2774 //==============================================================================
2775 //function : OSWindowSetup
2776 //purpose  : Setup for the X11 window to be able to cath the event
2777 //==============================================================================
2778
2779
2780 static void OSWindowSetup()
2781 {
2782 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2783   // X11
2784
2785   Window  window   = VT_GetWindow()->XWindow();
2786   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2787   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2788   XSynchronize(aDisplay, 1);
2789
2790   // X11 : For keyboard on SUN
2791   XWMHints wmhints;
2792   wmhints.flags = InputHint;
2793   wmhints.input = 1;
2794
2795   XSetWMHints( aDisplay, window, &wmhints);
2796
2797   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2798     ButtonPressMask | ButtonReleaseMask |
2799     StructureNotifyMask |
2800     PointerMotionMask |
2801     Button1MotionMask | Button2MotionMask |
2802     Button3MotionMask | FocusChangeMask
2803     );
2804   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2805   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2806
2807   XSynchronize(aDisplay, 0);
2808
2809 #else
2810   // _WIN32
2811 #endif
2812
2813 }
2814
2815 //==============================================================================
2816 //function : VFit
2817 //purpose  :
2818 //==============================================================================
2819
2820 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2821 {
2822   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2823   if (aView.IsNull())
2824   {
2825     std::cout << "Error: no active viewer!\n";
2826     return 1;
2827   }
2828
2829   Standard_Boolean toFit = Standard_True;
2830   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2831   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2832   {
2833     TCollection_AsciiString anArg (theArgv[anArgIter]);
2834     anArg.LowerCase();
2835     if (anUpdateTool.parseRedrawMode (anArg))
2836     {
2837       continue;
2838     }
2839     else if (anArg == "-selected")
2840     {
2841       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2842       toFit = Standard_False;
2843     }
2844     else
2845     {
2846       std::cout << "Syntax error at '" << anArg << "'\n";
2847     }
2848   }
2849
2850   if (toFit)
2851   {
2852     aView->FitAll (0.01, Standard_False);
2853   }
2854   return 0;
2855 }
2856
2857 //=======================================================================
2858 //function : VFitArea
2859 //purpose  : Fit view to show area located between two points
2860 //         : given in world 2D or 3D coordinates.
2861 //=======================================================================
2862 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2863 {
2864   Handle(V3d_View) aView = ViewerTest::CurrentView();
2865   if (aView.IsNull())
2866   {
2867     std::cerr << theArgVec[0] << "Error: No active view.\n";
2868     return 1;
2869   }
2870
2871   // Parse arguments.
2872   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2873   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2874
2875   if (theArgNb == 5)
2876   {
2877     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2878     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2879     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2880     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2881   }
2882   else if (theArgNb == 7)
2883   {
2884     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2885     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2886     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2887     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2888     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2889     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2890   }
2891   else
2892   {
2893     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2894     theDI.PrintHelp(theArgVec[0]);
2895     return 1;
2896   }
2897
2898   // Convert model coordinates to view space
2899   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2900   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2901   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2902
2903   // Determine fit area
2904   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2905   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2906
2907   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2908
2909   if (aDiagonal < Precision::Confusion())
2910   {
2911     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2912     return 1;
2913   }
2914
2915   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2916   return 0;
2917 }
2918
2919 //==============================================================================
2920 //function : VZFit
2921 //purpose  : ZFitall, no DRAW arguments
2922 //Draw arg : No args
2923 //==============================================================================
2924 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2925 {
2926   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2927
2928   if (aCurrentView.IsNull())
2929   {
2930     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2931     return 1;
2932   }
2933
2934   if (theArgsNb == 1)
2935   {
2936     aCurrentView->ZFitAll();
2937     aCurrentView->Redraw();
2938     return 0;
2939   }
2940
2941   Standard_Real aScale = 1.0;
2942
2943   if (theArgsNb >= 2)
2944   {
2945     aScale = Draw::Atoi (theArgVec[1]);
2946   }
2947
2948   aCurrentView->ZFitAll (aScale);
2949   aCurrentView->Redraw();
2950
2951   return 0;
2952 }
2953
2954 //==============================================================================
2955 //function : VRepaint
2956 //purpose  :
2957 //==============================================================================
2958 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2959 {
2960   Handle(V3d_View) aView = ViewerTest::CurrentView();
2961   if (aView.IsNull())
2962   {
2963     std::cout << "Error: no active viewer!\n";
2964     return 1;
2965   }
2966
2967   Standard_Boolean isImmediateUpdate = Standard_False;
2968   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2969   {
2970     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2971     anArg.LowerCase();
2972     if (anArg == "-immediate")
2973     {
2974       isImmediateUpdate = Standard_True;
2975       if (anArgIter + 1 < theArgNb
2976        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2977       {
2978         ++anArgIter;
2979       }
2980     }
2981     else
2982     {
2983       std::cout << "Syntax error at '" << anArg << "'\n";
2984     }
2985   }
2986
2987   if (isImmediateUpdate)
2988   {
2989     aView->RedrawImmediate();
2990   }
2991   else
2992   {
2993     aView->Redraw();
2994   }
2995   return 0;
2996 }
2997
2998 //==============================================================================
2999 //function : VClear
3000 //purpose  : Remove all the object from the viewer
3001 //Draw arg : No args
3002 //==============================================================================
3003
3004 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3005 {
3006   Handle(V3d_View) V = ViewerTest::CurrentView();
3007   if(!V.IsNull())
3008     ViewerTest::Clear();
3009   return 0;
3010 }
3011
3012 //==============================================================================
3013 //function : VPick
3014 //purpose  :
3015 //==============================================================================
3016
3017 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3018 { if (ViewerTest::CurrentView().IsNull() ) return 1;
3019
3020 if ( argc < 4 ) {
3021   di << argv[0] << "Invalid number of arguments\n";
3022   return 1;
3023 }
3024
3025 while (ViewerMainLoop( argc, argv)) {
3026 }
3027
3028 return 0;
3029 }
3030
3031 //==============================================================================
3032 //function : VSetBg
3033 //purpose  : Load image as background
3034 //==============================================================================
3035
3036 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3037 {
3038   if (argc < 2 || argc > 3)
3039   {
3040     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
3041     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
3042     return 1;
3043   }
3044
3045   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3046   if(AISContext.IsNull())
3047   {
3048     di << "use 'vinit' command before " << argv[0] << "\n";
3049     return 1;
3050   }
3051
3052   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
3053   if (argc == 3)
3054   {
3055     const char* szType = argv[2];
3056     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3057     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3058     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3059     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3060     else
3061     {
3062       di << "Wrong fill type : " << szType << "\n";
3063       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3064       return 1;
3065     }
3066   }
3067
3068   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3069   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
3070
3071   return 0;
3072 }
3073
3074 //==============================================================================
3075 //function : VSetBgMode
3076 //purpose  : Change background image fill type
3077 //==============================================================================
3078
3079 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3080 {
3081   if (argc != 2)
3082   {
3083     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
3084     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
3085     return 1;
3086   }
3087
3088   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3089   if(AISContext.IsNull())
3090   {
3091     di << "use 'vinit' command before " << argv[0] << "\n";
3092     return 1;
3093   }
3094   Aspect_FillMethod aFillType = Aspect_FM_NONE;
3095   const char* szType = argv[1];
3096   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3097   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3098   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3099   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3100   else
3101   {
3102     di << "Wrong fill type : " << szType << "\n";
3103     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3104     return 1;
3105   }
3106   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3107   V3dView->SetBgImageStyle(aFillType, Standard_True);
3108   return 0;
3109 }
3110
3111 //==============================================================================
3112 //function : VSetGradientBg
3113 //purpose  : Mount gradient background
3114 //==============================================================================
3115 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3116 {
3117   if (argc != 8 )
3118   {
3119     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
3120     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
3121     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3122     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3123     return 1;
3124   }
3125
3126   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3127   if(AISContext.IsNull())
3128   {
3129     di << "use 'vinit' command before " << argv[0] << "\n";
3130     return 1;
3131   }
3132   if (argc == 8)
3133   {
3134
3135     Standard_Real R1 = Draw::Atof(argv[1])/255.;
3136     Standard_Real G1 = Draw::Atof(argv[2])/255.;
3137     Standard_Real B1 = Draw::Atof(argv[3])/255.;
3138     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
3139
3140     Standard_Real R2 = Draw::Atof(argv[4])/255.;
3141     Standard_Real G2 = Draw::Atof(argv[5])/255.;
3142     Standard_Real B2 = Draw::Atof(argv[6])/255.;
3143
3144     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
3145     int aType = Draw::Atoi(argv[7]);
3146     if( aType < 0 || aType > 8 )
3147     {
3148       di << "Wrong fill type \n";
3149       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3150       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3151       return 1;
3152     }
3153
3154     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3155
3156     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3157     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
3158   }
3159
3160   return 0;
3161 }
3162
3163 //==============================================================================
3164 //function : VSetGradientBgMode
3165 //purpose  : Change gradient background fill style
3166 //==============================================================================
3167 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3168 {
3169   if (argc != 2 )
3170   {
3171     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
3172     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3173     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3174     return 1;
3175   }
3176
3177   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3178   if(AISContext.IsNull())
3179   {
3180     di << "use 'vinit' command before " << argv[0] << "\n";
3181     return 1;
3182   }
3183   if (argc == 2)
3184   {
3185     int aType = Draw::Atoi(argv[1]);
3186     if( aType < 0 || aType > 8 )
3187     {
3188       di << "Wrong fill type \n";
3189       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3190       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3191       return 1;
3192     }
3193
3194     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3195
3196     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3197     V3dView->SetBgGradientStyle( aMethod, 1 );
3198   }
3199
3200   return 0;
3201 }
3202
3203 //==============================================================================
3204 //function : VSetColorBg
3205 //purpose  : Set color background
3206 //==============================================================================
3207 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3208 {
3209   if (argc != 4 )
3210   {
3211     di << "Usage : " << argv[0] << " R G B : Set color background\n";
3212     di << "R,G,B = [0..255]\n";
3213     return 1;
3214   }
3215
3216   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3217   if(AISContext.IsNull())
3218   {
3219     di << "use 'vinit' command before " << argv[0] << "\n";
3220     return 1;
3221   }
3222   if (argc == 4)
3223   {
3224
3225     Standard_Real R = Draw::Atof(argv[1])/255.;
3226     Standard_Real G = Draw::Atof(argv[2])/255.;
3227     Standard_Real B = Draw::Atof(argv[3])/255.;
3228     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
3229
3230     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3231     V3dView->SetBackgroundColor( aColor );
3232     V3dView->Update();
3233   }
3234
3235   return 0;
3236 }
3237
3238 //==============================================================================
3239 //function : VSetDefaultBg
3240 //purpose  : Set default viewer background fill color
3241 //==============================================================================
3242 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3243 {
3244   if (theArgNb != 4
3245    && theArgNb != 8)
3246   {
3247     std::cout << "Error: wrong syntax! See usage:\n";
3248     theDI.PrintHelp (theArgVec[0]);
3249     return 1;
3250   }
3251
3252   ViewerTest_DefaultBackground.FillMethod =
3253     theArgNb == 4 ? Aspect_GFM_NONE
3254                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
3255
3256   if (theArgNb == 4)
3257   {
3258     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
3259     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
3260     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
3261     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
3262   }
3263   else
3264   {
3265     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
3266     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
3267     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
3268     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
3269
3270     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
3271     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
3272     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
3273     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
3274   }
3275
3276   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
3277        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
3278   {
3279     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
3280     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
3281     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
3282                                          ViewerTest_DefaultBackground.GradientColor2,
3283                                          ViewerTest_DefaultBackground.FillMethod);
3284   }
3285
3286   return 0;
3287 }
3288
3289 //==============================================================================
3290 //function : VScale
3291 //purpose  : View Scaling
3292 //==============================================================================
3293
3294 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3295 {
3296   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3297   if ( V3dView.IsNull() ) return 1;
3298
3299   if ( argc != 4 ) {
3300     di << argv[0] << "Invalid number of arguments\n";
3301     return 1;
3302   }
3303   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3304   return 0;
3305 }
3306 //==============================================================================
3307 //function : VZBuffTrihedron
3308 //purpose  :
3309 //==============================================================================
3310
3311 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3312                             Standard_Integer  theArgNb,
3313                             const char**      theArgVec)
3314 {
3315   Handle(V3d_View) aView = ViewerTest::CurrentView();
3316   if (aView.IsNull())
3317   {
3318     std::cout << "Error: no active viewer!\n";
3319     return 1;
3320   }
3321
3322   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3323
3324   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3325   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3326   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3327   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3328   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3329   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3330   Standard_Real                 aScale        = 0.1;
3331   Standard_Real                 aSizeRatio    = 0.8;
3332   Standard_Real                 anArrowDiam   = 0.05;
3333   Standard_Integer              aNbFacets     = 12;
3334   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3335   {
3336     Standard_CString        anArg = theArgVec[anArgIter];
3337     TCollection_AsciiString aFlag (anArg);
3338     aFlag.LowerCase();
3339     if (anUpdateTool.parseRedrawMode (aFlag))
3340     {
3341       continue;
3342     }
3343     else if (aFlag == "-on")
3344     {
3345       continue;
3346     }
3347     else if (aFlag == "-off")
3348     {
3349       aView->TriedronErase();
3350       return 0;
3351     }
3352     else if (aFlag == "-pos"
3353           || aFlag == "-position"
3354           || aFlag == "-corner")
3355     {
3356       if (++anArgIter >= theArgNb)
3357       {
3358         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3359         return 1;
3360       }
3361
3362       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3363       aPosName.LowerCase();
3364       if (aPosName == "center")
3365       {
3366         aPosition = Aspect_TOTP_CENTER;
3367       }
3368       else if (aPosName == "left_lower"
3369             || aPosName == "lower_left"
3370             || aPosName == "leftlower"
3371             || aPosName == "lowerleft")
3372       {
3373         aPosition = Aspect_TOTP_LEFT_LOWER;
3374       }
3375       else if (aPosName == "left_upper"
3376             || aPosName == "upper_left"
3377             || aPosName == "leftupper"
3378             || aPosName == "upperleft")
3379       {
3380         aPosition = Aspect_TOTP_LEFT_UPPER;
3381       }
3382       else if (aPosName == "right_lower"
3383             || aPosName == "lower_right"
3384             || aPosName == "rightlower"
3385             || aPosName == "lowerright")
3386       {
3387         aPosition = Aspect_TOTP_RIGHT_LOWER;
3388       }
3389       else if (aPosName == "right_upper"
3390             || aPosName == "upper_right"
3391             || aPosName == "rightupper"
3392             || aPosName == "upperright")
3393       {
3394         aPosition = Aspect_TOTP_RIGHT_UPPER;
3395       }
3396       else
3397       {
3398         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3399         return 1;
3400       }
3401     }
3402     else if (aFlag == "-type")
3403     {
3404       if (++anArgIter >= theArgNb)
3405       {
3406         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3407         return 1;
3408       }
3409
3410       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3411       aTypeName.LowerCase();
3412       if (aTypeName == "wireframe"
3413        || aTypeName == "wire")
3414       {
3415         aVisType = V3d_WIREFRAME;
3416       }
3417       else if (aTypeName == "zbuffer"
3418             || aTypeName == "shaded")
3419       {
3420         aVisType = V3d_ZBUFFER;
3421       }
3422       else
3423       {
3424         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3425       }
3426     }
3427     else if (aFlag == "-scale")
3428     {
3429       if (++anArgIter >= theArgNb)
3430       {
3431         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3432         return 1;
3433       }
3434
3435       aScale = Draw::Atof (theArgVec[anArgIter]);
3436     }
3437     else if (aFlag == "-size"
3438           || aFlag == "-sizeratio")
3439     {
3440       if (++anArgIter >= theArgNb)
3441       {
3442         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3443         return 1;
3444       }
3445
3446       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3447     }
3448     else if (aFlag == "-arrowdiam"
3449           || aFlag == "-arrowdiameter")
3450     {
3451       if (++anArgIter >= theArgNb)
3452       {
3453         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3454         return 1;
3455       }
3456
3457       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3458     }
3459     else if (aFlag == "-nbfacets")
3460     {
3461       if (++anArgIter >= theArgNb)
3462       {
3463         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3464         return 1;
3465       }
3466
3467       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3468     }
3469     else if (aFlag == "-colorlabel"
3470           || aFlag == "-colorlabels")
3471     {
3472       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3473                                                            theArgVec + anArgIter + 1,
3474                                                            aLabelsColor);
3475       if (aNbParsed == 0)
3476       {
3477         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3478         return 1;
3479       }
3480       anArgIter += aNbParsed;
3481     }
3482     else if (aFlag == "-colorarrowx")
3483     {
3484       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3485                                                            theArgVec + anArgIter + 1,
3486                                                            anArrowColorX);
3487       if (aNbParsed == 0)
3488       {
3489         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3490         return 1;
3491       }
3492       anArgIter += aNbParsed;
3493     }
3494     else if (aFlag == "-colorarrowy")
3495     {
3496       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3497                                                            theArgVec + anArgIter + 1,
3498                                                            anArrowColorY);
3499       if (aNbParsed == 0)
3500       {
3501         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3502         return 1;
3503       }
3504       anArgIter += aNbParsed;
3505     }
3506     else if (aFlag == "-colorarrowz")
3507     {
3508       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3509                                                            theArgVec + anArgIter + 1,
3510                                                            anArrowColorZ);
3511       if (aNbParsed == 0)
3512       {
3513         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3514         return 1;
3515       }
3516       anArgIter += aNbParsed;
3517     }
3518     else
3519     {
3520       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3521       return 1;
3522     }
3523   }
3524
3525   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3526                                aSizeRatio, anArrowDiam, aNbFacets);
3527   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3528   aView->ZFitAll();
3529   return 0;
3530 }
3531
3532 //==============================================================================
3533 //function : VRotate
3534 //purpose  : Camera Rotating
3535 //==============================================================================
3536
3537 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3538 {
3539   Handle(V3d_View) aView = ViewerTest::CurrentView();
3540   if (aView.IsNull())
3541   {
3542     std::cout << "No active view!\n";
3543     return 1;
3544   }
3545
3546   Standard_Boolean hasFlags = Standard_False;
3547   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3548   {
3549     Standard_CString        anArg (theArgVec[anArgIter]);
3550     TCollection_AsciiString aFlag (anArg);
3551     aFlag.LowerCase();
3552     if (aFlag == "-mousestart"
3553      || aFlag == "-mousefrom")
3554     {
3555       hasFlags = Standard_True;
3556       if (anArgIter + 2 >= theArgNb)
3557       {
3558         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3559         return 1;
3560       }
3561
3562       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3563       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3564       aView->StartRotation (anX, anY);
3565     }
3566     else if (aFlag == "-mousemove")
3567     {
3568       hasFlags = Standard_True;
3569       if (anArgIter + 2 >= theArgNb)
3570       {
3571         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3572         return 1;
3573       }
3574
3575       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3576       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3577       aView->Rotation (anX, anY);
3578     }
3579     else if (theArgNb != 4
3580           && theArgNb != 7)
3581     {
3582       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3583       return 1;
3584     }
3585   }
3586
3587   if (hasFlags)
3588   {
3589     return 0;
3590   }
3591   else if (theArgNb == 4)
3592   {
3593     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3594     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3595     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3596     aView->Rotate (anAX, anAY, anAZ);
3597     return 0;
3598   }
3599   else if (theArgNb == 7)
3600   {
3601     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3602     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3603     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3604
3605     Standard_Real anX = Draw::Atof (theArgVec[4]);
3606     Standard_Real anY = Draw::Atof (theArgVec[5]);
3607     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3608
3609     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3610     return 0;
3611   }
3612
3613   std::cout << "Error: Invalid number of arguments\n";
3614   return 1;
3615 }
3616
3617 //==============================================================================
3618 //function : VZoom
3619 //purpose  : View zoom in / out (relative to current zoom)
3620 //==============================================================================
3621
3622 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3623   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3624   if ( V3dView.IsNull() ) {
3625     return 1;
3626   }
3627
3628   if ( argc == 2 ) {
3629     Standard_Real coef = Draw::Atof(argv[1]);
3630     if ( coef <= 0.0 ) {
3631       di << argv[1] << "Invalid value\n";
3632       return 1;
3633     }
3634     V3dView->SetZoom( Draw::Atof(argv[1]) );
3635     return 0;
3636   } else {
3637     di << argv[0] << " Invalid number of arguments\n";
3638     return 1;
3639   }
3640 }
3641
3642 //==============================================================================
3643 //function : VPan
3644 //purpose  : View panning (in pixels)
3645 //==============================================================================
3646
3647 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3648   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3649   if ( V3dView.IsNull() ) return 1;
3650
3651   if ( argc == 3 ) {
3652     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3653     return 0;
3654   } else {
3655     di << argv[0] << " Invalid number of arguments\n";
3656     return 1;
3657   }
3658 }
3659
3660 //==============================================================================
3661 //function : VPlace
3662 //purpose  : Place the point (in pixels) at the center of the window
3663 //==============================================================================
3664 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3665 {
3666   Handle(V3d_View) aView = ViewerTest::CurrentView();
3667   if (aView.IsNull())
3668   {
3669     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3670     return 1;
3671   }
3672
3673   if (theArgNb != 3)
3674   {
3675     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3676     return 1;
3677   }
3678
3679   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3680
3681   return 0;
3682 }
3683
3684 static int VColorScale (Draw_Interpretor& theDI,
3685                         Standard_Integer  theArgNb,
3686                         const char**      theArgVec)
3687 {
3688   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3689   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3690   if (aContext.IsNull())
3691   {
3692     std::cout << "Error: no active view!\n";
3693     return 1;
3694   }
3695   if (theArgNb <= 1)
3696   {
3697     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3698     return 1;
3699   }
3700
3701   Handle(AIS_ColorScale) aColorScale;
3702   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3703   {
3704     // find existing object
3705     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3706     if (aColorScale.IsNull())
3707     {
3708       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3709       return 1;
3710     }
3711   }
3712
3713   if (theArgNb <= 2)
3714   {
3715     if (aColorScale.IsNull())
3716     {
3717       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3718       return 1;
3719     }
3720
3721     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3722           << "Min range: "            << aColorScale->GetMin() << "\n"
3723           << "Max range: "            << aColorScale->GetMax() << "\n"
3724           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3725           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3726           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3727           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3728           << "Label position: ";
3729     switch (aColorScale->GetLabelPosition())
3730     {
3731       case Aspect_TOCSP_NONE:
3732         theDI << "None\n";
3733         break;
3734       case Aspect_TOCSP_LEFT:
3735         theDI << "Left\n";
3736         break;
3737       case Aspect_TOCSP_RIGHT:
3738         theDI << "Right\n";
3739         break;
3740       case Aspect_TOCSP_CENTER:
3741         theDI << "Center\n";
3742         break;
3743     }
3744     return 0;
3745   }
3746
3747   if (aColorScale.IsNull())
3748   {
3749     aColorScale = new AIS_ColorScale();
3750     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3751     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3752   }
3753
3754   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3755   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3756   {
3757     Standard_CString        anArg = theArgVec[anArgIter];
3758     TCollection_AsciiString aFlag (anArg);
3759     aFlag.LowerCase();
3760     if (anUpdateTool.parseRedrawMode (aFlag))
3761     {
3762       continue;
3763     }
3764     else if (aFlag == "-range")
3765     {
3766       if (anArgIter + 3 >= theArgNb)
3767       {
3768         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3769         return 1;
3770       }
3771
3772       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3773       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3774       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3775       if (!aRangeMin.IsRealValue()
3776        || !aRangeMax.IsRealValue())
3777       {
3778         std::cout << "Error: the range values should be real!\n";
3779         return 1;
3780       }
3781       else if (!aNbIntervals.IsIntegerValue())
3782       {
3783         std::cout << "Error: the number of intervals should be integer!\n";
3784         return 1;
3785       }
3786
3787       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3788       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3789     }
3790     else if (aFlag == "-font")
3791     {
3792       if (anArgIter + 1 >= theArgNb)
3793       {
3794         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3795         return 1;
3796       }
3797       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3798       if (!aFontArg.IsIntegerValue())
3799       {
3800         std::cout << "Error: HeightFont value should be integer!\n";
3801         return 1;
3802       }
3803
3804       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3805       anArgIter += 1;
3806     }
3807     else if (aFlag == "-textpos")
3808     {
3809       if (anArgIter + 1 >= theArgNb)
3810       {
3811         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3812         return 1;
3813       }
3814
3815       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3816       aTextPosArg.LowerCase();
3817       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3818       if (aTextPosArg == "none")
3819       {
3820         aLabPosition = Aspect_TOCSP_NONE;
3821       }
3822       else if (aTextPosArg == "left")
3823       {
3824         aLabPosition = Aspect_TOCSP_LEFT;
3825       }
3826       else if (aTextPosArg == "right")
3827       {
3828         aLabPosition = Aspect_TOCSP_RIGHT;
3829       }
3830       else if (aTextPosArg == "center")
3831       {
3832         aLabPosition = Aspect_TOCSP_CENTER;
3833       }
3834       else
3835       {
3836         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3837         return 1;
3838       }
3839       aColorScale->SetLabelPosition (aLabPosition);
3840     }
3841     else if (aFlag == "-logarithmic"
3842           || aFlag == "-log")
3843     {
3844       if (anArgIter + 1 >= theArgNb)
3845       {
3846         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3847         return 1;
3848       }
3849
3850       Standard_Boolean IsLog;
3851       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3852       {
3853         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3854         return 1;
3855       }
3856       aColorScale->SetLogarithmic (IsLog);
3857     }
3858     else if (aFlag == "-huerange"
3859           || aFlag == "-hue")
3860     {
3861       if (anArgIter + 2 >= theArgNb)
3862       {
3863         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3864         return 1;
3865       }
3866
3867       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3868       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3869       aColorScale->SetHueRange (aHueMin, aHueMax);
3870     }
3871     else if (aFlag == "-colorrange")
3872     {
3873       Quantity_Color aColorMin, aColorMax;
3874       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3875                                                             theArgVec + (anArgIter + 1),
3876                                                             aColorMin);
3877       anArgIter += aNbParsed1;
3878       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3879                                                             theArgVec + (anArgIter + 1),
3880                                                             aColorMax);
3881       anArgIter += aNbParsed2;
3882       if (aNbParsed1 == 0
3883        || aNbParsed2 == 0)
3884       {
3885         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3886         return 1;
3887       }
3888
3889       aColorScale->SetColorRange (aColorMin, aColorMax);
3890     }
3891     else if (aFlag == "-reversed"
3892           || aFlag == "-inverted"
3893           || aFlag == "-topdown"
3894           || aFlag == "-bottomup")
3895     {
3896       Standard_Boolean toEnable = Standard_True;
3897       if (anArgIter + 1 < theArgNb
3898        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3899       {
3900         ++anArgIter;
3901       }
3902       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3903     }
3904     else if (aFlag == "-smooth"
3905           || aFlag == "-smoothtransition")
3906     {
3907       Standard_Boolean toEnable = Standard_True;
3908       if (anArgIter + 1 < theArgNb
3909        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3910       {
3911         ++anArgIter;
3912       }
3913       aColorScale->SetSmoothTransition (toEnable);
3914     }
3915     else if (aFlag == "-xy")
3916     {
3917       if (anArgIter + 2 >= theArgNb)
3918       {
3919         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3920         return 1;
3921       }
3922
3923       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3924       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3925       if (!anX.IsIntegerValue()
3926        || !anY.IsIntegerValue())
3927       {
3928         std::cout << "Error: coordinates should be integer values!\n";
3929         return 1;
3930       }
3931
3932       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3933     }
3934     else if (aFlag == "-width"
3935           || aFlag == "-w"
3936           || aFlag == "-breadth")
3937     {
3938       if (anArgIter + 1 >= theArgNb)
3939       {
3940         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3941         return 1;
3942       }
3943
3944       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3945       if (!aBreadth.IsIntegerValue())
3946       {
3947         std::cout << "Error: a width should be an integer value!\n";
3948         return 1;
3949       }
3950       aColorScale->SetBreadth (aBreadth.IntegerValue());
3951     }
3952     else if (aFlag == "-height"
3953           || aFlag == "-h")
3954     {
3955       if (anArgIter + 1 >= theArgNb)
3956       {
3957         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3958         return 1;
3959       }
3960
3961       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3962       if (!aHeight.IsIntegerValue())
3963       {
3964         std::cout << "Error: a width should be an integer value!\n";
3965         return 1;
3966       }
3967       aColorScale->SetHeight (aHeight.IntegerValue());
3968     }
3969     else if (aFlag == "-color")
3970     {
3971       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3972       {
3973         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3974         return 1;
3975       }
3976       else if (anArgIter + 2 >= theArgNb)
3977       {
3978         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3979         return 1;
3980       }
3981
3982       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3983       if (!anInd.IsIntegerValue())
3984       {
3985         std::cout << "Error: Index value should be integer!\n";
3986         return 1;
3987       }
3988       const Standard_Integer anIndex = anInd.IntegerValue();
3989       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3990       {
3991         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3992         return 1;
3993       }
3994
3995       Quantity_Color aColor;
3996       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3997                                                            theArgVec + (anArgIter + 1),
3998                                                            aColor);
3999       if (aNbParsed == 0)
4000       {
4001         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4002         return 1;
4003       }
4004       aColorScale->SetIntervalColor (aColor, anIndex);
4005       aColorScale->SetColorType (Aspect_TOCSD_USER);
4006       anArgIter += aNbParsed;
4007     }
4008     else if (aFlag == "-label")
4009     {
4010       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4011       {
4012         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4013         return 1;
4014       }
4015       else if (anArgIter + 2 >= theArgNb)
4016       {
4017         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4018         return 1;
4019       }
4020
4021       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4022       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4023       {
4024         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4025         return 1;
4026       }
4027
4028       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4029       aColorScale->SetLabel     (aText, anIndex);
4030       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4031       anArgIter += 2;
4032     }
4033     else if (aFlag == "-labelat"
4034           || aFlag == "-labat"
4035           || aFlag == "-labelatborder"
4036           || aFlag == "-labatborder"
4037           || aFlag == "-labelatcenter"
4038           || aFlag == "-labatcenter")
4039     {
4040       Standard_Boolean toEnable = Standard_True;
4041       if (aFlag == "-labelat"
4042        || aFlag == "-labat")
4043       {
4044         Standard_Integer aLabAtBorder = -1;
4045         if (++anArgIter >= theArgNb)
4046         {
4047           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4048           anAtBorder.LowerCase();
4049           if (anAtBorder == "border")
4050           {
4051             aLabAtBorder = 1;
4052           }
4053           else if (anAtBorder == "center")
4054           {
4055             aLabAtBorder = 0;
4056           }
4057         }
4058         if (aLabAtBorder == -1)
4059         {
4060           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4061           return 1;
4062         }
4063         toEnable = (aLabAtBorder == 1);
4064       }
4065       else if (anArgIter + 1 < theArgNb
4066             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4067       {
4068         ++anArgIter;
4069       }
4070       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4071                                   || aFlag == "-labatcenter"
4072                                    ? !toEnable
4073                                    :  toEnable);
4074     }
4075     else if (aFlag == "-colors")
4076     {
4077       Aspect_SequenceOfColor aSeq;
4078       for (;;)
4079       {
4080         Quantity_Color aColor;
4081         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4082                                                              theArgVec + (anArgIter + 1),
4083                                                              aColor);
4084         if (aNbParsed == 0)
4085         {
4086           break;
4087         }
4088         anArgIter += aNbParsed;
4089         aSeq.Append (aColor);
4090       }
4091       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4092       {
4093         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4094                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4095         return 1;
4096       }
4097
4098       aColorScale->SetColors    (aSeq);
4099       aColorScale->SetColorType (Aspect_TOCSD_USER);
4100     }
4101     else if (aFlag == "-labels"
4102           || aFlag == "-freelabels")
4103     {
4104       if (anArgIter + 1 >= theArgNb)
4105       {
4106         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4107         return 1;
4108       }
4109
4110       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4111                                  ? aColorScale->GetNumberOfIntervals() + 1
4112                                  : aColorScale->GetNumberOfIntervals();
4113       if (aFlag == "-freelabels")
4114       {
4115         ++anArgIter;
4116         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4117       }
4118       if (anArgIter + aNbLabels >= theArgNb)
4119       {
4120         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4121         return 1;
4122       }
4123
4124       TColStd_SequenceOfExtendedString aSeq;
4125       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4126       {
4127         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4128       }
4129       aColorScale->SetLabels (aSeq);
4130       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4131     }
4132     else if (aFlag == "-title")
4133     {
4134       if (anArgIter + 1 >= theArgNb)
4135       {
4136         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4137         return 1;
4138       }
4139
4140       Standard_Boolean isTwoArgs = Standard_False;
4141       if (anArgIter + 2 < theArgNb)
4142       {
4143         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4144         aSecondArg.LowerCase();
4145       Standard_DISABLE_DEPRECATION_WARNINGS
4146         if (aSecondArg == "none")
4147         {
4148           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4149           isTwoArgs = Standard_True;
4150         }
4151         else if (aSecondArg == "left")
4152         {
4153           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4154           isTwoArgs = Standard_True;
4155         }
4156         else if (aSecondArg == "right")
4157         {
4158           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4159           isTwoArgs = Standard_True;
4160         }
4161         else if (aSecondArg == "center")
4162         {
4163           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4164           isTwoArgs = Standard_True;
4165         }
4166       Standard_ENABLE_DEPRECATION_WARNINGS
4167       }
4168
4169       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4170       if (isTwoArgs)
4171       {
4172         anArgIter += 1;
4173       }
4174       anArgIter += 1;
4175     }
4176     else if (aFlag == "-demoversion"
4177           || aFlag == "-demo")
4178     {
4179       aColorScale->SetPosition (0, 0);
4180       aColorScale->SetTextHeight (16);
4181       aColorScale->SetRange (0.0, 100.0);
4182       aColorScale->SetNumberOfIntervals (10);
4183       aColorScale->SetBreadth (0);
4184       aColorScale->SetHeight  (0);
4185       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4186       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4187       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4188     }
4189     else if (aFlag == "-findcolor")
4190     {
4191       if (anArgIter + 1 >= theArgNb)
4192       {
4193         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4194         return 1;
4195       }
4196
4197       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4198
4199       if (!anArg1.IsRealValue())
4200       {
4201         std::cout << "Error: the value should be real!\n";
4202         return 1;
4203       }
4204
4205       Quantity_Color aColor;
4206       aColorScale->FindColor (anArg1.RealValue(), aColor);
4207       theDI << Quantity_Color::StringName (aColor.Name());
4208       return 0;
4209     }
4210     else
4211     {
4212       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4213       return 1;
4214     }
4215   }
4216
4217   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4218   aView->Window()->Size (aWinWidth, aWinHeight);
4219   if (aColorScale->GetBreadth() == 0)
4220   {
4221     aColorScale->SetBreadth (aWinWidth);
4222   }
4223   if (aColorScale->GetHeight() == 0)
4224   {
4225     aColorScale->SetHeight (aWinHeight);
4226   }
4227   aColorScale->SetToUpdate();
4228   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4229   return 0;
4230 }
4231
4232 //==============================================================================
4233 //function : VGraduatedTrihedron
4234 //purpose  : Displays or hides a graduated trihedron
4235 //==============================================================================
4236 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4237                                   Quantity_Color& theColor)
4238 {
4239   Quantity_NameOfColor aColorName;
4240   TCollection_AsciiString aVal = theValue;
4241   aVal.UpperCase();
4242   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4243   {
4244     return Standard_False;
4245   }
4246   theColor = Quantity_Color (aColorName);
4247   return Standard_True;
4248 }
4249
4250 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4251 {
4252   if (theArgNum < 2)
4253   {
4254     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4255               << theArgs[0] <<"' for more information.\n";
4256     return 1;  //TCL_ERROR
4257   }
4258
4259   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4260   TCollection_AsciiString aParseKey;
4261   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4262   {
4263     TCollection_AsciiString anArg (theArgs [anArgIt]);
4264
4265     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4266     {
4267       aParseKey = anArg;
4268       aParseKey.Remove (1);
4269       aParseKey.LowerCase();
4270       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4271       continue;
4272     }
4273
4274     if (aParseKey.IsEmpty())
4275     {
4276       continue;
4277     }
4278
4279     aMapOfArgs(aParseKey)->Append (anArg);
4280   }
4281
4282   // Check parameters
4283   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4284        aMapIt.More(); aMapIt.Next())
4285   {
4286     const TCollection_AsciiString& aKey = aMapIt.Key();
4287     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4288
4289     // Bool key, without arguments
4290     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4291         && anArgs->IsEmpty())
4292     {
4293       continue;
4294     }
4295
4296     // One argument
4297     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4298           && anArgs->Length() == 1)
4299     {
4300       continue;
4301     }
4302
4303     // On/off arguments
4304     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4305         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4306         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4307         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4308         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4309     {
4310       continue;
4311     }
4312
4313     // One string argument
4314     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4315           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4316           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4317     {
4318       continue;
4319     }
4320
4321     // One integer argument
4322     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4323           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4324           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4325           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4326          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4327     {
4328       continue;
4329     }
4330
4331     // One real argument
4332     if ( aKey.IsEqual ("arrowlength")
4333          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4334     {
4335       continue;
4336     }
4337
4338     // Two string arguments
4339     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4340          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4341     {
4342       continue;
4343     }
4344
4345     TCollection_AsciiString aLowerKey;
4346     aLowerKey  = "-";
4347     aLowerKey += aKey;
4348     aLowerKey.LowerCase();
4349     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4350     std::cout << "Type help for more information.\n";
4351     return 1;
4352   }
4353
4354   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4355   if (anAISContext.IsNull())
4356   {
4357     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4358     return 1;
4359   }
4360
4361   Standard_Boolean toDisplay = Standard_True;
4362   Quantity_Color aColor;
4363   Graphic3d_GraduatedTrihedron aTrihedronData;
4364   // Process parameters
4365   Handle(TColStd_HSequenceOfAsciiString) aValues;
4366   if (aMapOfArgs.Find ("off", aValues))
4367   {
4368     toDisplay = Standard_False;
4369   }
4370
4371   // AXES NAMES
4372   if (aMapOfArgs.Find ("xname", aValues))
4373   {
4374     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4375   }
4376   if (aMapOfArgs.Find ("yname", aValues))
4377   {
4378     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4379   }
4380   if (aMapOfArgs.Find ("zname", aValues))
4381   {
4382     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4383   }
4384   if (aMapOfArgs.Find ("xdrawname", aValues))
4385   {
4386     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4387   }
4388   if (aMapOfArgs.Find ("ydrawname", aValues))
4389   {
4390     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4391   }
4392   if (aMapOfArgs.Find ("zdrawname", aValues))
4393   {
4394     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4395   }
4396   if (aMapOfArgs.Find ("xnameoffset", aValues))
4397   {
4398     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4399   }
4400   if (aMapOfArgs.Find ("ynameoffset", aValues))
4401   {
4402     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4403   }
4404   if (aMapOfArgs.Find ("znameoffset", aValues))
4405   {
4406     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4407   }
4408
4409   // COLORS
4410   if (aMapOfArgs.Find ("xnamecolor", aValues))
4411   {
4412     if (!GetColor (aValues->Value(1), aColor))
4413     {
4414       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4415       return 1;
4416     }
4417     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4418   }
4419   if (aMapOfArgs.Find ("ynamecolor", aValues))
4420   {
4421     if (!GetColor (aValues->Value(1), aColor))
4422     {
4423       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4424       return 1;
4425     }
4426     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4427   }
4428   if (aMapOfArgs.Find ("znamecolor", aValues))
4429   {
4430     if (!GetColor (aValues->Value(1), aColor))
4431     {
4432       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4433       return 1;
4434     }
4435     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4436   }
4437   if (aMapOfArgs.Find ("xcolor", aValues))
4438   {
4439     if (!GetColor (aValues->Value(1), aColor))
4440     {
4441       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4442       return 1;
4443     }
4444     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4445   }
4446   if (aMapOfArgs.Find ("ycolor", aValues))
4447   {
4448     if (!GetColor (aValues->Value(1), aColor))
4449     {
4450       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4451       return 1;
4452     }
4453     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4454   }
4455   if (aMapOfArgs.Find ("zcolor", aValues))
4456   {
4457     if (!GetColor (aValues->Value(1), aColor))
4458     {
4459       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4460       return 1;
4461     }
4462     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4463   }
4464
4465   // TICKMARKS
4466   if (aMapOfArgs.Find ("xticks", aValues))
4467   {
4468     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4469   }
4470   if (aMapOfArgs.Find ("yticks", aValues))
4471   {
4472     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4473   }
4474   if (aMapOfArgs.Find ("zticks", aValues))
4475   {
4476     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4477   }
4478   if (aMapOfArgs.Find ("xticklength", aValues))
4479   {
4480     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4481   }
4482   if (aMapOfArgs.Find ("yticklength", aValues))
4483   {
4484     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4485   }
4486   if (aMapOfArgs.Find ("zticklength", aValues))
4487   {
4488     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4489   }
4490   if (aMapOfArgs.Find ("xdrawticks", aValues))
4491   {
4492     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4493   }
4494   if (aMapOfArgs.Find ("ydrawticks", aValues))
4495   {
4496     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4497   }
4498   if (aMapOfArgs.Find ("zdrawticks", aValues))
4499   {
4500     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4501   }
4502
4503   // VALUES
4504   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4505   {
4506     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4507   }
4508   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4509   {
4510     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4511   }
4512   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4513   {
4514     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4515   }
4516   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4517   {
4518     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4519   }
4520   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4521   {
4522     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4523   }
4524   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4525   {
4526     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4527   }
4528
4529   // ARROWS
4530   if (aMapOfArgs.Find ("arrowlength", aValues))
4531   {
4532     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4533   }
4534
4535   // FONTS
4536   if (aMapOfArgs.Find ("namefont", aValues))
4537   {
4538     aTrihedronData.SetNamesFont (aValues->Value(1));
4539   }
4540   if (aMapOfArgs.Find ("valuesfont", aValues))
4541   {
4542     aTrihedronData.SetValuesFont (aValues->Value(1));
4543   }
4544
4545   if (aMapOfArgs.Find ("drawgrid", aValues))
4546   {
4547     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4548   }
4549   if (aMapOfArgs.Find ("drawaxes", aValues))
4550   {
4551     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4552   }
4553
4554   // The final step: display of erase trihedron
4555   if (toDisplay)
4556   {
4557     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4558   }
4559   else
4560   {
4561     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4562   }
4563
4564   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4565   ViewerTest::CurrentView()->Redraw();
4566
4567   return 0;
4568 }
4569
4570 //==============================================================================
4571 //function : VTile
4572 //purpose  :
4573 //==============================================================================
4574 static int VTile (Draw_Interpretor& theDI,
4575                   Standard_Integer  theArgNb,
4576                   const char**      theArgVec)
4577 {
4578   Handle(V3d_View) aView = ViewerTest::CurrentView();
4579   if (aView.IsNull())
4580   {
4581     std::cerr << "Error: no active viewer.\n";
4582     return 1;
4583   }
4584
4585   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4586   if (theArgNb < 2)
4587   {
4588     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4589           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4590           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4591     return 0;
4592   }
4593
4594   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4595   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4596   {
4597     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4598     anArg.LowerCase();
4599     if (anArg == "-lowerleft"
4600      || anArg == "-upperleft")
4601     {
4602       if (anArgIter + 3 < theArgNb)
4603       {
4604         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4605         return 1;
4606       }
4607       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4608       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4609       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4610     }
4611     else if (anArg == "-total"
4612           || anArg == "-totalsize"
4613           || anArg == "-viewsize")
4614     {
4615       if (anArgIter + 3 < theArgNb)
4616       {
4617         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4618         return 1;
4619       }
4620       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4621       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4622       if (aTile.TotalSize.x() < 1
4623        || aTile.TotalSize.y() < 1)
4624       {
4625         std::cerr << "Error: total size is incorrect.\n";
4626         return 1;
4627       }
4628     }
4629     else if (anArg == "-tilesize")
4630     {
4631       if (anArgIter + 3 < theArgNb)
4632       {
4633         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4634         return 1;
4635       }
4636
4637       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4638       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4639       if (aTile.TileSize.x() < 1
4640        || aTile.TileSize.y() < 1)
4641       {
4642         std::cerr << "Error: tile size is incorrect.\n";
4643         return 1;
4644       }
4645     }
4646     else if (anArg == "-unset")
4647     {
4648       aView->Camera()->SetTile (Graphic3d_CameraTile());
4649       aView->Redraw();
4650       return 0;
4651     }
4652   }
4653
4654   if (aTile.TileSize.x() < 1
4655    || aTile.TileSize.y() < 1)
4656   {
4657     std::cerr << "Error: tile size is undefined.\n";
4658     return 1;
4659   }
4660   else if (aTile.TotalSize.x() < 1
4661         || aTile.TotalSize.y() < 1)
4662   {
4663     std::cerr << "Error: total size is undefined.\n";
4664     return 1;
4665   }
4666
4667   aView->Camera()->SetTile (aTile);
4668   aView->Redraw();
4669   return 0;
4670 }
4671
4672 //! Format ZLayer ID.
4673 inline const char* formZLayerId (const Standard_Integer theLayerId)
4674 {
4675   switch (theLayerId)
4676   {
4677     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4678     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4679     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4680     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4681     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4682     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4683   }
4684   return "";
4685 }
4686
4687 //! Print the ZLayer information.
4688 inline void printZLayerInfo (Draw_Interpretor& theDI,
4689                              const Graphic3d_ZLayerSettings& theLayer)
4690 {
4691   if (!theLayer.Name().IsEmpty())
4692   {
4693     theDI << "  Name: " << theLayer.Name() << "\n";
4694   }
4695   if (theLayer.IsImmediate())
4696   {
4697     theDI << "  Immediate: TRUE\n";
4698   }
4699   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4700   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
4701   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
4702   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4703   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4704   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4705   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4706   {
4707     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4708   }
4709 }
4710
4711 //==============================================================================
4712 //function : VZLayer
4713 //purpose  : Test z layer operations for v3d viewer
4714 //==============================================================================
4715 static int VZLayer (Draw_Interpretor& theDI,
4716                     Standard_Integer  theArgNb,
4717                     const char**      theArgVec)
4718 {
4719   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4720   if (aContextAIS.IsNull())
4721   {
4722     std::cout << "No active viewer!\n";
4723     return 1;
4724   }
4725
4726   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4727   if (theArgNb < 2)
4728   {
4729     TColStd_SequenceOfInteger aLayers;
4730     aViewer->GetAllZLayers (aLayers);
4731     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4732     {
4733       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4734       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4735       printZLayerInfo (theDI, aSettings);
4736     }
4737     return 1;
4738   }
4739
4740   Standard_Integer anArgIter = 1;
4741   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4742   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4743   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4744   {
4745     ++anArgIter;
4746   }
4747
4748   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4749   if (aFirstArg.IsIntegerValue())
4750   {
4751     ++anArgIter;
4752     aLayerId = aFirstArg.IntegerValue();
4753   }
4754   else
4755   {
4756     aFirstArg.LowerCase();
4757     if (aFirstArg == "default"
4758      || aFirstArg == "def")
4759     {
4760       aLayerId = Graphic3d_ZLayerId_Default;
4761       ++anArgIter;
4762     }
4763     else if (aFirstArg == "top")
4764     {
4765       aLayerId = Graphic3d_ZLayerId_Top;
4766       ++anArgIter;
4767     }
4768     else if (aFirstArg == "topmost")
4769     {
4770       aLayerId = Graphic3d_ZLayerId_Topmost;
4771       ++anArgIter;
4772     }
4773     else if (aFirstArg == "overlay"
4774           || aFirstArg == "toposd")
4775     {
4776       aLayerId = Graphic3d_ZLayerId_TopOSD;
4777       ++anArgIter;
4778     }
4779     else if (aFirstArg == "underlay"
4780           || aFirstArg == "botosd")
4781     {
4782       aLayerId = Graphic3d_ZLayerId_BotOSD;
4783       ++anArgIter;
4784     }
4785     else
4786     {
4787       TColStd_SequenceOfInteger aLayers;
4788       aViewer->GetAllZLayers (aLayers);
4789       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4790       {
4791         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4792         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4793         {
4794           aLayerId = aLayeriter.Value();
4795           ++anArgIter;
4796           break;
4797         }
4798       }
4799     }
4800   }
4801
4802   for (; anArgIter < theArgNb; ++anArgIter)
4803   {
4804     // perform operation
4805     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4806     anArg.LowerCase();
4807     if (anUpdateTool.parseRedrawMode (anArg))
4808     {
4809       //
4810     }
4811     else if (anArg == "-add"
4812           || anArg == "add")
4813     {
4814       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4815       if (!aViewer->AddZLayer (aLayerId))
4816       {
4817         std::cout << "Error: can not add a new z layer!\n";
4818         return 0;
4819       }
4820
4821       theDI << aLayerId;
4822     }
4823     else if (anArg == "-del"
4824           || anArg == "-delete"
4825           || anArg == "del")
4826     {
4827       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4828       {
4829         if (++anArgIter >= theArgNb)
4830         {
4831           std::cout << "Syntax error: id of z layer to remove is missing\n";
4832           return 1;
4833         }
4834
4835         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4836       }
4837
4838       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4839        || aLayerId == Graphic3d_ZLayerId_Default
4840        || aLayerId == Graphic3d_ZLayerId_Top
4841        || aLayerId == Graphic3d_ZLayerId_Topmost
4842        || aLayerId == Graphic3d_ZLayerId_TopOSD
4843        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4844       {
4845         std::cout << "Syntax error: standard Z layer can not be removed\n";
4846         return 1;
4847       }
4848
4849       // move all object displayed in removing layer to default layer
4850       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4851            anObjIter.More(); anObjIter.Next())
4852       {
4853         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
4854         if (aPrs.IsNull()
4855          || aPrs->ZLayer() != aLayerId)
4856         {
4857           continue;
4858         }
4859         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4860       }
4861
4862       if (!aViewer->RemoveZLayer (aLayerId))
4863       {
4864         std::cout << "Z layer can not be removed!\n";
4865       }
4866       else
4867       {
4868         theDI << aLayerId << " ";
4869       }
4870     }
4871     else if (anArg == "-get"
4872           || anArg == "get")
4873     {
4874       TColStd_SequenceOfInteger aLayers;
4875       aViewer->GetAllZLayers (aLayers);
4876       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4877       {
4878         theDI << aLayeriter.Value() << " ";
4879       }
4880
4881       theDI << "\n";
4882     }
4883     else if (anArg == "-name")
4884     {
4885       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4886       {
4887         std::cout << "Syntax error: id of Z layer is missing\n";
4888         return 1;
4889       }
4890
4891       if (++anArgIter >= theArgNb)
4892       {
4893         std::cout << "Syntax error: name is missing\n";
4894         return 1;
4895       }
4896
4897       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4898       aSettings.SetName (theArgVec[anArgIter]);
4899       aViewer->SetZLayerSettings (aLayerId, aSettings);
4900     }
4901     else if (anArg == "-origin")
4902     {
4903       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4904       {
4905         std::cout << "Syntax error: id of Z layer is missing\n";
4906         return 1;
4907       }
4908
4909       if (anArgIter + 2 >= theArgNb)
4910       {
4911         std::cout << "Syntax error: origin coordinates are missing\n";
4912         return 1;
4913       }
4914
4915       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4916       gp_XYZ anOrigin;
4917       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4918       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4919       anOrigin.SetZ (0.0);
4920       if (anArgIter + 3 < theArgNb)
4921       {
4922         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4923         anArgIter += 3;
4924       }
4925       else
4926       {
4927         anArgIter += 2;
4928       }
4929       aSettings.SetOrigin (anOrigin);
4930       aViewer->SetZLayerSettings (aLayerId, aSettings);
4931     }
4932     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4933           && anArgIter + 1 < theArgNb
4934           && (anArg == "-cullingdistance"
4935            || anArg == "-cullingdist"
4936            || anArg == "-culldistance"
4937            || anArg == "-culldist"
4938            || anArg == "-distcull"
4939            || anArg == "-distculling"
4940            || anArg == "-distanceculling"))
4941     {
4942       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4943       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
4944       aSettings.SetCullingDistance (aDist);
4945       aViewer->SetZLayerSettings (aLayerId, aSettings);
4946     }
4947     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4948           && anArgIter + 1 < theArgNb
4949           && (anArg == "-cullingsize"
4950            || anArg == "-cullsize"
4951            || anArg == "-sizecull"
4952            || anArg == "-sizeculling"))
4953     {
4954       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4955       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
4956       aSettings.SetCullingSize (aSize);
4957       aViewer->SetZLayerSettings (aLayerId, aSettings);
4958     }
4959     else if (anArg == "-settings"
4960           || anArg == "settings")
4961     {
4962       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4963       {
4964         if (++anArgIter >= theArgNb)
4965         {
4966           std::cout << "Syntax error: id of Z layer is missing\n";
4967           return 1;
4968         }
4969
4970         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4971       }
4972
4973       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4974       printZLayerInfo (theDI, aSettings);
4975     }
4976     else if (anArg == "-enable"
4977           || anArg == "enable"
4978           || anArg == "-disable"
4979           || anArg == "disable")
4980     {
4981       const Standard_Boolean toEnable = anArg == "-enable"
4982                                      || anArg == "enable";
4983       if (++anArgIter >= theArgNb)
4984       {
4985         std::cout << "Syntax error: option name is missing\n";
4986         return 1;
4987       }
4988
4989       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4990       aSubOp.LowerCase();
4991       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4992       {
4993         if (++anArgIter >= theArgNb)
4994         {
4995           std::cout << "Syntax error: id of Z layer is missing\n";
4996           return 1;
4997         }
4998
4999         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5000       }
5001
5002       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5003       if (aSubOp == "depthtest"
5004        || aSubOp == "test")
5005       {
5006         aSettings.SetEnableDepthTest (toEnable);
5007       }
5008       else if (aSubOp == "depthwrite"
5009             || aSubOp == "write")
5010       {
5011         aSettings.SetEnableDepthWrite (toEnable);
5012       }
5013       else if (aSubOp == "depthclear"
5014             || aSubOp == "clear")
5015       {
5016         aSettings.SetClearDepth (toEnable);
5017       }
5018       else if (aSubOp == "depthoffset"
5019             || aSubOp == "offset")
5020       {
5021         Graphic3d_PolygonOffset aParams;
5022         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5023         if (toEnable)
5024         {
5025           if (anArgIter + 2 >= theArgNb)
5026           {
5027             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5028             return 1;
5029           }
5030
5031           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5032           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5033         }
5034         aSettings.SetPolygonOffset (aParams);
5035       }
5036       else if (aSubOp == "positiveoffset"
5037             || aSubOp == "poffset")
5038       {
5039         if (toEnable)
5040         {
5041           aSettings.SetDepthOffsetPositive();
5042         }
5043         else
5044         {
5045           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5046         }
5047       }
5048       else if (aSubOp == "negativeoffset"
5049             || aSubOp == "noffset")
5050       {
5051         if (toEnable)
5052         {
5053           aSettings.SetDepthOffsetNegative();
5054         }
5055         else
5056         {
5057           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5058         }
5059       }
5060       else if (aSubOp == "textureenv")
5061       {
5062         aSettings.SetEnvironmentTexture (toEnable);
5063       }
5064
5065       aViewer->SetZLayerSettings (aLayerId, aSettings);
5066     }
5067     else
5068     {
5069       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5070       return 1;
5071     }
5072   }
5073
5074   return 0;
5075 }
5076
5077 // The interactive presentation of 2d layer item
5078 // for "vlayerline" command it provides a presentation of
5079 // line with user-defined linewidth, linetype and transparency.
5080 class V3d_LineItem : public AIS_InteractiveObject
5081 {
5082 public:
5083   // CASCADE RTTI
5084   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5085
5086   // constructor
5087   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5088                                Standard_Real X2, Standard_Real Y2,
5089                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5090                                Standard_Real theWidth    = 0.5,
5091                                Standard_Real theTransp   = 1.0);
5092
5093   private:
5094
5095   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5096                 const Handle(Prs3d_Presentation)& thePresentation,
5097                 const Standard_Integer theMode) Standard_OVERRIDE;
5098
5099   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5100                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5101   {}
5102
5103 private:
5104
5105   Standard_Real       myX1, myY1, myX2, myY2;
5106   Aspect_TypeOfLine   myType;
5107   Standard_Real       myWidth;
5108 };
5109
5110 // default constructor for line item
5111 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5112                            Standard_Real X2, Standard_Real Y2,
5113                            Aspect_TypeOfLine theType,
5114                            Standard_Real theWidth,
5115                            Standard_Real theTransp) :
5116   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5117   myType(theType), myWidth(theWidth)
5118 {
5119   SetTransparency (1-theTransp);
5120 }
5121
5122 // render line
5123 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5124                             const Handle(Prs3d_Presentation)& thePresentation,
5125                             const Standard_Integer /*theMode*/)
5126 {
5127   thePresentation->Clear();
5128   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5129   Standard_Integer aWidth, aHeight;
5130   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5131   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5132   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5133   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5134   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5135   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5136   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5137   aGroup->AddPrimitiveArray (aPrim);
5138 }
5139
5140 //=============================================================================
5141 //function : VLayerLine
5142 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5143 //         : linewidth, transparency coefficient
5144 //============================================================================
5145 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5146 {
5147   // get the active view
5148   Handle(V3d_View) aView = ViewerTest::CurrentView();
5149   if (aView.IsNull())
5150   {
5151     di << "Call vinit before!\n";
5152     return 1;
5153   }
5154   else if (argc < 5)
5155   {
5156     di << "Use: " << argv[0];
5157     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5158     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5159     di << "              0 - solid  \n";
5160     di << "              1 - dashed \n";
5161     di << "              2 - dot    \n";
5162     di << "              3 - dashdot\n";
5163     di << " transparency : { 0.0 - 1.0 } \n";
5164     di << "                  0.0 - transparent\n";
5165     di << "                  1.0 - visible    \n";
5166     return 1;
5167   }
5168
5169   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5170   // get the input params
5171   Standard_Real X1 = Draw::Atof(argv[1]);
5172   Standard_Real Y1 = Draw::Atof(argv[2]);
5173   Standard_Real X2 = Draw::Atof(argv[3]);
5174   Standard_Real Y2 = Draw::Atof(argv[4]);
5175
5176   Standard_Real aWidth = 0.5;
5177   Standard_Real aTransparency = 1.0;
5178
5179   // has width
5180   if (argc > 5)
5181     aWidth = Draw::Atof(argv[5]);
5182
5183   // select appropriate line type
5184   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5185   if (argc > 6
5186   && !ViewerTest::ParseLineType (argv[6], aLineType))
5187   {
5188     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5189     return 1;
5190   }
5191
5192   // has transparency
5193   if (argc > 7)
5194   {
5195     aTransparency = Draw::Atof(argv[7]);
5196     if (aTransparency < 0 || aTransparency > 1.0)
5197       aTransparency = 1.0;
5198   }
5199
5200   static Handle (V3d_LineItem) aLine;
5201   if (!aLine.IsNull())
5202   {
5203     aContext->Erase (aLine, Standard_False);
5204   }
5205   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5206                             aLineType, aWidth,
5207                             aTransparency);
5208
5209   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5210   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5211   aLine->SetToUpdate();
5212   aContext->Display (aLine, Standard_True);
5213
5214   return 0;
5215 }
5216
5217
5218 //==============================================================================
5219 //function : VGrid
5220 //purpose  :
5221 //==============================================================================
5222
5223 static int VGrid (Draw_Interpretor& /*theDI*/,
5224                   Standard_Integer  theArgNb,
5225                   const char**      theArgVec)
5226 {
5227   // get the active view
5228   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5229   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5230   if (aView.IsNull() || aViewer.IsNull())
5231   {
5232     std::cerr << "No active view. Please call vinit.\n";
5233     return 1;
5234   }
5235
5236   Aspect_GridType     aType = aViewer->GridType();
5237   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5238   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5239   Standard_Integer anIter = 1;
5240   for (; anIter < theArgNb; ++anIter)
5241   {
5242     const char* aValue = theArgVec[anIter];
5243     if (anUpdateTool.parseRedrawMode (aValue))
5244     {
5245       continue;
5246     }
5247     else if (*aValue == 'r')
5248     {
5249       aType = Aspect_GT_Rectangular;
5250     }
5251     else if (*aValue == 'c')
5252     {
5253       aType = Aspect_GT_Circular;
5254     }
5255     else if (*aValue == 'l')
5256     {
5257       aMode = Aspect_GDM_Lines;
5258     }
5259     else if (*aValue == 'p')
5260     {
5261       aMode = Aspect_GDM_Points;
5262     }
5263     else if (strcmp (aValue, "off" ) == 0)
5264     {
5265       aViewer->DeactivateGrid();
5266       return 0;
5267     }
5268     else
5269     {
5270       break;
5271     }
5272   }
5273
5274   Standard_Integer aTail = (theArgNb - anIter);
5275   if (aTail == 0)
5276   {
5277     aViewer->ActivateGrid (aType, aMode);
5278     return 0;
5279   }
5280   else if (aTail != 2 && aTail != 5)
5281   {
5282     std::cerr << "Incorrect arguments number! Usage:\n"
5283               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5284     return 1;
5285   }
5286
5287   Standard_Real anOriginX, anOriginY, aRotAngle;
5288   if (aType == Aspect_GT_Rectangular)
5289   {
5290     Standard_Real aRStepX, aRStepY;
5291     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5292
5293     anOriginX = Draw::Atof (theArgVec[anIter++]);
5294     anOriginY = Draw::Atof (theArgVec[anIter++]);
5295     if (aTail == 5)
5296     {
5297       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5298       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5299       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5300     }
5301     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5302     aViewer->ActivateGrid (aType, aMode);
5303   }
5304   else if (aType == Aspect_GT_Circular)
5305   {
5306     Standard_Real aRadiusStep;
5307     Standard_Integer aDivisionNumber;
5308     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5309
5310     anOriginX = Draw::Atof (theArgVec[anIter++]);
5311     anOriginY = Draw::Atof (theArgVec[anIter++]);
5312     if (aTail == 5)
5313     {
5314       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5315       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5316       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5317     }
5318
5319     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5320     aViewer->ActivateGrid (aType, aMode);
5321   }
5322
5323   return 0;
5324 }
5325
5326 //==============================================================================
5327 //function : VPriviledgedPlane
5328 //purpose  :
5329 //==============================================================================
5330
5331 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5332                               Standard_Integer  theArgNb,
5333                               const char**      theArgVec)
5334 {
5335   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5336   {
5337     std::cerr << "Error: wrong number of arguments! See usage:\n";
5338     theDI.PrintHelp (theArgVec[0]);
5339     return 1;
5340   }
5341
5342   // get the active viewer
5343   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5344   if (aViewer.IsNull())
5345   {
5346     std::cerr << "Error: no active viewer. Please call vinit.\n";
5347     return 1;
5348   }
5349
5350   if (theArgNb == 1)
5351   {
5352     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5353     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5354     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5355     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5356     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5357           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5358           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5359     return 0;
5360   }
5361
5362   Standard_Integer anArgIdx = 1;
5363   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5364   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5365   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5366   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5367   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5368   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5369
5370   gp_Ax3 aPriviledgedPlane;
5371   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5372   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5373   if (theArgNb > 7)
5374   {
5375     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5376     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5377     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5378     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5379     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5380   }
5381   else
5382   {
5383     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5384   }
5385
5386   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5387
5388   return 0;
5389 }
5390
5391 //==============================================================================
5392 //function : VConvert
5393 //purpose  :
5394 //==============================================================================
5395
5396 static int VConvert (Draw_Interpretor& theDI,
5397                      Standard_Integer  theArgNb,
5398                      const char**      theArgVec)
5399 {
5400   // get the active view
5401   Handle(V3d_View) aView = ViewerTest::CurrentView();
5402   if (aView.IsNull())
5403   {
5404     std::cerr << "Error: no active view. Please call vinit.\n";
5405     return 1;
5406   }
5407
5408   enum { Model, Ray, View, Window, Grid } aMode = Model;
5409
5410   // access coordinate arguments
5411   TColStd_SequenceOfReal aCoord;
5412   Standard_Integer anArgIdx = 1;
5413   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5414   {
5415     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5416     if (!anArg.IsRealValue())
5417     {
5418       break;
5419     }
5420     aCoord.Append (anArg.RealValue());
5421   }
5422
5423   // non-numeric argument too early
5424   if (aCoord.IsEmpty())
5425   {
5426     std::cerr << "Error: wrong number of arguments! See usage:\n";
5427     theDI.PrintHelp (theArgVec[0]);
5428     return 1;
5429   }
5430
5431   // collect all other arguments and options
5432   for (; anArgIdx < theArgNb; ++anArgIdx)
5433   {
5434     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5435     anArg.LowerCase();
5436     if      (anArg == "window") aMode = Window;
5437     else if (anArg == "view")   aMode = View;
5438     else if (anArg == "grid")   aMode = Grid;
5439     else if (anArg == "ray")    aMode = Ray;
5440     else
5441     {
5442       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5443       theDI.PrintHelp (theArgVec[0]);
5444       return 1;
5445     }
5446   }
5447
5448   // complete input checks
5449   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5450       (aCoord.Length() == 2 && theArgNb > 4) ||
5451       (aCoord.Length() == 3 && theArgNb > 5))
5452   {
5453     std::cerr << "Error: wrong number of arguments! See usage:\n";
5454     theDI.PrintHelp (theArgVec[0]);
5455     return 1;
5456   }
5457
5458   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5459   Standard_Integer aXYp[2] = {0, 0};
5460
5461   // convert one-dimensional coordinate
5462   if (aCoord.Length() == 1)
5463   {
5464     switch (aMode)
5465     {
5466       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5467       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5468       default:
5469         std::cerr << "Error: wrong arguments! See usage:\n";
5470         theDI.PrintHelp (theArgVec[0]);
5471         return 1;
5472     }
5473   }
5474
5475   // convert 2D coordinates from projection or view reference space
5476   if (aCoord.Length() == 2)
5477   {
5478     switch (aMode)
5479     {
5480       case Model :
5481         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5482         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5483         return 0;
5484
5485       case View :
5486         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5487         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5488         return 0;
5489
5490       case Window :
5491         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5492         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5493         return 0;
5494
5495       case Grid :
5496         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5497         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5498         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5499         return 0;
5500
5501       case Ray :
5502         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5503                                 (Standard_Integer) aCoord (2),
5504                                 aXYZ[0], aXYZ[1], aXYZ[2],
5505                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5506         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5507         return 0;
5508
5509       default:
5510         std::cerr << "Error: wrong arguments! See usage:\n";
5511         theDI.PrintHelp (theArgVec[0]);
5512         return 1;
5513     }
5514   }
5515
5516   // convert 3D coordinates from view reference space
5517   else if (aCoord.Length() == 3)
5518   {
5519     switch (aMode)
5520     {
5521       case Window :
5522         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5523         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5524         return 0;
5525
5526       case Grid :
5527         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5528         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5529         return 0;
5530
5531       default:
5532         std::cerr << "Error: wrong arguments! See usage:\n";
5533         theDI.PrintHelp (theArgVec[0]);
5534         return 1;
5535     }
5536   }
5537
5538   return 0;
5539 }
5540
5541 //==============================================================================
5542 //function : VFps
5543 //purpose  :
5544 //==============================================================================
5545
5546 static int VFps (Draw_Interpretor& theDI,
5547                  Standard_Integer  theArgNb,
5548                  const char**      theArgVec)
5549 {
5550   // get the active view
5551   Handle(V3d_View) aView = ViewerTest::CurrentView();
5552   if (aView.IsNull())
5553   {
5554     std::cerr << "No active view. Please call vinit.\n";
5555     return 1;
5556   }
5557
5558   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5559   if (aFramesNb <= 0)
5560   {
5561     std::cerr << "Incorrect arguments!\n";
5562     return 1;
5563   }
5564
5565   // the time is meaningless for first call
5566   // due to async OpenGl rendering
5567   aView->Redraw();
5568
5569   // redraw view in loop to estimate average values
5570   OSD_Timer aTimer;
5571   aTimer.Start();
5572   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5573   {
5574     aView->Redraw();
5575   }
5576   aTimer.Stop();
5577   Standard_Real aCpu;
5578   const Standard_Real aTime = aTimer.ElapsedTime();
5579   aTimer.OSD_Chronometer::Show (aCpu);
5580
5581   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5582   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5583
5584   // return statistics
5585   theDI << "FPS: " << aFpsAver << "\n"
5586         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5587
5588   // compute additional statistics in ray-tracing mode
5589   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5590
5591   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5592   {
5593     Standard_Integer aSizeX;
5594     Standard_Integer aSizeY;
5595
5596     aView->Window()->Size (aSizeX, aSizeY);
5597
5598     // 1 shadow ray and 1 secondary ray pew each bounce
5599     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5600
5601     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5602   }
5603
5604   return 0;
5605 }
5606
5607 //==============================================================================
5608 //function : VGlDebug
5609 //purpose  :
5610 //==============================================================================
5611
5612 static int VGlDebug (Draw_Interpretor& theDI,
5613                      Standard_Integer  theArgNb,
5614                      const char**      theArgVec)
5615 {
5616   Handle(OpenGl_GraphicDriver) aDriver;
5617   Handle(V3d_View) aView = ViewerTest::CurrentView();
5618   if (!aView.IsNull())
5619   {
5620     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5621   }
5622   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5623   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5624
5625   if (theArgNb < 2)
5626   {
5627     TCollection_AsciiString aDebActive, aSyncActive;
5628     if (aCaps == NULL)
5629     {
5630       aCaps = aDefCaps;
5631     }
5632     else
5633     {
5634       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5635                                                                   "GL_ARB_debug_output");
5636       aDebActive = isActive ? " (active)" : " (inactive)";
5637       if (isActive)
5638       {
5639         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5640         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5641       }
5642     }
5643
5644     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5645           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5646           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5647           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5648     return 0;
5649   }
5650
5651   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5652   {
5653     Standard_CString        anArg     = theArgVec[anArgIter];
5654     TCollection_AsciiString anArgCase (anArg);
5655     anArgCase.LowerCase();
5656     Standard_Boolean toEnableDebug = Standard_True;
5657     if (anArgCase == "-glsl"
5658      || anArgCase == "-glslwarn"
5659      || anArgCase == "-glslwarns"
5660      || anArgCase == "-glslwarnings")
5661     {
5662       Standard_Boolean toShowWarns = Standard_True;
5663       if (++anArgIter < theArgNb
5664       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5665       {
5666         --anArgIter;
5667       }
5668       aDefCaps->glslWarnings = toShowWarns;
5669       if (aCaps != NULL)
5670       {
5671         aCaps->glslWarnings = toShowWarns;
5672       }
5673     }
5674     else if (anArgCase == "-extra"
5675           || anArgCase == "-extramsg"
5676           || anArgCase == "-extramessages")
5677     {
5678       Standard_Boolean toShow = Standard_True;
5679       if (++anArgIter < theArgNb
5680       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5681       {
5682         --anArgIter;
5683       }
5684       aDefCaps->suppressExtraMsg = !toShow;
5685       if (aCaps != NULL)
5686       {
5687         aCaps->suppressExtraMsg = !toShow;
5688       }
5689     }
5690     else if (anArgCase == "-noextra"
5691           || anArgCase == "-noextramsg"
5692           || anArgCase == "-noextramessages")
5693     {
5694       Standard_Boolean toSuppress = Standard_True;
5695       if (++anArgIter < theArgNb
5696       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5697       {
5698         --anArgIter;
5699       }
5700       aDefCaps->suppressExtraMsg = toSuppress;
5701       if (aCaps != NULL)
5702       {
5703         aCaps->suppressExtraMsg = toSuppress;
5704       }
5705     }
5706     else if (anArgCase == "-sync")
5707     {
5708       Standard_Boolean toSync = Standard_True;
5709       if (++anArgIter < theArgNb
5710       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5711       {
5712         --anArgIter;
5713       }
5714       aDefCaps->contextSyncDebug = toSync;
5715       if (toSync)
5716       {
5717         aDefCaps->contextDebug = Standard_True;
5718       }
5719     }
5720     else if (anArgCase == "-debug")
5721     {
5722       if (++anArgIter < theArgNb
5723       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5724       {
5725         --anArgIter;
5726       }
5727       aDefCaps->contextDebug = toEnableDebug;
5728     }
5729     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5730           && (anArgIter + 1 == theArgNb))
5731     {
5732       // simple alias to turn on almost everything
5733       aDefCaps->contextDebug     = toEnableDebug;
5734       aDefCaps->contextSyncDebug = toEnableDebug;
5735       aDefCaps->glslWarnings     = toEnableDebug;
5736     }
5737     else
5738     {
5739       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5740       return 1;
5741     }
5742   }
5743
5744   return 0;
5745 }
5746
5747 //==============================================================================
5748 //function : VVbo
5749 //purpose  :
5750 //==============================================================================
5751
5752 static int VVbo (Draw_Interpretor& theDI,
5753                  Standard_Integer  theArgNb,
5754                  const char**      theArgVec)
5755 {
5756   const Standard_Boolean toSet    = (theArgNb > 1);
5757   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5758   if (toSet)
5759   {
5760     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5761   }
5762
5763   // get the context
5764   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5765   if (aContextAIS.IsNull())
5766   {
5767     if (!toSet)
5768     {
5769       std::cerr << "No active view!\n";
5770     }
5771     return 1;
5772   }
5773   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5774   if (!aDriver.IsNull())
5775   {
5776     if (!toSet)
5777     {
5778       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5779     }
5780     else
5781     {
5782       aDriver->ChangeOptions().vboDisable = toUseVbo;
5783     }
5784   }
5785
5786   return 0;
5787 }
5788
5789 //==============================================================================
5790 //function : VCaps
5791 //purpose  :
5792 //==============================================================================
5793
5794 static int VCaps (Draw_Interpretor& theDI,
5795                   Standard_Integer  theArgNb,
5796                   const char**      theArgVec)
5797 {
5798   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5799   Handle(OpenGl_GraphicDriver)   aDriver;
5800   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5801   if (!aContext.IsNull())
5802   {
5803     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5804     aCaps   = &aDriver->ChangeOptions();
5805   }
5806
5807   if (theArgNb < 2)
5808   {
5809     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5810     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5811     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5812     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5813     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5814     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5815     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5816     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5817     return 0;
5818   }
5819
5820   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5821   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5822   {
5823     Standard_CString        anArg     = theArgVec[anArgIter];
5824     TCollection_AsciiString anArgCase (anArg);
5825     anArgCase.LowerCase();
5826     if (anUpdateTool.parseRedrawMode (anArg))
5827     {
5828       continue;
5829     }
5830     else if (anArgCase == "-vsync"
5831           || anArgCase == "-swapinterval")
5832     {
5833       Standard_Boolean toEnable = Standard_True;
5834       if (++anArgIter < theArgNb
5835       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5836       {
5837         --anArgIter;
5838       }
5839       aCaps->swapInterval = toEnable;
5840     }
5841     else if (anArgCase == "-ffp")
5842     {
5843       Standard_Boolean toEnable = Standard_True;
5844       if (++anArgIter < theArgNb
5845       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5846       {
5847         --anArgIter;
5848       }
5849       aCaps->ffpEnable = toEnable;
5850     }
5851     else if (anArgCase == "-vbo")
5852     {
5853       Standard_Boolean toEnable = Standard_True;
5854       if (++anArgIter < theArgNb
5855       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5856       {
5857         --anArgIter;
5858       }
5859       aCaps->vboDisable = !toEnable;
5860     }
5861     else if (anArgCase == "-sprite"
5862           || anArgCase == "-sprites")
5863     {
5864       Standard_Boolean toEnable = Standard_True;
5865       if (++anArgIter < theArgNb
5866       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5867       {
5868         --anArgIter;
5869       }
5870       aCaps->pntSpritesDisable = !toEnable;
5871     }
5872     else if (anArgCase == "-softmode")
5873     {
5874       Standard_Boolean toEnable = Standard_True;
5875       if (++anArgIter < theArgNb
5876       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5877       {
5878         --anArgIter;
5879       }
5880       aCaps->contextNoAccel = toEnable;
5881     }
5882     else if (anArgCase == "-winbuffer"
5883           || anArgCase == "-windowbuffer"
5884           || anArgCase == "-usewinbuffer"
5885           || anArgCase == "-usewindowbuffer"
5886           || anArgCase == "-usesystembuffer")
5887     {
5888       Standard_Boolean toEnable = Standard_True;
5889       if (++anArgIter < theArgNb
5890       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5891       {
5892         --anArgIter;
5893       }
5894       aCaps->useSystemBuffer = toEnable;
5895     }
5896     else if (anArgCase == "-accel"
5897           || anArgCase == "-acceleration")
5898     {
5899       Standard_Boolean toEnable = Standard_True;
5900       if (++anArgIter < theArgNb
5901       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5902       {
5903         --anArgIter;
5904       }
5905       aCaps->contextNoAccel = !toEnable;
5906     }
5907     else if (anArgCase == "-compat"
5908           || anArgCase == "-compatprofile"
5909           || anArgCase == "-compatible"
5910           || anArgCase == "-compatibleprofile")
5911     {
5912       Standard_Boolean toEnable = Standard_True;
5913       if (++anArgIter < theArgNb
5914       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5915       {
5916         --anArgIter;
5917       }
5918       aCaps->contextCompatible = toEnable;
5919       if (!aCaps->contextCompatible)
5920       {
5921         aCaps->ffpEnable = Standard_False;
5922       }
5923     }
5924     else if (anArgCase == "-core"
5925           || anArgCase == "-coreprofile")
5926     {
5927       Standard_Boolean toEnable = Standard_True;
5928       if (++anArgIter < theArgNb
5929       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5930       {
5931         --anArgIter;
5932       }
5933       aCaps->contextCompatible = !toEnable;
5934       if (!aCaps->contextCompatible)
5935       {
5936         aCaps->ffpEnable = Standard_False;
5937       }
5938     }
5939     else if (anArgCase == "-stereo"
5940           || anArgCase == "-quadbuffer")
5941     {
5942       Standard_Boolean toEnable = Standard_True;
5943       if (++anArgIter < theArgNb
5944       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5945       {
5946         --anArgIter;
5947       }
5948       aCaps->contextStereo = toEnable;
5949     }
5950     else
5951     {
5952       std::cout << "Error: unknown argument '" << anArg << "'\n";
5953       return 1;
5954     }
5955   }
5956   if (aCaps != &ViewerTest_myDefaultCaps)
5957   {
5958     ViewerTest_myDefaultCaps = *aCaps;
5959   }
5960   return 0;
5961 }
5962
5963 //==============================================================================
5964 //function : VMemGpu
5965 //purpose  :
5966 //==============================================================================
5967
5968 static int VMemGpu (Draw_Interpretor& theDI,
5969                     Standard_Integer  theArgNb,
5970                     const char**      theArgVec)
5971 {
5972   // get the context
5973   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5974   if (aContextAIS.IsNull())
5975   {
5976     std::cerr << "No active view. Please call vinit.\n";
5977     return 1;
5978   }
5979
5980   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5981   if (aDriver.IsNull())
5982   {
5983     std::cerr << "Graphic driver not available.\n";
5984     return 1;
5985   }
5986
5987   Standard_Size aFreeBytes = 0;
5988   TCollection_AsciiString anInfo;
5989   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5990   {
5991     std::cerr << "Information not available.\n";
5992     return 1;
5993   }
5994
5995   if (theArgNb > 1 && *theArgVec[1] == 'f')
5996   {
5997     theDI << Standard_Real (aFreeBytes);
5998   }
5999   else
6000   {
6001     theDI << anInfo;
6002   }
6003
6004   return 0;
6005 }
6006
6007 // ==============================================================================
6008 // function : VReadPixel
6009 // purpose  :
6010 // ==============================================================================
6011 static int VReadPixel (Draw_Interpretor& theDI,
6012                        Standard_Integer  theArgNb,
6013                        const char**      theArgVec)
6014 {
6015   // get the active view
6016   Handle(V3d_View) aView = ViewerTest::CurrentView();
6017   if (aView.IsNull())
6018   {
6019     std::cerr << "No active view. Please call vinit.\n";
6020     return 1;
6021   }
6022   else if (theArgNb < 3)
6023   {
6024     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
6025     return 1;
6026   }
6027
6028   Image_Format         aFormat     = Image_Format_RGBA;
6029   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
6030
6031   Standard_Integer aWidth, aHeight;
6032   aView->Window()->Size (aWidth, aHeight);
6033   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
6034   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
6035   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
6036   {
6037     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
6038     return 1;
6039   }
6040
6041   Standard_Boolean toShowName = Standard_False;
6042   Standard_Boolean toShowHls  = Standard_False;
6043   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6044   {
6045     TCollection_AsciiString aParam (theArgVec[anIter]);
6046     aParam.LowerCase();
6047     if (aParam == "rgb")
6048     {
6049       aFormat     = Image_Format_RGB;
6050       aBufferType = Graphic3d_BT_RGB;
6051     }
6052     else if (aParam == "hls")
6053     {
6054       aFormat     = Image_Format_RGB;
6055       aBufferType = Graphic3d_BT_RGB;
6056       toShowHls   = Standard_True;
6057     }
6058     else if (aParam == "rgbf")
6059     {
6060       aFormat     = Image_Format_RGBF;
6061       aBufferType = Graphic3d_BT_RGB;
6062     }
6063     else if (aParam == "rgba")
6064     {
6065       aFormat     = Image_Format_RGBA;
6066       aBufferType = Graphic3d_BT_RGBA;
6067     }
6068     else if (aParam == "rgbaf")
6069     {
6070       aFormat     = Image_Format_RGBAF;
6071       aBufferType = Graphic3d_BT_RGBA;
6072     }
6073     else if (aParam == "depth")
6074     {
6075       aFormat     = Image_Format_GrayF;
6076       aBufferType = Graphic3d_BT_Depth;
6077     }
6078     else if (aParam == "name")
6079     {
6080       toShowName = Standard_True;
6081     }
6082   }
6083
6084   Image_PixMap anImage;
6085   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6086   {
6087     std::cerr << "Image allocation failed\n";
6088     return 1;
6089   }
6090   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6091   {
6092     std::cerr << "Image dump failed\n";
6093     return 1;
6094   }
6095
6096   // redirect possible warning messages that could have been added by ToPixMap
6097   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6098   // contaminate result of the command
6099   Standard_CString aWarnLog = theDI.Result();
6100   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6101   {
6102     std::cout << aWarnLog << std::endl;
6103   }
6104   theDI.Reset();
6105
6106   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6107   if (toShowName)
6108   {
6109     if (aBufferType == Graphic3d_BT_RGBA)
6110     {
6111       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6112     }
6113     else
6114     {
6115       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6116     }
6117   }
6118   else
6119   {
6120     switch (aBufferType)
6121     {
6122       default:
6123       case Graphic3d_BT_RGB:
6124       {
6125         if (toShowHls)
6126         {
6127           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6128         }
6129         else
6130         {
6131           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6132         }
6133         break;
6134       }
6135       case Graphic3d_BT_RGBA:
6136       {
6137         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6138         break;
6139       }
6140       case Graphic3d_BT_Depth:
6141       {
6142         theDI << aColor.GetRGB().Red();
6143         break;
6144       }
6145     }
6146   }
6147
6148   return 0;
6149 }
6150
6151 //! Auxiliary presentation for an image plane.
6152 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6153 {
6154 public:
6155   //! Main constructor.
6156   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6157                        const Standard_Real theWidth,
6158                        const Standard_Real theHeight,
6159                        const TCollection_AsciiString& theLabel)
6160   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6161   {
6162     SetDisplayMode (0);
6163     SetHilightMode (1);
6164     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6165     {
6166       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6167       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6168       Graphic3d_MaterialAspect aMat;
6169       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6170       aMat.SetAmbient  (1.0);
6171       aMat.SetDiffuse  (1.0);
6172       aMat.SetSpecular (1.0);
6173       aMat.SetEmissive (1.0);
6174       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6175       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6176       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6177       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6178       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6179       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6180       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6181       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6182       aFillAspect->SetFrontMaterial (aMat);
6183       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6184       aFillAspect->SetTextureMapOn();
6185     }
6186     {
6187       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6188       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6189       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6190       myDrawer->SetTextAspect (aTextAspect);
6191     }
6192     {
6193       const gp_Dir aNorm (0.0, 0.0, 1.0);
6194       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6195       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6196       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6197       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6198       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6199       myTris->AddEdge (1);
6200       myTris->AddEdge (2);
6201       myTris->AddEdge (3);
6202       myTris->AddEdge (3);
6203       myTris->AddEdge (2);
6204       myTris->AddEdge (4);
6205
6206       myRect = new Graphic3d_ArrayOfPolylines (4);
6207       myRect->AddVertex (myTris->Vertice (1));
6208       myRect->AddVertex (myTris->Vertice (3));
6209       myRect->AddVertex (myTris->Vertice (4));
6210       myRect->AddVertex (myTris->Vertice (2));
6211     }
6212   }
6213
6214   //! Returns TRUE for accepted display modes.
6215   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6216
6217   //! Compute presentation.
6218   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6219   {
6220     switch (theMode)
6221     {
6222       case 0:
6223       {
6224         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6225         aGroup->AddPrimitiveArray (myTris);
6226         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6227         aGroup->AddPrimitiveArray (myRect);
6228         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6229         return;
6230       }
6231       case 1:
6232       {
6233         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6234         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6235         aGroup->AddPrimitiveArray (myRect);
6236         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6237         return;
6238       }
6239     }
6240   }
6241
6242   //! Compute selection.
6243   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6244   {
6245     if (theMode == 0)
6246     {
6247       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6248       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6249       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6250       theSel->Add (aSensitive);
6251     }
6252   }
6253
6254 private:
6255   Handle(Graphic3d_ArrayOfTriangles) myTris;
6256   Handle(Graphic3d_ArrayOfPolylines) myRect;
6257   TCollection_AsciiString myLabel;
6258   Standard_Real myWidth;
6259   Standard_Real myHeight;
6260 };
6261
6262 //==============================================================================
6263 //function : VDiffImage
6264 //purpose  : The draw-command compares two images.
6265 //==============================================================================
6266
6267 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6268 {
6269   if (theArgNb < 3)
6270   {
6271     std::cout << "Syntax error: not enough arguments.\n";
6272     return 1;
6273   }
6274
6275   Standard_Integer anArgIter = 1;
6276   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6277   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6278   TCollection_AsciiString aDiffImagePath;
6279   Standard_Real    aTolColor        = -1.0;
6280   Standard_Integer toBlackWhite     = -1;
6281   Standard_Integer isBorderFilterOn = -1;
6282   Standard_Boolean isOldSyntax = Standard_False;
6283   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6284   for (; anArgIter < theArgNb; ++anArgIter)
6285   {
6286     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6287     anArg.LowerCase();
6288     if (anArgIter + 1 < theArgNb
6289      && (anArg == "-toleranceofcolor"
6290       || anArg == "-tolerancecolor"
6291       || anArg == "-tolerance"
6292       || anArg == "-toler"))
6293     {
6294       aTolColor = Atof (theArgVec[++anArgIter]);
6295       if (aTolColor < 0.0 || aTolColor > 1.0)
6296       {
6297         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6298         return 1;
6299       }
6300     }
6301     else if (anArg == "-blackwhite")
6302     {
6303       Standard_Boolean toEnable = Standard_True;
6304       if (anArgIter + 1 < theArgNb
6305        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6306       {
6307         ++anArgIter;
6308       }
6309       toBlackWhite = toEnable ? 1 : 0;
6310     }
6311     else if (anArg == "-borderfilter")
6312     {
6313       Standard_Boolean toEnable = Standard_True;
6314       if (anArgIter + 1 < theArgNb
6315        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6316       {
6317         ++anArgIter;
6318       }
6319       isBorderFilterOn = toEnable ? 1 : 0;
6320     }
6321     else if (anArg == "-exitonclose")
6322     {
6323       Draw_ToExitOnCloseView = true;
6324       if (anArgIter + 1 < theArgNb
6325        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6326       {
6327         ++anArgIter;
6328       }
6329     }
6330     else if (anArg == "-closeonescape"
6331           || anArg == "-closeonesc")
6332     {
6333       Draw_ToCloseViewOnEsc = true;
6334       if (anArgIter + 1 < theArgNb
6335        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6336       {
6337         ++anArgIter;
6338       }
6339     }
6340     else if (anArgIter + 3 < theArgNb
6341           && anArg == "-display")
6342     {
6343       aViewName   = theArgVec[++anArgIter];
6344       aPrsNameRef = theArgVec[++anArgIter];
6345       aPrsNameNew = theArgVec[++anArgIter];
6346       if (anArgIter + 1 < theArgNb
6347       && *theArgVec[anArgIter + 1] != '-')
6348       {
6349         aPrsNameDiff = theArgVec[++anArgIter];
6350       }
6351     }
6352     else if (aTolColor < 0.0
6353           && anArg.IsRealValue())
6354     {
6355       isOldSyntax = Standard_True;
6356       aTolColor = anArg.RealValue();
6357       if (aTolColor < 0.0 || aTolColor > 1.0)
6358       {
6359         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6360         return 1;
6361       }
6362     }
6363     else if (isOldSyntax
6364           && toBlackWhite == -1
6365           && (anArg == "0" || anArg == "1"))
6366     {
6367       toBlackWhite = anArg == "1" ? 1 : 0;
6368     }
6369     else if (isOldSyntax
6370           && isBorderFilterOn == -1
6371           && (anArg == "0" || anArg == "1"))
6372     {
6373       isBorderFilterOn = anArg == "1" ? 1 : 0;
6374     }
6375     else if (aDiffImagePath.IsEmpty())
6376     {
6377       aDiffImagePath = theArgVec[anArgIter];
6378     }
6379     else
6380     {
6381       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6382       return 1;
6383     }
6384   }
6385
6386   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6387   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6388   if (!anImgRef->Load (anImgPathRef))
6389   {
6390     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6391     return 1;
6392   }
6393   if (!anImgNew->Load (anImgPathNew))
6394   {
6395     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6396     return 1;
6397   }
6398
6399   // compare the images
6400   Image_Diff aComparer;
6401   Standard_Integer aDiffColorsNb = -1;
6402   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6403   {
6404     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6405     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6406     aDiffColorsNb = aComparer.Compare();
6407     theDI << aDiffColorsNb << "\n";
6408   }
6409
6410   // save image of difference
6411   Handle(Image_AlienPixMap) aDiff;
6412   if (aDiffColorsNb > 0
6413   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6414   {
6415     aDiff = new Image_AlienPixMap();
6416     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6417     {
6418       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6419       return 1;
6420     }
6421     aComparer.SaveDiffImage (*aDiff);
6422     if (!aDiffImagePath.IsEmpty()
6423      && !aDiff->Save (aDiffImagePath))
6424     {
6425       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6426       return 1;
6427     }
6428   }
6429
6430   if (aViewName.IsEmpty())
6431   {
6432     return 0;
6433   }
6434
6435   ViewerTest_Names aViewNames (aViewName);
6436   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6437   {
6438     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6439     theDI.Eval (aCommand.ToCString());
6440   }
6441
6442   Standard_Integer aPxLeft = 0;
6443   Standard_Integer aPxTop  = 0;
6444   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6445   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6446                               ? int(anImgRef->SizeY() * 2)
6447                               : int(anImgRef->SizeY());
6448   TCollection_AsciiString aDisplayName;
6449   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
6450                                                             aViewName, aDisplayName);
6451
6452   Standard_Real aRatio = anImgRef->Ratio();
6453   Standard_Real aSizeX = 1.0;
6454   Standard_Real aSizeY = aSizeX / aRatio;
6455   {
6456     OSD_Path aPath (anImgPathRef);
6457     TCollection_AsciiString aLabelRef;
6458     if (!aPath.Name().IsEmpty())
6459     {
6460       aLabelRef = aPath.Name() + aPath.Extension();
6461     }
6462     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6463
6464     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6465     gp_Trsf aTrsfRef;
6466     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6467     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6468     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6469   }
6470   {
6471     OSD_Path aPath (anImgPathNew);
6472     TCollection_AsciiString aLabelNew;
6473     if (!aPath.Name().IsEmpty())
6474     {
6475       aLabelNew = aPath.Name() + aPath.Extension();
6476     }
6477     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6478
6479     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6480     gp_Trsf aTrsfRef;
6481     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6482     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6483     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6484   }
6485   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6486   if (!aDiff.IsNull())
6487   {
6488     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6489     gp_Trsf aTrsfDiff;
6490     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6491     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6492   }
6493   if (!aPrsNameDiff.IsEmpty())
6494   {
6495     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6496   }
6497   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6498   ViewerTest::CurrentView()->FitAll();
6499   return 0;
6500 }
6501
6502 //=======================================================================
6503 //function : VSelect
6504 //purpose  : Emulates different types of selection by mouse:
6505 //           1) single click selection
6506 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6507 //           3) selection with polygon having corners at
6508 //           pixel positions (x1,y1),...,(xn,yn)
6509 //           4) any of these selections with shift button pressed
6510 //=======================================================================
6511 static Standard_Integer VSelect (Draw_Interpretor& di,
6512                                  Standard_Integer argc,
6513                                  const char ** argv)
6514 {
6515   if(argc < 3)
6516   {
6517     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6518     return 1;
6519   }
6520
6521   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6522   if(myAIScontext.IsNull())
6523   {
6524     di << "use 'vinit' command before " << argv[0] << "\n";
6525     return 1;
6526   }
6527
6528   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6529   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6530   TCollection_AsciiString anArg;
6531   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6532   anArg.LowerCase();
6533   if (anArg == "-allowoverlap")
6534   {
6535     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6536       : argc == 7;
6537     if (!isValidated)
6538     {
6539       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6540       return 1;
6541     }
6542
6543     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6544     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6545     aCoordsNb -= 2;
6546   }
6547
6548   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6549   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6550   if(aCoordsNb == 2)
6551   {
6552     if(isShiftSelection)
6553       aCurrentEventManager->ShiftSelect();
6554     else
6555       aCurrentEventManager->Select();
6556   }
6557   else if(aCoordsNb == 4)
6558   {
6559     if(isShiftSelection)
6560       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6561     else
6562       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6563   }
6564   else
6565   {
6566     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6567
6568     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6569       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6570
6571     if(isShiftSelection)
6572       aCurrentEventManager->ShiftSelect(aPolyline);
6573     else
6574       aCurrentEventManager->Select(aPolyline);
6575   }
6576   return 0;
6577 }
6578
6579 //=======================================================================
6580 //function : VMoveTo
6581 //purpose  : Emulates cursor movement to defined pixel position
6582 //=======================================================================
6583 static Standard_Integer VMoveTo (Draw_Interpretor& ,
6584                                 Standard_Integer theNbArgs,
6585                                 const char**     theArgVec)
6586 {
6587   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
6588   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
6589   if (aContext.IsNull())
6590   {
6591     std::cout << "Error: no active View\n";
6592     return 1;
6593   }
6594
6595   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
6596   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
6597   {
6598     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
6599     anArgStr.LowerCase();
6600     if (anArgStr == "-reset"
6601      || anArgStr == "-clear")
6602     {
6603       if (anArgIter + 1 < theNbArgs)
6604       {
6605         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
6606         return 1;
6607       }
6608
6609       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
6610                                        && aContext->CurrentViewer()->GridEcho();
6611       if (toEchoGrid)
6612       {
6613         aContext->CurrentViewer()->HideGridEcho (aView);
6614       }
6615       if (aContext->ClearDetected() || toEchoGrid)
6616       {
6617         aContext->CurrentViewer()->RedrawImmediate();
6618       }
6619       return 0;
6620     }
6621     else if (aMousePos.x() == IntegerLast()
6622           && anArgStr.IsIntegerValue())
6623     {
6624       aMousePos.x() = anArgStr.IntegerValue();
6625     }
6626     else if (aMousePos.y() == IntegerLast()
6627           && anArgStr.IsIntegerValue())
6628     {
6629       aMousePos.y() = anArgStr.IntegerValue();
6630     }
6631     else
6632     {
6633       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6634       return 1;
6635     }
6636   }
6637
6638   if (aMousePos.x() == IntegerLast()
6639    || aMousePos.y() == IntegerLast())
6640   {
6641     std::cout << "Syntax error: wrong number of arguments\n";
6642     return 1;
6643   }
6644
6645   ViewerTest::CurrentEventManager()->MoveTo (aMousePos.x(), aMousePos.y());
6646   return 0;
6647 }
6648
6649 namespace
6650 {
6651   //! Global map storing all animations registered in ViewerTest.
6652   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6653
6654   //! The animation calling the Draw Harness command.
6655   class ViewerTest_AnimationProc : public AIS_Animation
6656   {
6657   public:
6658
6659     //! Main constructor.
6660     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6661                               Draw_Interpretor* theDI,
6662                               const TCollection_AsciiString& theCommand)
6663     : AIS_Animation (theAnimationName),
6664       myDrawInter(theDI),
6665       myCommand  (theCommand)
6666     {
6667       //
6668     }
6669
6670   protected:
6671
6672     //! Evaluate the command.
6673     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6674     {
6675       TCollection_AsciiString aCmd = myCommand;
6676       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6677       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6678       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6679       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6680       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6681       myDrawInter->Eval (aCmd.ToCString());
6682     }
6683
6684     //! Find the keyword in the command and replace it with value.
6685     //! @return the position of the keyword to pass value
6686     void replace (TCollection_AsciiString&       theCmd,
6687                   const TCollection_AsciiString& theKey,
6688                   const TCollection_AsciiString& theVal)
6689     {
6690       TCollection_AsciiString aCmd (theCmd);
6691       aCmd.LowerCase();
6692       const Standard_Integer aPos = aCmd.Search (theKey);
6693       if (aPos == -1)
6694       {
6695         return;
6696       }
6697
6698       TCollection_AsciiString aPart1, aPart2;
6699       Standard_Integer aPart1To = aPos - 1;
6700       if (aPart1To >= 1
6701        && aPart1To <= theCmd.Length())
6702       {
6703         aPart1 = theCmd.SubString (1, aPart1To);
6704       }
6705
6706       Standard_Integer aPart2From = aPos + theKey.Length();
6707       if (aPart2From >= 1
6708        && aPart2From <= theCmd.Length())
6709       {
6710         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6711       }
6712
6713       theCmd = aPart1 + theVal + aPart2;
6714     }
6715
6716   protected:
6717
6718     Draw_Interpretor*       myDrawInter;
6719     TCollection_AsciiString myCommand;
6720
6721   };
6722
6723   //! Replace the animation with the new one.
6724   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6725                                 Handle(AIS_Animation)&       theAnimation,
6726                                 const Handle(AIS_Animation)& theAnimationNew)
6727   {
6728     theAnimationNew->CopyFrom (theAnimation);
6729     if (!theParentAnimation.IsNull())
6730     {
6731       theParentAnimation->Replace (theAnimation, theAnimationNew);
6732     }
6733     else
6734     {
6735       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6736       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6737     }
6738     theAnimation = theAnimationNew;
6739   }
6740
6741   //! Parse the point.
6742   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6743   {
6744     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6745     if (!anXYZ[0].IsRealValue()
6746      || !anXYZ[1].IsRealValue()
6747      || !anXYZ[2].IsRealValue())
6748     {
6749       return Standard_False;
6750     }
6751
6752     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6753     return Standard_True;
6754   }
6755
6756   //! Parse the quaternion.
6757   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6758   {
6759     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6760     if (!anXYZW[0].IsRealValue()
6761      || !anXYZW[1].IsRealValue()
6762      || !anXYZW[2].IsRealValue()
6763      || !anXYZW[3].IsRealValue())
6764     {
6765       return Standard_False;
6766     }
6767
6768     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6769     return Standard_True;
6770   }
6771
6772   //! Auxiliary class for flipping image upside-down.
6773   class ImageFlipper
6774   {
6775   public:
6776
6777     //! Empty constructor.
6778     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6779
6780     //! Perform flipping.
6781     Standard_Boolean FlipY (Image_PixMap& theImage)
6782     {
6783       if (theImage.IsEmpty()
6784        || theImage.SizeX() == 0
6785        || theImage.SizeY() == 0)
6786       {
6787         return Standard_False;
6788       }
6789
6790       const Standard_Size aRowSize = theImage.SizeRowBytes();
6791       if (myTmp.Size() < aRowSize
6792       && !myTmp.Allocate (aRowSize))
6793       {
6794         return Standard_False;
6795       }
6796
6797       // for odd height middle row should be left as is
6798       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6799       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6800       {
6801         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6802         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6803         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
6804         memcpy (aTop,               aBot,         aRowSize);
6805         memcpy (aBot,               myTmp.Data(), aRowSize);
6806       }
6807       return Standard_True;
6808     }
6809
6810   private:
6811     NCollection_Buffer myTmp;
6812   };
6813
6814 }
6815
6816 //=================================================================================================
6817 //function : VViewParams
6818 //purpose  : Gets or sets AIS View characteristics
6819 //=================================================================================================
6820 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6821 {
6822   Handle(V3d_View) aView = ViewerTest::CurrentView();
6823   if (aView.IsNull())
6824   {
6825     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6826     return 1;
6827   }
6828
6829   Standard_Boolean toSetProj     = Standard_False;
6830   Standard_Boolean toSetUp       = Standard_False;
6831   Standard_Boolean toSetAt       = Standard_False;
6832   Standard_Boolean toSetEye      = Standard_False;
6833   Standard_Boolean toSetScale    = Standard_False;
6834   Standard_Boolean toSetSize     = Standard_False;
6835   Standard_Boolean toSetCenter2d = Standard_False;
6836   Standard_Real    aViewScale = aView->Scale();
6837   Standard_Real    aViewSize  = 1.0;
6838   Graphic3d_Vec2i  aCenter2d;
6839   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6840   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6841   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6842   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6843   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6844   if (theArgsNb == 1)
6845   {
6846     // print all of the available view parameters
6847     char aText[4096];
6848     Sprintf (aText,
6849              "Scale: %g\n"
6850              "Proj:  %12g %12g %12g\n"
6851              "Up:    %12g %12g %12g\n"
6852              "At:    %12g %12g %12g\n"
6853              "Eye:   %12g %12g %12g\n",
6854               aViewScale,
6855               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6856               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6857               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6858               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6859     theDi << aText;
6860     return 0;
6861   }
6862
6863   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6864   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6865   {
6866     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6867     anArg.LowerCase();
6868     if (anUpdateTool.parseRedrawMode (anArg))
6869     {
6870       continue;
6871     }
6872     else if (anArg == "-cmd"
6873           || anArg == "-command"
6874           || anArg == "-args")
6875     {
6876       char aText[4096];
6877       Sprintf (aText,
6878                "-scale %g "
6879                "-proj %g %g %g "
6880                "-up %g %g %g "
6881                "-at %g %g %g\n",
6882                 aViewScale,
6883                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6884                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6885                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6886       theDi << aText;
6887     }
6888     else if (anArg == "-scale"
6889           || anArg == "-size")
6890     {
6891       if (anArgIter + 1 < theArgsNb
6892        && *theArgVec[anArgIter + 1] != '-')
6893       {
6894         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6895         if (aValueArg.IsRealValue())
6896         {
6897           ++anArgIter;
6898           if (anArg == "-scale")
6899           {
6900             toSetScale = Standard_True;
6901             aViewScale = aValueArg.RealValue();
6902           }
6903           else if (anArg == "-size")
6904           {
6905             toSetSize = Standard_True;
6906             aViewSize = aValueArg.RealValue();
6907           }
6908           continue;
6909         }
6910       }
6911       if (anArg == "-scale")
6912       {
6913         theDi << "Scale: " << aView->Scale() << "\n";
6914       }
6915       else if (anArg == "-size")
6916       {
6917         Graphic3d_Vec2d aSizeXY;
6918         aView->Size (aSizeXY.x(), aSizeXY.y());
6919         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6920       }
6921     }
6922     else if (anArg == "-eye"
6923           || anArg == "-at"
6924           || anArg == "-up"
6925           || anArg == "-proj")
6926     {
6927       if (anArgIter + 3 < theArgsNb)
6928       {
6929         gp_XYZ anXYZ;
6930         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6931         {
6932           anArgIter += 3;
6933           if (anArg == "-eye")
6934           {
6935             toSetEye = Standard_True;
6936             aViewEye = anXYZ;
6937           }
6938           else if (anArg == "-at")
6939           {
6940             toSetAt = Standard_True;
6941             aViewAt = anXYZ;
6942           }
6943           else if (anArg == "-up")
6944           {
6945             toSetUp = Standard_True;
6946             aViewUp = anXYZ;
6947           }
6948           else if (anArg == "-proj")
6949           {
6950             toSetProj = Standard_True;
6951             aViewProj = anXYZ;
6952           }
6953           continue;
6954         }
6955       }
6956
6957       if (anArg == "-eye")
6958       {
6959         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6960       }
6961       else if (anArg == "-at")
6962       {
6963         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6964       }
6965       else if (anArg == "-up")
6966       {
6967         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6968       }
6969       else if (anArg == "-proj")
6970       {
6971         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6972       }
6973     }
6974     else if (anArg == "-center")
6975     {
6976       if (anArgIter + 2 < theArgsNb)
6977       {
6978         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6979         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6980         if (anX.IsIntegerValue()
6981          && anY.IsIntegerValue())
6982         {
6983           toSetCenter2d = Standard_True;
6984           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6985         }
6986       }
6987     }
6988     else
6989     {
6990       std::cout << "Syntax error at '" << anArg << "'\n";
6991       return 1;
6992     }
6993   }
6994
6995   // change view parameters in proper order
6996   if (toSetScale)
6997   {
6998     aView->SetScale (aViewScale);
6999   }
7000   if (toSetSize)
7001   {
7002     aView->SetSize (aViewSize);
7003   }
7004   if (toSetEye)
7005   {
7006     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7007   }
7008   if (toSetAt)
7009   {
7010     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7011   }
7012   if (toSetProj)
7013   {
7014     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7015   }
7016   if (toSetUp)
7017   {
7018     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7019   }
7020   if (toSetCenter2d)
7021   {
7022     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
7023   }
7024
7025   return 0;
7026 }
7027
7028 //==============================================================================
7029 //function : V2DMode
7030 //purpose  :
7031 //==============================================================================
7032 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7033 {
7034   bool is2dMode = true;
7035   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7036   if (aV3dView.IsNull())
7037   {
7038     std::cout << "Error: no active view.\n";
7039     return 1;
7040   }
7041   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7042   {
7043     const TCollection_AsciiString anArg = theArgVec[anArgIt];
7044     TCollection_AsciiString anArgCase = anArg;
7045     anArgCase.LowerCase();
7046     if (anArgIt + 1 < theArgsNb
7047      && anArgCase == "-name")
7048     {
7049       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
7050       TCollection_AsciiString aViewName = aViewNames.GetViewName();
7051       if (!ViewerTest_myViews.IsBound1 (aViewName))
7052       {
7053         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
7054         return 1;
7055       }
7056       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7057     }
7058     else if (anArgCase == "-mode")
7059     {
7060       if (anArgIt + 1 < theArgsNb
7061        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
7062       {
7063         ++anArgIt;
7064       }
7065     }
7066     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
7067     {
7068       //
7069     }
7070     else
7071     {
7072       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
7073       return 1;
7074     }
7075   }
7076
7077   aV3dView->SetView2DMode (is2dMode);
7078   return 0;
7079 }
7080
7081 //==============================================================================
7082 //function : VAnimation
7083 //purpose  :
7084 //==============================================================================
7085 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7086                                     Standard_Integer  theArgNb,
7087                                     const char**      theArgVec)
7088 {
7089   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7090   if (theArgNb < 2)
7091   {
7092     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7093          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7094     {
7095       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
7096     }
7097     return 0;
7098   }
7099   if (aCtx.IsNull())
7100   {
7101     std::cout << "Error: no active view\n";
7102     return 1;
7103   }
7104
7105   Standard_Integer anArgIter = 1;
7106   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7107   if (aNameArg.IsEmpty())
7108   {
7109     std::cout << "Syntax error: animation name is not defined.\n";
7110     return 1;
7111   }
7112
7113   TCollection_AsciiString aNameArgLower = aNameArg;
7114   aNameArgLower.LowerCase();
7115   if (aNameArgLower == "-reset"
7116    || aNameArgLower == "-clear")
7117   {
7118     ViewerTest_AnimationTimelineMap.Clear();
7119     return 0;
7120   }
7121   else if (aNameArg.Value (1) == '-')
7122   {
7123     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
7124     return 1;
7125   }
7126
7127   const char* aNameSplitter = "/";
7128   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7129   if (aSplitPos == -1)
7130   {
7131     aNameSplitter = ".";
7132     aSplitPos = aNameArg.Search (aNameSplitter);
7133   }
7134
7135   // find existing or create a new animation by specified name within syntax "parent.child".
7136   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
7137   for (; !aNameArg.IsEmpty();)
7138   {
7139     TCollection_AsciiString aNameParent;
7140     if (aSplitPos != -1)
7141     {
7142       if (aSplitPos == aNameArg.Length())
7143       {
7144         std::cout << "Syntax error: animation name is not defined.\n";
7145         return 1;
7146       }
7147
7148       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7149       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7150
7151       aSplitPos = aNameArg.Search (aNameSplitter);
7152     }
7153     else
7154     {
7155       aNameParent = aNameArg;
7156       aNameArg.Clear();
7157     }
7158
7159     if (anAnimation.IsNull())
7160     {
7161       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7162       {
7163         anAnimation = new AIS_Animation (aNameParent);
7164         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7165       }
7166       aRootAnimation = anAnimation;
7167     }
7168     else
7169     {
7170       aParentAnimation = anAnimation;
7171       anAnimation = aParentAnimation->Find (aNameParent);
7172       if (anAnimation.IsNull())
7173       {
7174         anAnimation = new AIS_Animation (aNameParent);
7175         aParentAnimation->Add (anAnimation);
7176       }
7177     }
7178   }
7179
7180   if (anArgIter >= theArgNb)
7181   {
7182     // just print the list of children
7183     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7184     {
7185       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7186     }
7187     return 0;
7188   }
7189
7190   // animation parameters
7191   Standard_Boolean toPlay = Standard_False;
7192   Standard_Real aPlaySpeed     = 1.0;
7193   Standard_Real aPlayStartTime = anAnimation->StartPts();
7194   Standard_Real aPlayDuration  = anAnimation->Duration();
7195   Standard_Boolean isFreeCamera = Standard_False;
7196   Standard_Boolean isLockLoop   = Standard_False;
7197
7198   // video recording parameters
7199   TCollection_AsciiString aRecFile;
7200   Image_VideoParams aRecParams;
7201
7202   Handle(V3d_View) aView = ViewerTest::CurrentView();
7203   for (; anArgIter < theArgNb; ++anArgIter)
7204   {
7205     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7206     anArg.LowerCase();
7207     // general options
7208     if (anArg == "-reset"
7209      || anArg == "-clear")
7210     {
7211       anAnimation->Clear();
7212     }
7213     else if (anArg == "-remove"
7214           || anArg == "-del"
7215           || anArg == "-delete")
7216     {
7217       if (!aParentAnimation.IsNull())
7218       {
7219         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7220       }
7221       else
7222       {
7223         aParentAnimation->Remove (anAnimation);
7224       }
7225     }
7226     // playback options
7227     else if (anArg == "-play")
7228     {
7229       toPlay = Standard_True;
7230       if (++anArgIter < theArgNb)
7231       {
7232         if (*theArgVec[anArgIter] == '-')
7233         {
7234           --anArgIter;
7235           continue;
7236         }
7237         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7238
7239         if (++anArgIter < theArgNb)
7240         {
7241           if (*theArgVec[anArgIter] == '-')
7242           {
7243             --anArgIter;
7244             continue;
7245           }
7246           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7247         }
7248       }
7249     }
7250     else if (anArg == "-resume")
7251     {
7252       toPlay = Standard_True;
7253       aPlayStartTime = anAnimation->ElapsedTime();
7254       if (++anArgIter < theArgNb)
7255       {
7256         if (*theArgVec[anArgIter] == '-')
7257         {
7258           --anArgIter;
7259           continue;
7260         }
7261
7262         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7263       }
7264     }
7265     else if (anArg == "-playspeed"
7266           || anArg == "-speed")
7267     {
7268       if (++anArgIter >= theArgNb)
7269       {
7270         std::cout << "Syntax error at " << anArg << ".\n";
7271         return 1;
7272       }
7273       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7274     }
7275     else if (anArg == "-lock"
7276           || anArg == "-lockloop"
7277           || anArg == "-playlockloop")
7278     {
7279       isLockLoop = Standard_True;
7280     }
7281     else if (anArg == "-freecamera"
7282           || anArg == "-playfreecamera"
7283           || anArg == "-freelook")
7284     {
7285       isFreeCamera = Standard_True;
7286     }
7287     // video recodring options
7288     else if (anArg == "-rec"
7289           || anArg == "-record")
7290     {
7291       if (++anArgIter >= theArgNb)
7292       {
7293         std::cout << "Syntax error at " << anArg << ".\n";
7294         return 1;
7295       }
7296
7297       aRecFile = theArgVec[anArgIter];
7298       if (aRecParams.FpsNum <= 0)
7299       {
7300         aRecParams.FpsNum = 24;
7301       }
7302
7303       if (anArgIter + 2 < theArgNb
7304       && *theArgVec[anArgIter + 1] != '-'
7305       && *theArgVec[anArgIter + 2] != '-')
7306       {
7307         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7308         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7309         if (aWidthArg .IsIntegerValue()
7310          && aHeightArg.IsIntegerValue())
7311         {
7312           aRecParams.Width  = aWidthArg .IntegerValue();
7313           aRecParams.Height = aHeightArg.IntegerValue();
7314           anArgIter += 2;
7315         }
7316       }
7317     }
7318     else if (anArg == "-fps")
7319     {
7320       if (++anArgIter >= theArgNb)
7321       {
7322         std::cout << "Syntax error at " << anArg << ".\n";
7323         return 1;
7324       }
7325
7326       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7327       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7328       if (aSplitIndex == 0)
7329       {
7330         aRecParams.FpsNum = aFpsArg.IntegerValue();
7331       }
7332       else
7333       {
7334         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7335         aFpsArg.Split (aFpsArg.Length() - 1);
7336         const TCollection_AsciiString aNumStr = aFpsArg;
7337         aRecParams.FpsNum = aNumStr.IntegerValue();
7338         aRecParams.FpsDen = aDenStr.IntegerValue();
7339         if (aRecParams.FpsDen < 1)
7340         {
7341           std::cout << "Syntax error at " << anArg << ".\n";
7342           return 1;
7343         }
7344       }
7345     }
7346     else if (anArg == "-format")
7347     {
7348       if (++anArgIter >= theArgNb)
7349       {
7350         std::cout << "Syntax error at " << anArg << ".\n";
7351         return 1;
7352       }
7353       aRecParams.Format = theArgVec[anArgIter];
7354     }
7355     else if (anArg == "-pix_fmt"
7356           || anArg == "-pixfmt"
7357           || anArg == "-pixelformat")
7358     {
7359       if (++anArgIter >= theArgNb)
7360       {
7361         std::cout << "Syntax error at " << anArg << ".\n";
7362         return 1;
7363       }
7364       aRecParams.PixelFormat = theArgVec[anArgIter];
7365     }
7366     else if (anArg == "-codec"
7367           || anArg == "-vcodec"
7368           || anArg == "-videocodec")
7369     {
7370       if (++anArgIter >= theArgNb)
7371       {
7372         std::cout << "Syntax error at " << anArg << ".\n";
7373         return 1;
7374       }
7375       aRecParams.VideoCodec = theArgVec[anArgIter];
7376     }
7377     else if (anArg == "-crf"
7378           || anArg == "-preset"
7379           || anArg == "-qp")
7380     {
7381       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7382       if (++anArgIter >= theArgNb)
7383       {
7384         std::cout << "Syntax error at " << anArg << ".\n";
7385         return 1;
7386       }
7387
7388       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7389     }
7390     // animation definition options
7391     else if (anArg == "-start"
7392           || anArg == "-starttime"
7393           || anArg == "-startpts")
7394     {
7395       if (++anArgIter >= theArgNb)
7396       {
7397         std::cout << "Syntax error at " << anArg << ".\n";
7398         return 1;
7399       }
7400
7401       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7402       aRootAnimation->UpdateTotalDuration();
7403     }
7404     else if (anArg == "-end"
7405           || anArg == "-endtime"
7406           || anArg == "-endpts")
7407     {
7408       if (++anArgIter >= theArgNb)
7409       {
7410         std::cout << "Syntax error at " << anArg << ".\n";
7411         return 1;
7412       }
7413
7414       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7415       aRootAnimation->UpdateTotalDuration();
7416     }
7417     else if (anArg == "-dur"
7418           || anArg == "-duration")
7419     {
7420       if (++anArgIter >= theArgNb)
7421       {
7422         std::cout << "Syntax error at " << anArg << ".\n";
7423         return 1;
7424       }
7425
7426       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7427       aRootAnimation->UpdateTotalDuration();
7428     }
7429     else if (anArg == "-command"
7430           || anArg == "-cmd"
7431           || anArg == "-invoke"
7432           || anArg == "-eval"
7433           || anArg == "-proc")
7434     {
7435       if (++anArgIter >= theArgNb)
7436       {
7437         std::cout << "Syntax error at " << anArg << ".\n";
7438         return 1;
7439       }
7440
7441       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7442       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7443     }
7444     else if (anArg == "-objecttrsf"
7445           || anArg == "-objectransformation"
7446           || anArg == "-objtransformation"
7447           || anArg == "-objtrsf"
7448           || anArg == "-object"
7449           || anArg == "-obj")
7450     {
7451       if (++anArgIter >= theArgNb)
7452       {
7453         std::cout << "Syntax error at " << anArg << ".\n";
7454         return 1;
7455       }
7456
7457       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7458       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7459       Handle(AIS_InteractiveObject) anObject;
7460       if (!aMapOfAIS.Find2 (anObjName, anObject))
7461       {
7462         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7463         return 1;
7464       }
7465
7466       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7467       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7468       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7469       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7470       Standard_Boolean isTrsfSet = Standard_False;
7471       Standard_Integer aTrsfArgIter = anArgIter + 1;
7472       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7473       {
7474         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7475         aTrsfArg.LowerCase();
7476         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7477         if (aTrsfArg.StartsWith ("-rotation")
7478          || aTrsfArg.StartsWith ("-rot"))
7479         {
7480           isTrsfSet = Standard_True;
7481           if (aTrsfArgIter + 4 >= theArgNb
7482           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7483           {
7484             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7485             return 1;
7486           }
7487           aTrsfArgIter += 4;
7488         }
7489         else if (aTrsfArg.StartsWith ("-location")
7490               || aTrsfArg.StartsWith ("-loc"))
7491         {
7492           isTrsfSet = Standard_True;
7493           if (aTrsfArgIter + 3 >= theArgNb
7494           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7495           {
7496             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7497             return 1;
7498           }
7499           aTrsfArgIter += 3;
7500         }
7501         else if (aTrsfArg.StartsWith ("-scale"))
7502         {
7503           isTrsfSet = Standard_True;
7504           if (++aTrsfArgIter >= theArgNb)
7505           {
7506             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7507             return 1;
7508           }
7509
7510           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7511           if (!aScaleStr.IsRealValue())
7512           {
7513             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7514             return 1;
7515           }
7516           aScales[anIndex] = aScaleStr.RealValue();
7517         }
7518         else
7519         {
7520           anArgIter = aTrsfArgIter - 1;
7521           break;
7522         }
7523       }
7524       if (!isTrsfSet)
7525       {
7526         std::cout << "Syntax error at " << anArg << ".\n";
7527         return 1;
7528       }
7529       else if (aTrsfArgIter >= theArgNb)
7530       {
7531         anArgIter = theArgNb;
7532       }
7533
7534       aTrsfs[0].SetRotation        (aRotQuats[0]);
7535       aTrsfs[1].SetRotation        (aRotQuats[1]);
7536       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7537       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7538       aTrsfs[0].SetScaleFactor     (aScales[0]);
7539       aTrsfs[1].SetScaleFactor     (aScales[1]);
7540
7541       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7542       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7543     }
7544     else if (anArg == "-viewtrsf"
7545           || anArg == "-view")
7546     {
7547       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7548       if (aCamAnimation.IsNull())
7549       {
7550         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7551         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7552       }
7553
7554       Handle(Graphic3d_Camera) aCams[2] =
7555       {
7556         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7557         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7558       };
7559
7560       Standard_Boolean isTrsfSet = Standard_False;
7561       Standard_Integer aViewArgIter = anArgIter + 1;
7562       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7563       {
7564         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7565         aViewArg.LowerCase();
7566         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7567         if (aViewArg.StartsWith ("-scale"))
7568         {
7569           isTrsfSet = Standard_True;
7570           if (++aViewArgIter >= theArgNb)
7571           {
7572             std::cout << "Syntax error at " << anArg << ".\n";
7573             return 1;
7574           }
7575
7576           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7577           if (!aScaleStr.IsRealValue())
7578           {
7579             std::cout << "Syntax error at " << aViewArg << ".\n";
7580             return 1;
7581           }
7582           Standard_Real aScale = aScaleStr.RealValue();
7583           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7584           aCams[anIndex]->SetScale (aScale);
7585         }
7586         else if (aViewArg.StartsWith ("-eye")
7587               || aViewArg.StartsWith ("-center")
7588               || aViewArg.StartsWith ("-at")
7589               || aViewArg.StartsWith ("-up"))
7590         {
7591           isTrsfSet = Standard_True;
7592           gp_XYZ anXYZ;
7593           if (aViewArgIter + 3 >= theArgNb
7594           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7595           {
7596             std::cout << "Syntax error at " << aViewArg << ".\n";
7597             return 1;
7598           }
7599           aViewArgIter += 3;
7600
7601           if (aViewArg.StartsWith ("-eye"))
7602           {
7603             aCams[anIndex]->SetEye (anXYZ);
7604           }
7605           else if (aViewArg.StartsWith ("-center")
7606                 || aViewArg.StartsWith ("-at"))
7607           {
7608             aCams[anIndex]->SetCenter (anXYZ);
7609           }
7610           else if (aViewArg.StartsWith ("-up"))
7611           {
7612             aCams[anIndex]->SetUp (anXYZ);
7613           }
7614         }
7615         else
7616         {
7617           anArgIter = aViewArgIter - 1;
7618           break;
7619         }
7620       }
7621       if (!isTrsfSet)
7622       {
7623         std::cout << "Syntax error at " << anArg << ".\n";
7624         return 1;
7625       }
7626       else if (aViewArgIter >= theArgNb)
7627       {
7628         anArgIter = theArgNb;
7629       }
7630
7631       aCamAnimation->SetCameraStart(aCams[0]);
7632       aCamAnimation->SetCameraEnd  (aCams[1]);
7633     }
7634     else
7635     {
7636       std::cout << "Syntax error at " << anArg << ".\n";
7637       return 1;
7638     }
7639   }
7640
7641   if (!toPlay && aRecFile.IsEmpty())
7642   {
7643     return 0;
7644   }
7645
7646   // Start animation timeline and process frame updating.
7647   TheIsAnimating = Standard_True;
7648   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7649   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7650   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7651   if (isFreeCamera)
7652   {
7653     aView->Camera()->Copy (aCameraBack);
7654   }
7655
7656   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7657   if (aRecParams.FpsNum <= 0)
7658   {
7659     while (!anAnimation->IsStopped())
7660     {
7661       aCameraBack->Copy (aView->Camera());
7662       const Standard_Real aPts = anAnimation->UpdateTimer();
7663       if (isFreeCamera)
7664       {
7665         aView->Camera()->Copy (aCameraBack);
7666       }
7667
7668       if (aPts >= anUpperPts)
7669       {
7670         anAnimation->Pause();
7671         break;
7672       }
7673
7674       if (aView->IsInvalidated())
7675       {
7676         aView->Redraw();
7677       }
7678       else
7679       {
7680         aView->RedrawImmediate();
7681       }
7682
7683       if (!isLockLoop)
7684       {
7685         // handle user events
7686         theDI.Eval ("after 1 set waiter 1");
7687         theDI.Eval ("vwait waiter");
7688       }
7689       if (!TheIsAnimating)
7690       {
7691         anAnimation->Pause();
7692         theDI << aPts;
7693         break;
7694       }
7695     }
7696
7697     if (aView->IsInvalidated())
7698     {
7699       aView->Redraw();
7700     }
7701     else
7702     {
7703       aView->RedrawImmediate();
7704     }
7705   }
7706   else
7707   {
7708     OSD_Timer aPerfTimer;
7709     aPerfTimer.Start();
7710
7711     Handle(Image_VideoRecorder) aRecorder;
7712     ImageFlipper aFlipper;
7713     Handle(Draw_ProgressIndicator) aProgress;
7714     if (!aRecFile.IsEmpty())
7715     {
7716       if (aRecParams.Width  <= 0
7717        || aRecParams.Height <= 0)
7718       {
7719         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7720       }
7721
7722       aRecorder = new Image_VideoRecorder();
7723       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7724       {
7725         std::cout << "Error: failed to open video file for recording\n";
7726         return 0;
7727       }
7728
7729       aProgress = new Draw_ProgressIndicator (theDI, 1);
7730     }
7731
7732     // Manage frame-rated animation here
7733     Standard_Real aPts = aPlayStartTime;
7734     int64_t aNbFrames = 0;
7735     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7736     Standard_Integer aSecondsProgress = 0;
7737     for (; aPts <= anUpperPts && aPSentry.More();)
7738     {
7739       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
7740       aPts = aPlayStartTime + aRecPts;
7741       ++aNbFrames;
7742       if (!anAnimation->Update (aPts))
7743       {
7744         break;
7745       }
7746
7747       if (!aRecorder.IsNull())
7748       {
7749         V3d_ImageDumpOptions aDumpParams;
7750         aDumpParams.Width          = aRecParams.Width;
7751         aDumpParams.Height         = aRecParams.Height;
7752         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
7753         aDumpParams.StereoOptions  = V3d_SDO_MONO;
7754         aDumpParams.ToAdjustAspect = Standard_True;
7755         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
7756         {
7757           std::cout << "Error: view dump is failed!\n";
7758           return 0;
7759         }
7760         aFlipper.FlipY (aRecorder->ChangeFrame());
7761         if (!aRecorder->PushFrame())
7762         {
7763           return 0;
7764         }
7765       }
7766       else
7767       {
7768         aView->Redraw();
7769       }
7770
7771       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7772       {
7773         aPSentry.Next();
7774         ++aSecondsProgress;
7775       }
7776     }
7777
7778     aPerfTimer.Stop();
7779     anAnimation->Stop();
7780     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7781     theDI << "Average FPS: " << aRecFps << "\n"
7782           << "Nb. Frames: "  << Standard_Real(aNbFrames);
7783
7784     aView->Redraw();
7785   }
7786
7787   aView->SetImmediateUpdate (wasImmediateUpdate);
7788   TheIsAnimating = Standard_False;
7789   return 0;
7790 }
7791
7792
7793 //=======================================================================
7794 //function : VChangeSelected
7795 //purpose  : Adds the shape to selection or remove one from it
7796 //=======================================================================
7797 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7798                                 Standard_Integer argc,
7799                                 const char ** argv)
7800 {
7801   if(argc != 2)
7802   {
7803     di<<"Usage : " << argv[0] << " shape \n";
7804     return 1;
7805   }
7806   //get AIS_Shape:
7807   TCollection_AsciiString aName(argv[1]);
7808   Handle(AIS_InteractiveObject) anAISObject;
7809   if (!GetMapOfAIS().Find2 (aName, anAISObject)
7810     || anAISObject.IsNull())
7811   {
7812     di<<"Use 'vdisplay' before";
7813     return 1;
7814   }
7815
7816   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
7817   return 0;
7818 }
7819
7820 //=======================================================================
7821 //function : VNbSelected
7822 //purpose  : Returns number of selected objects
7823 //=======================================================================
7824 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7825                                 Standard_Integer argc,
7826                                 const char ** argv)
7827 {
7828   if(argc != 1)
7829   {
7830     di << "Usage : " << argv[0] << "\n";
7831     return 1;
7832   }
7833   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7834   if(aContext.IsNull())
7835   {
7836     di << "use 'vinit' command before " << argv[0] << "\n";
7837     return 1;
7838   }
7839   di << aContext->NbSelected() << "\n";
7840   return 0;
7841 }
7842
7843 //=======================================================================
7844 //function : VPurgeDisplay
7845 //purpose  : Switches altialiasing on or off
7846 //=======================================================================
7847 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7848                                 Standard_Integer argc,
7849                                 const char ** argv)
7850 {
7851   if (argc > 1)
7852   {
7853     di << "Usage : " << argv[0] << "\n";
7854     return 1;
7855   }
7856   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7857   if (aContext.IsNull())
7858   {
7859     di << "use 'vinit' command before " << argv[0] << "\n";
7860     return 1;
7861   }
7862
7863   di << aContext->PurgeDisplay() << "\n";
7864   return 0;
7865 }
7866
7867 //=======================================================================
7868 //function : VSetViewSize
7869 //purpose  :
7870 //=======================================================================
7871 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7872                                 Standard_Integer argc,
7873                                 const char ** argv)
7874 {
7875   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7876   if(aContext.IsNull())
7877   {
7878     di << "use 'vinit' command before " << argv[0] << "\n";
7879     return 1;
7880   }
7881   if(argc != 2)
7882   {
7883     di<<"Usage : " << argv[0] << " Size\n";
7884     return 1;
7885   }
7886   Standard_Real aSize = Draw::Atof (argv[1]);
7887   if (aSize <= 0.)
7888   {
7889     di<<"Bad Size value  : " << aSize << "\n";
7890     return 1;
7891   }
7892
7893   Handle(V3d_View) aView = ViewerTest::CurrentView();
7894   aView->SetSize(aSize);
7895   return 0;
7896 }
7897
7898 //=======================================================================
7899 //function : VMoveView
7900 //purpose  :
7901 //=======================================================================
7902 static Standard_Integer VMoveView (Draw_Interpretor& di,
7903                                 Standard_Integer argc,
7904                                 const char ** argv)
7905 {
7906   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7907   if(aContext.IsNull())
7908   {
7909     di << "use 'vinit' command before " << argv[0] << "\n";
7910     return 1;
7911   }
7912   if(argc < 4 || argc > 5)
7913   {
7914     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7915     return 1;
7916   }
7917   Standard_Real Dx = Draw::Atof (argv[1]);
7918   Standard_Real Dy = Draw::Atof (argv[2]);
7919   Standard_Real Dz = Draw::Atof (argv[3]);
7920   Standard_Boolean aStart = Standard_True;
7921   if (argc == 5)
7922   {
7923       aStart = (Draw::Atoi (argv[4]) > 0);
7924   }
7925
7926   Handle(V3d_View) aView = ViewerTest::CurrentView();
7927   aView->Move(Dx,Dy,Dz,aStart);
7928   return 0;
7929 }
7930
7931 //=======================================================================
7932 //function : VTranslateView
7933 //purpose  :
7934 //=======================================================================
7935 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7936                                 Standard_Integer argc,
7937                                 const char ** argv)
7938 {
7939   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7940   if(aContext.IsNull())
7941   {
7942     di << "use 'vinit' command before " << argv[0] << "\n";
7943     return 1;
7944   }
7945   if(argc < 4 || argc > 5)
7946   {
7947     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7948     return 1;
7949   }
7950   Standard_Real Dx = Draw::Atof (argv[1]);
7951   Standard_Real Dy = Draw::Atof (argv[2]);
7952   Standard_Real Dz = Draw::Atof (argv[3]);
7953   Standard_Boolean aStart = Standard_True;
7954   if (argc == 5)
7955   {
7956       aStart = (Draw::Atoi (argv[4]) > 0);
7957   }
7958
7959   Handle(V3d_View) aView = ViewerTest::CurrentView();
7960   aView->Translate(Dx,Dy,Dz,aStart);
7961   return 0;
7962 }
7963
7964 //=======================================================================
7965 //function : VTurnView
7966 //purpose  :
7967 //=======================================================================
7968 static Standard_Integer VTurnView (Draw_Interpretor& di,
7969                                 Standard_Integer argc,
7970                                 const char ** argv)
7971 {
7972   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7973   if(aContext.IsNull()) {
7974     di << "use 'vinit' command before " << argv[0] << "\n";
7975     return 1;
7976   }
7977   if(argc < 4 || argc > 5){
7978     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7979     return 1;
7980   }
7981   Standard_Real Ax = Draw::Atof (argv[1]);
7982   Standard_Real Ay = Draw::Atof (argv[2]);
7983   Standard_Real Az = Draw::Atof (argv[3]);
7984   Standard_Boolean aStart = Standard_True;
7985   if (argc == 5)
7986   {
7987       aStart = (Draw::Atoi (argv[4]) > 0);
7988   }
7989
7990   Handle(V3d_View) aView = ViewerTest::CurrentView();
7991   aView->Turn(Ax,Ay,Az,aStart);
7992   return 0;
7993 }
7994
7995 //==============================================================================
7996 //function : VTextureEnv
7997 //purpose  : ENables or disables environment mapping
7998 //==============================================================================
7999 class OCC_TextureEnv : public Graphic3d_TextureEnv
8000 {
8001 public:
8002   OCC_TextureEnv(const Standard_CString FileName);
8003   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8004   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8005                             const Standard_Boolean theModulateFlag,
8006                             const Graphic3d_TypeOfTextureFilter theFilter,
8007                             const Standard_ShortReal theXScale,
8008                             const Standard_ShortReal theYScale,
8009                             const Standard_ShortReal theXShift,
8010                             const Standard_ShortReal theYShift,
8011                             const Standard_ShortReal theAngle);
8012   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
8013 };
8014 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
8015
8016 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8017   : Graphic3d_TextureEnv(theFileName)
8018 {
8019 }
8020
8021 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8022   : Graphic3d_TextureEnv(theTexId)
8023 {
8024 }
8025
8026 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8027                                           const Standard_Boolean theModulateFlag,
8028                                           const Graphic3d_TypeOfTextureFilter theFilter,
8029                                           const Standard_ShortReal theXScale,
8030                                           const Standard_ShortReal theYScale,
8031                                           const Standard_ShortReal theXShift,
8032                                           const Standard_ShortReal theYShift,
8033                                           const Standard_ShortReal theAngle)
8034 {
8035   myParams->SetRepeat     (theRepeatFlag);
8036   myParams->SetModulate   (theModulateFlag);
8037   myParams->SetFilter     (theFilter);
8038   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
8039   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8040   myParams->SetRotation   (theAngle);
8041 }
8042
8043 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
8044 {
8045   // get the active view
8046   Handle(V3d_View) aView = ViewerTest::CurrentView();
8047   if (aView.IsNull())
8048   {
8049     std::cerr << "No active view. Please call vinit.\n";
8050     return 1;
8051   }
8052
8053   // Checking the input arguments
8054   Standard_Boolean anEnableFlag = Standard_False;
8055   Standard_Boolean isOk         = theArgNb >= 2;
8056   if (isOk)
8057   {
8058     TCollection_AsciiString anEnableOpt(theArgVec[1]);
8059     anEnableFlag = anEnableOpt.IsEqual("on");
8060     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
8061   }
8062   if (anEnableFlag)
8063   {
8064     isOk = (theArgNb == 3 || theArgNb == 11);
8065     if (isOk)
8066     {
8067       TCollection_AsciiString aTextureOpt(theArgVec[2]);
8068       isOk = (!aTextureOpt.IsIntegerValue() ||
8069              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8070
8071       if (isOk && theArgNb == 11)
8072       {
8073         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
8074                                 aModulateOpt(theArgVec[4]),
8075                                 aFilterOpt  (theArgVec[5]),
8076                                 aSScaleOpt  (theArgVec[6]),
8077                                 aTScaleOpt  (theArgVec[7]),
8078                                 aSTransOpt  (theArgVec[8]),
8079                                 aTTransOpt  (theArgVec[9]),
8080                                 anAngleOpt  (theArgVec[10]);
8081         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
8082                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8083                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
8084                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
8085                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
8086                 anAngleOpt.IsRealValue());
8087       }
8088     }
8089   }
8090
8091   if (!isOk)
8092   {
8093     std::cerr << "Usage :" << std::endl;
8094     std::cerr << theArgVec[0] << " off" << std::endl;
8095     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;
8096     return 1;
8097   }
8098
8099   if (anEnableFlag)
8100   {
8101     TCollection_AsciiString aTextureOpt(theArgVec[2]);
8102     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8103                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8104                                      new OCC_TextureEnv(theArgVec[2]);
8105
8106     if (theArgNb == 11)
8107     {
8108       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8109       aTexEnv->SetTextureParameters(
8110         aRepeatOpt.  IsEqual("repeat"),
8111         aModulateOpt.IsEqual("modulate"),
8112         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8113                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8114                                                                            Graphic3d_TOTF_TRILINEAR,
8115         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8116         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8117         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8118         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8119         (Standard_ShortReal)Draw::Atof(theArgVec[10])
8120         );
8121     }
8122     aView->SetTextureEnv(aTexEnv);
8123   }
8124   else // Disabling environment mapping
8125   {
8126     Handle(Graphic3d_TextureEnv) aTexture;
8127     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8128   }
8129
8130   aView->Redraw();
8131   return 0;
8132 }
8133
8134 namespace
8135 {
8136   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8137
8138   //! Remove registered clipping plane from all views and objects.
8139   static void removePlane (MapOfPlanes& theRegPlanes,
8140                            const TCollection_AsciiString& theName)
8141   {
8142     Handle(Graphic3d_ClipPlane) aClipPlane;
8143     if (!theRegPlanes.Find (theName, aClipPlane))
8144     {
8145       std::cout << "Warning: no such plane.\n";
8146       return;
8147     }
8148
8149     theRegPlanes.UnBind (theName);
8150     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8151          anIObjIt.More(); anIObjIt.Next())
8152     {
8153       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
8154       aPrs->RemoveClipPlane (aClipPlane);
8155     }
8156
8157     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8158          aViewIt.More(); aViewIt.Next())
8159     {
8160       const Handle(V3d_View)& aView = aViewIt.Key2();
8161       aView->RemoveClipPlane(aClipPlane);
8162     }
8163
8164     ViewerTest::RedrawAllViews();
8165   }
8166 }
8167
8168 //===============================================================================================
8169 //function : VClipPlane
8170 //purpose  :
8171 //===============================================================================================
8172 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8173 {
8174   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8175   static MapOfPlanes aRegPlanes;
8176
8177   if (theArgsNb < 2)
8178   {
8179     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8180     {
8181       theDi << aPlaneIter.Key() << " ";
8182     }
8183     return 0;
8184   }
8185
8186   TCollection_AsciiString aCommand (theArgVec[1]);
8187   aCommand.LowerCase();
8188   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8189   if (anActiveView.IsNull())
8190   {
8191     std::cout << "Error: no active view.\n";
8192     return 1;
8193   }
8194
8195   // print maximum number of planes for current viewer
8196   if (aCommand == "-maxplanes"
8197    || aCommand == "maxplanes")
8198   {
8199     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8200           << " plane slots provided by driver.\n";
8201     return 0;
8202   }
8203
8204   // create / delete plane instance
8205   if (aCommand == "-create"
8206    || aCommand == "create"
8207    || aCommand == "-delete"
8208    || aCommand == "delete"
8209    || aCommand == "-clone"
8210    || aCommand == "clone")
8211   {
8212     if (theArgsNb < 3)
8213     {
8214       std::cout << "Syntax error: plane name is required.\n";
8215       return 1;
8216     }
8217
8218     Standard_Boolean toCreate = aCommand == "-create"
8219                              || aCommand == "create";
8220     Standard_Boolean toClone  = aCommand == "-clone"
8221                              || aCommand == "clone";
8222     Standard_Boolean toDelete = aCommand == "-delete"
8223                              || aCommand == "delete";
8224     TCollection_AsciiString aPlane (theArgVec[2]);
8225
8226     if (toCreate)
8227     {
8228       if (aRegPlanes.IsBound (aPlane))
8229       {
8230         std::cout << "Warning: existing plane has been overridden.\n";
8231         toDelete = true;
8232       }
8233       else
8234       {
8235         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8236         return 0;
8237       }
8238     }
8239     else if (toClone) // toClone
8240     {
8241       if (!aRegPlanes.IsBound (aPlane))
8242       {
8243         std::cout << "Error: no such plane.\n";
8244         return 1;
8245       }
8246       else if (theArgsNb < 4)
8247       {
8248         std::cout << "Syntax error: enter name for new plane.\n";
8249         return 1;
8250       }
8251
8252       TCollection_AsciiString aClone (theArgVec[3]);
8253       if (aRegPlanes.IsBound (aClone))
8254       {
8255         std::cout << "Error: plane name is in use.\n";
8256         return 1;
8257       }
8258
8259       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8260
8261       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8262       return 0;
8263     }
8264
8265     if (toDelete)
8266     {
8267       if (aPlane == "ALL"
8268        || aPlane == "all"
8269        || aPlane == "*")
8270       {
8271         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8272         {
8273           aPlane = aPlaneIter.Key();
8274           removePlane (aRegPlanes, aPlane);
8275           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8276         }
8277       }
8278       else
8279       {
8280         removePlane (aRegPlanes, aPlane);
8281       }
8282     }
8283
8284     if (toCreate)
8285     {
8286       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8287     }
8288     return 0;
8289   }
8290
8291   // set / unset plane command
8292   if (aCommand == "set"
8293    || aCommand == "unset")
8294   {
8295     if (theArgsNb < 5)
8296     {
8297       std::cout << "Syntax error: need more arguments.\n";
8298       return 1;
8299     }
8300
8301     // redirect to new syntax
8302     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8303     anArgVec.SetValue (1, theArgVec[0]);
8304     anArgVec.SetValue (2, theArgVec[2]);
8305     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8306     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8307     {
8308       anArgVec.SetValue (anIt, theArgVec[anIt]);
8309     }
8310
8311     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8312   }
8313
8314   // change plane command
8315   TCollection_AsciiString aPlaneName;
8316   Handle(Graphic3d_ClipPlane) aClipPlane;
8317   Standard_Integer anArgIter = 0;
8318   if (aCommand == "-change"
8319    || aCommand == "change")
8320   {
8321     // old syntax support
8322     if (theArgsNb < 3)
8323     {
8324       std::cout << "Syntax error: need more arguments.\n";
8325       return 1;
8326     }
8327
8328     anArgIter  = 3;
8329     aPlaneName = theArgVec[2];
8330     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8331     {
8332       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8333       return 1;
8334     }
8335   }
8336   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8337   {
8338     anArgIter  = 2;
8339     aPlaneName = theArgVec[1];
8340   }
8341   else
8342   {
8343     anArgIter  = 2;
8344     aPlaneName = theArgVec[1];
8345     aClipPlane = new Graphic3d_ClipPlane();
8346     aRegPlanes.Bind (aPlaneName, aClipPlane);
8347     theDi << "Created new plane " << aPlaneName << ".\n";
8348   }
8349
8350   if (theArgsNb - anArgIter < 1)
8351   {
8352     std::cout << "Syntax error: need more arguments.\n";
8353     return 1;
8354   }
8355
8356   for (; anArgIter < theArgsNb; ++anArgIter)
8357   {
8358     const char**     aChangeArgs   = theArgVec + anArgIter;
8359     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8360     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8361     aChangeArg.LowerCase();
8362
8363     Standard_Boolean toEnable = Standard_True;
8364     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8365     {
8366       aClipPlane->SetOn (toEnable);
8367     }
8368     else if (aChangeArg.StartsWith ("-equation")
8369           || aChangeArg.StartsWith ("equation"))
8370     {
8371       if (aNbChangeArgs < 5)
8372       {
8373         std::cout << "Syntax error: need more arguments.\n";
8374         return 1;
8375       }
8376
8377       Standard_Integer aSubIndex = 1;
8378       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
8379       if (aPrefixLen < aChangeArg.Length())
8380       {
8381         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
8382         if (!aSubStr.IsIntegerValue()
8383           || aSubStr.IntegerValue() <= 0)
8384         {
8385           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8386           return 1;
8387         }
8388         aSubIndex = aSubStr.IntegerValue();
8389       }
8390
8391       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
8392       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
8393       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
8394       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
8395       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8396       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
8397       {
8398         if (aSubPln->ChainNextPlane().IsNull())
8399         {
8400           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8401         }
8402         aSubPln = aSubPln->ChainNextPlane();
8403       }
8404       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8405       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8406       anArgIter += 4;
8407     }
8408     else if ((aChangeArg == "-boxinterior"
8409            || aChangeArg == "-boxint"
8410            || aChangeArg == "-box")
8411             && aNbChangeArgs >= 7)
8412     {
8413       Graphic3d_BndBox3d aBndBox;
8414       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
8415       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
8416       anArgIter += 6;
8417
8418       Standard_Integer aNbSubPlanes = 6;
8419       const Graphic3d_Vec3d aDirArray[6] =
8420       {
8421         Graphic3d_Vec3d (-1, 0, 0),
8422         Graphic3d_Vec3d ( 1, 0, 0),
8423         Graphic3d_Vec3d ( 0,-1, 0),
8424         Graphic3d_Vec3d ( 0, 1, 0),
8425         Graphic3d_Vec3d ( 0, 0,-1),
8426         Graphic3d_Vec3d ( 0, 0, 1),
8427       };
8428       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8429       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
8430       {
8431         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
8432         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
8433         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
8434         if (aSubPlaneIter + 1 == aNbSubPlanes)
8435         {
8436           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8437         }
8438         else
8439         {
8440           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8441         }
8442         aSubPln = aSubPln->ChainNextPlane();
8443       }
8444     }
8445     else if (aChangeArg == "-capping"
8446           || aChangeArg == "capping")
8447     {
8448       if (aNbChangeArgs < 2)
8449       {
8450         std::cout << "Syntax error: need more arguments.\n";
8451         return 1;
8452       }
8453
8454       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8455       {
8456         aClipPlane->SetCapping (toEnable);
8457         anArgIter += 1;
8458       }
8459       else
8460       {
8461         // just skip otherwise (old syntax)
8462       }
8463     }
8464     else if (aChangeArg == "-useobjectmaterial"
8465           || aChangeArg == "-useobjectmat"
8466           || aChangeArg == "-useobjmat"
8467           || aChangeArg == "-useobjmaterial")
8468     {
8469       if (aNbChangeArgs < 2)
8470       {
8471         std::cout << "Syntax error: need more arguments.\n";
8472         return 1;
8473       }
8474
8475       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8476       {
8477         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8478         anArgIter += 1;
8479       }
8480     }
8481     else if (aChangeArg == "-useobjecttexture"
8482           || aChangeArg == "-useobjecttex"
8483           || aChangeArg == "-useobjtexture"
8484           || aChangeArg == "-useobjtex")
8485     {
8486       if (aNbChangeArgs < 2)
8487       {
8488         std::cout << "Syntax error: need more arguments.\n";
8489         return 1;
8490       }
8491
8492       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8493       {
8494         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8495         anArgIter += 1;
8496       }
8497     }
8498     else if (aChangeArg == "-useobjectshader"
8499           || aChangeArg == "-useobjshader")
8500     {
8501       if (aNbChangeArgs < 2)
8502       {
8503         std::cout << "Syntax error: need more arguments.\n";
8504         return 1;
8505       }
8506
8507       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8508       {
8509         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8510         anArgIter += 1;
8511       }
8512     }
8513     else if (aChangeArg == "-color"
8514           || aChangeArg == "color")
8515     {
8516       Quantity_Color aColor;
8517       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8518                                                            aChangeArgs + 1,
8519                                                            aColor);
8520       if (aNbParsed == 0)
8521       {
8522         std::cout << "Syntax error: need more arguments.\n";
8523         return 1;
8524       }
8525
8526       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8527       aMat.SetAmbientColor (aColor);
8528       aMat.SetDiffuseColor (aColor);
8529       aClipPlane->SetCappingMaterial (aMat);
8530       anArgIter += aNbParsed;
8531     }
8532     else if ((aChangeArg == "-transparency"
8533            || aChangeArg == "-transp")
8534           && aNbChangeArgs >= 2)
8535     {
8536       TCollection_AsciiString aValStr (aChangeArgs[1]);
8537       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
8538       if (aValStr.IsRealValue())
8539       {
8540         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8541         aMat.SetTransparency ((float )aValStr.RealValue());
8542         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
8543         aClipPlane->SetCappingMaterial (aMat);
8544       }
8545       else
8546       {
8547         aValStr.LowerCase();
8548         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
8549         if (aValStr == "opaque")
8550         {
8551           aMode = Graphic3d_AlphaMode_Opaque;
8552         }
8553         else if (aValStr == "mask")
8554         {
8555           aMode = Graphic3d_AlphaMode_Mask;
8556         }
8557         else if (aValStr == "blend")
8558         {
8559           aMode = Graphic3d_AlphaMode_Blend;
8560         }
8561         else if (aValStr == "blendauto")
8562         {
8563           aMode = Graphic3d_AlphaMode_BlendAuto;
8564         }
8565         else
8566         {
8567           std::cout << "Syntax error at '" << aValStr << "'\n";
8568           return 1;
8569         }
8570         anAspect->SetAlphaMode (aMode);
8571         aClipPlane->SetCappingAspect (anAspect);
8572       }
8573       anArgIter += 1;
8574     }
8575     else if (aChangeArg == "-texname"
8576           || aChangeArg == "texname")
8577     {
8578       if (aNbChangeArgs < 2)
8579       {
8580         std::cout << "Syntax error: need more arguments.\n";
8581         return 1;
8582       }
8583
8584       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8585       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8586       if (!aTexture->IsDone())
8587       {
8588         aClipPlane->SetCappingTexture (NULL);
8589       }
8590       else
8591       {
8592         aTexture->EnableModulate();
8593         aTexture->EnableRepeat();
8594         aClipPlane->SetCappingTexture (aTexture);
8595       }
8596       anArgIter += 1;
8597     }
8598     else if (aChangeArg == "-texscale"
8599           || aChangeArg == "texscale")
8600     {
8601       if (aClipPlane->CappingTexture().IsNull())
8602       {
8603         std::cout << "Error: no texture is set.\n";
8604         return 1;
8605       }
8606
8607       if (aNbChangeArgs < 3)
8608       {
8609         std::cout << "Syntax error: need more arguments.\n";
8610         return 1;
8611       }
8612
8613       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8614       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8615       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8616       anArgIter += 2;
8617     }
8618     else if (aChangeArg == "-texorigin"
8619           || aChangeArg == "texorigin") // texture origin
8620     {
8621       if (aClipPlane->CappingTexture().IsNull())
8622       {
8623         std::cout << "Error: no texture is set.\n";
8624         return 1;
8625       }
8626
8627       if (aNbChangeArgs < 3)
8628       {
8629         std::cout << "Syntax error: need more arguments.\n";
8630         return 1;
8631       }
8632
8633       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8634       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8635
8636       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8637       anArgIter += 2;
8638     }
8639     else if (aChangeArg == "-texrotate"
8640           || aChangeArg == "texrotate") // texture rotation
8641     {
8642       if (aClipPlane->CappingTexture().IsNull())
8643       {
8644         std::cout << "Error: no texture is set.\n";
8645         return 1;
8646       }
8647
8648       if (aNbChangeArgs < 2)
8649       {
8650         std::cout << "Syntax error: need more arguments.\n";
8651         return 1;
8652       }
8653
8654       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8655       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8656       anArgIter += 1;
8657     }
8658     else if (aChangeArg == "-hatch"
8659           || aChangeArg == "hatch")
8660     {
8661       if (aNbChangeArgs < 2)
8662       {
8663         std::cout << "Syntax error: need more arguments.\n";
8664         return 1;
8665       }
8666
8667       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8668       aHatchStr.LowerCase();
8669       if (aHatchStr == "on")
8670       {
8671         aClipPlane->SetCappingHatchOn();
8672       }
8673       else if (aHatchStr == "off")
8674       {
8675         aClipPlane->SetCappingHatchOff();
8676       }
8677       else
8678       {
8679         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8680       }
8681       anArgIter += 1;
8682     }
8683     else if (aChangeArg == "-delete"
8684           || aChangeArg == "delete")
8685     {
8686       removePlane (aRegPlanes, aPlaneName);
8687       return 0;
8688     }
8689     else if (aChangeArg == "-set"
8690           || aChangeArg == "-unset"
8691           || aChangeArg == "-setoverrideglobal")
8692     {
8693       // set / unset plane command
8694       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
8695       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
8696       Standard_Integer anIt = 1;
8697       for (; anIt < aNbChangeArgs; ++anIt)
8698       {
8699         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8700         if (anEntityName.IsEmpty()
8701          || anEntityName.Value (1) == '-')
8702         {
8703           break;
8704         }
8705         else if (!toOverrideGlobal
8706                && ViewerTest_myViews.IsBound1 (anEntityName))
8707         {
8708           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8709           if (toSet)
8710           {
8711             aView->AddClipPlane (aClipPlane);
8712           }
8713           else
8714           {
8715             aView->RemoveClipPlane (aClipPlane);
8716           }
8717           continue;
8718         }
8719         else if (GetMapOfAIS().IsBound2 (anEntityName))
8720         {
8721           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
8722           if (toSet)
8723           {
8724             aIObj->AddClipPlane (aClipPlane);
8725           }
8726           else
8727           {
8728             aIObj->RemoveClipPlane (aClipPlane);
8729           }
8730           if (!aIObj->ClipPlanes().IsNull())
8731           {
8732             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
8733           }
8734         }
8735         else
8736         {
8737           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
8738           return 1;
8739         }
8740       }
8741
8742       if (anIt == 1)
8743       {
8744         // apply to active view
8745         if (toSet)
8746         {
8747           anActiveView->AddClipPlane (aClipPlane);
8748         }
8749         else
8750         {
8751           anActiveView->RemoveClipPlane (aClipPlane);
8752         }
8753       }
8754       else
8755       {
8756         anArgIter = anArgIter + anIt - 1;
8757       }
8758     }
8759     else
8760     {
8761       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8762       return 1;
8763     }
8764   }
8765
8766   ViewerTest::RedrawAllViews();
8767   return 0;
8768 }
8769
8770 //===============================================================================================
8771 //function : VZRange
8772 //purpose  :
8773 //===============================================================================================
8774 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8775 {
8776   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8777
8778   if (aCurrentView.IsNull())
8779   {
8780     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8781     return 1;
8782   }
8783
8784   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
8785
8786   if (theArgsNb < 2)
8787   {
8788     theDi << "ZNear: " << aCamera->ZNear() << "\n";
8789     theDi << "ZFar: " << aCamera->ZFar() << "\n";
8790     return 0;
8791   }
8792
8793   if (theArgsNb == 3)
8794   {
8795     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8796     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
8797
8798     if (aNewZNear >= aNewZFar)
8799     {
8800       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
8801       return 1;
8802     }
8803
8804     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8805     {
8806       std::cout << theArgVec[0] << ": invalid arguments: ";
8807       std::cout << "znear, zfar should be positive for perspective camera.\n";
8808       return 1;
8809     }
8810
8811     aCamera->SetZRange (aNewZNear, aNewZFar);
8812   }
8813   else
8814   {
8815     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8816     return 1;
8817   }
8818
8819   aCurrentView->Redraw();
8820
8821   return 0;
8822 }
8823
8824 //===============================================================================================
8825 //function : VAutoZFit
8826 //purpose  :
8827 //===============================================================================================
8828 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8829 {
8830   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8831
8832   if (aCurrentView.IsNull())
8833   {
8834     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8835     return 1;
8836   }
8837
8838   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
8839
8840   if (theArgsNb > 3)
8841   {
8842     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8843     return 1;
8844   }
8845
8846   if (theArgsNb < 2)
8847   {
8848     theDi << "Auto z-fit mode: \n"
8849           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
8850           << "Scale: " << aScale << "\n";
8851     return 0;
8852   }
8853
8854   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
8855
8856   if (theArgsNb >= 3)
8857   {
8858     aScale = Draw::Atoi (theArgVec[2]);
8859   }
8860
8861   aCurrentView->SetAutoZFitMode (isOn, aScale);
8862   aCurrentView->AutoZFit();
8863   aCurrentView->Redraw();
8864
8865   return 0;
8866 }
8867
8868 //! Auxiliary function to print projection type
8869 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
8870 {
8871   switch (theProjType)
8872   {
8873     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
8874     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
8875     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
8876     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
8877     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
8878   }
8879   return "UNKNOWN";
8880 }
8881
8882 //===============================================================================================
8883 //function : VCamera
8884 //purpose  :
8885 //===============================================================================================
8886 static int VCamera (Draw_Interpretor& theDI,
8887                     Standard_Integer  theArgsNb,
8888                     const char**      theArgVec)
8889 {
8890   Handle(V3d_View) aView = ViewerTest::CurrentView();
8891   if (aView.IsNull())
8892   {
8893     std::cout << "Error: no active view.\n";
8894     return 1;
8895   }
8896
8897   Handle(Graphic3d_Camera) aCamera = aView->Camera();
8898   if (theArgsNb < 2)
8899   {
8900     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
8901     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
8902     theDI << "Distance:   " << aCamera->Distance() << "\n";
8903     theDI << "IOD:        " << aCamera->IOD() << "\n";
8904     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
8905     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
8906     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
8907     return 0;
8908   }
8909
8910   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8911   {
8912     Standard_CString        anArg = theArgVec[anArgIter];
8913     TCollection_AsciiString anArgCase (anArg);
8914     anArgCase.LowerCase();
8915     if (anArgCase == "-proj"
8916      || anArgCase == "-projection"
8917      || anArgCase == "-projtype"
8918      || anArgCase == "-projectiontype")
8919     {
8920       theDI << projTypeName (aCamera->ProjectionType()) << " ";
8921     }
8922     else if (anArgCase == "-ortho"
8923           || anArgCase == "-orthographic")
8924     {
8925       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8926     }
8927     else if (anArgCase == "-persp"
8928           || anArgCase == "-perspective"
8929           || anArgCase == "-perspmono"
8930           || anArgCase == "-perspectivemono"
8931           || anArgCase == "-mono")
8932     {
8933       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8934     }
8935     else if (anArgCase == "-stereo"
8936           || anArgCase == "-stereoscopic"
8937           || anArgCase == "-perspstereo"
8938           || anArgCase == "-perspectivestereo")
8939     {
8940       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8941     }
8942     else if (anArgCase == "-left"
8943           || anArgCase == "-lefteye"
8944           || anArgCase == "-monoleft"
8945           || anArgCase == "-monolefteye"
8946           || anArgCase == "-perpsleft"
8947           || anArgCase == "-perpslefteye")
8948     {
8949       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8950     }
8951     else if (anArgCase == "-right"
8952           || anArgCase == "-righteye"
8953           || anArgCase == "-monoright"
8954           || anArgCase == "-monorighteye"
8955           || anArgCase == "-perpsright")
8956     {
8957       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8958     }
8959     else if (anArgCase == "-dist"
8960           || anArgCase == "-distance")
8961     {
8962       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8963       if (anArgValue != NULL
8964       && *anArgValue != '-')
8965       {
8966         ++anArgIter;
8967         aCamera->SetDistance (Draw::Atof (anArgValue));
8968         continue;
8969       }
8970       theDI << aCamera->Distance() << " ";
8971     }
8972     else if (anArgCase == "-iod")
8973     {
8974       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8975       if (anArgValue != NULL
8976       && *anArgValue != '-')
8977       {
8978         ++anArgIter;
8979         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8980         continue;
8981       }
8982       theDI << aCamera->IOD() << " ";
8983     }
8984     else if (anArgCase == "-iodtype")
8985     {
8986       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8987       TCollection_AsciiString anValueCase (anArgValue);
8988       anValueCase.LowerCase();
8989       if (anValueCase == "abs"
8990        || anValueCase == "absolute")
8991       {
8992         ++anArgIter;
8993         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8994         continue;
8995       }
8996       else if (anValueCase == "rel"
8997             || anValueCase == "relative")
8998       {
8999         ++anArgIter;
9000         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
9001         continue;
9002       }
9003       else if (*anArgValue != '-')
9004       {
9005         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
9006         return 1;
9007       }
9008       switch (aCamera->GetIODType())
9009       {
9010         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
9011         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
9012       }
9013     }
9014     else if (anArgCase == "-zfocus")
9015     {
9016       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9017       if (anArgValue != NULL
9018       && *anArgValue != '-')
9019       {
9020         ++anArgIter;
9021         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
9022         continue;
9023       }
9024       theDI << aCamera->ZFocus() << " ";
9025     }
9026     else if (anArgCase == "-zfocustype")
9027     {
9028       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9029       TCollection_AsciiString anValueCase (anArgValue);
9030       anValueCase.LowerCase();
9031       if (anValueCase == "abs"
9032        || anValueCase == "absolute")
9033       {
9034         ++anArgIter;
9035         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
9036         continue;
9037       }
9038       else if (anValueCase == "rel"
9039             || anValueCase == "relative")
9040       {
9041         ++anArgIter;
9042         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
9043         continue;
9044       }
9045       else if (*anArgValue != '-')
9046       {
9047         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
9048         return 1;
9049       }
9050       switch (aCamera->ZFocusType())
9051       {
9052         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
9053         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
9054       }
9055     }
9056     else if (anArgCase == "-fov"
9057           || anArgCase == "-fovy")
9058     {
9059       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9060       if (anArgValue != NULL
9061       && *anArgValue != '-')
9062       {
9063         ++anArgIter;
9064         aCamera->SetFOVy (Draw::Atof (anArgValue));
9065         continue;
9066       }
9067       theDI << aCamera->FOVy() << " ";
9068     }
9069     else
9070     {
9071       std::cout << "Error: unknown argument '" << anArg << "'\n";
9072       return 1;
9073     }
9074   }
9075
9076   aView->AutoZFit();
9077   aView->Redraw();
9078
9079   return 0;
9080 }
9081
9082 //! Parse stereo output mode
9083 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
9084                                          Graphic3d_StereoMode& theMode)
9085 {
9086   TCollection_AsciiString aFlag (theArg);
9087   aFlag.LowerCase();
9088   if (aFlag == "quadbuffer")
9089   {
9090     theMode = Graphic3d_StereoMode_QuadBuffer;
9091   }
9092   else if (aFlag == "anaglyph")
9093   {
9094     theMode = Graphic3d_StereoMode_Anaglyph;
9095   }
9096   else if (aFlag == "row"
9097         || aFlag == "rowinterlaced")
9098   {
9099     theMode = Graphic3d_StereoMode_RowInterlaced;
9100   }
9101   else if (aFlag == "col"
9102         || aFlag == "colinterlaced"
9103         || aFlag == "columninterlaced")
9104   {
9105     theMode = Graphic3d_StereoMode_ColumnInterlaced;
9106   }
9107   else if (aFlag == "chess"
9108         || aFlag == "chessboard")
9109   {
9110     theMode = Graphic3d_StereoMode_ChessBoard;
9111   }
9112   else if (aFlag == "sbs"
9113         || aFlag == "sidebyside")
9114   {
9115     theMode = Graphic3d_StereoMode_SideBySide;
9116   }
9117   else if (aFlag == "ou"
9118         || aFlag == "overunder")
9119   {
9120     theMode = Graphic3d_StereoMode_OverUnder;
9121   }
9122   else if (aFlag == "pageflip"
9123         || aFlag == "softpageflip")
9124   {
9125     theMode = Graphic3d_StereoMode_SoftPageFlip;
9126   }
9127   else
9128   {
9129     return Standard_False;
9130   }
9131   return Standard_True;
9132 }
9133
9134 //! Parse anaglyph filter
9135 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
9136                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
9137 {
9138   TCollection_AsciiString aFlag (theArg);
9139   aFlag.LowerCase();
9140   if (aFlag == "redcyansimple")
9141   {
9142     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9143   }
9144   else if (aFlag == "redcyan"
9145         || aFlag == "redcyanoptimized")
9146   {
9147     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
9148   }
9149   else if (aFlag == "yellowbluesimple")
9150   {
9151     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
9152   }
9153   else if (aFlag == "yellowblue"
9154         || aFlag == "yellowblueoptimized")
9155   {
9156     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
9157   }
9158   else if (aFlag == "greenmagenta"
9159         || aFlag == "greenmagentasimple")
9160   {
9161     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
9162   }
9163   else
9164   {
9165     return Standard_False;
9166   }
9167   return Standard_True;
9168 }
9169
9170 //==============================================================================
9171 //function : VStereo
9172 //purpose  :
9173 //==============================================================================
9174
9175 static int VStereo (Draw_Interpretor& theDI,
9176                     Standard_Integer  theArgNb,
9177                     const char**      theArgVec)
9178 {
9179   Handle(V3d_View) aView = ViewerTest::CurrentView();
9180   if (theArgNb < 2)
9181   {
9182     if (aView.IsNull())
9183     {
9184       std::cout << "Error: no active viewer!\n";
9185       return 0;
9186     }
9187
9188     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
9189     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
9190     if (isActive)
9191     {
9192       TCollection_AsciiString aMode;
9193       switch (aView->RenderingParams().StereoMode)
9194       {
9195         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
9196         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
9197         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
9198         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
9199         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
9200         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
9201         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
9202         case Graphic3d_StereoMode_Anaglyph  :
9203           aMode = "anaglyph";
9204           switch (aView->RenderingParams().AnaglyphFilter)
9205           {
9206             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
9207             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
9208             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
9209             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
9210             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
9211             default: break;
9212           }
9213         default: break;
9214       }
9215       theDI << "Mode " << aMode << "\n";
9216     }
9217     return 0;
9218   }
9219
9220   Handle(Graphic3d_Camera) aCamera;
9221   Graphic3d_RenderingParams*   aParams   = NULL;
9222   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
9223   if (!aView.IsNull())
9224   {
9225     aParams   = &aView->ChangeRenderingParams();
9226     aMode     = aParams->StereoMode;
9227     aCamera   = aView->Camera();
9228   }
9229
9230   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9231   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9232   {
9233     Standard_CString        anArg = theArgVec[anArgIter];
9234     TCollection_AsciiString aFlag (anArg);
9235     aFlag.LowerCase();
9236     if (anUpdateTool.parseRedrawMode (aFlag))
9237     {
9238       continue;
9239     }
9240     else if (aFlag == "0"
9241           || aFlag == "off")
9242     {
9243       if (++anArgIter < theArgNb)
9244       {
9245         std::cout << "Error: wrong number of arguments!\n";
9246         return 1;
9247       }
9248
9249       if (!aCamera.IsNull()
9250        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
9251       {
9252         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9253       }
9254       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
9255       return 0;
9256     }
9257     else if (aFlag == "1"
9258           || aFlag == "on")
9259     {
9260       if (++anArgIter < theArgNb)
9261       {
9262         std::cout << "Error: wrong number of arguments!\n";
9263         return 1;
9264       }
9265
9266       if (!aCamera.IsNull())
9267       {
9268         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9269       }
9270       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9271       return 0;
9272     }
9273     else if (aFlag == "-reverse"
9274           || aFlag == "-reversed"
9275           || aFlag == "-swap")
9276     {
9277       Standard_Boolean toEnable = Standard_True;
9278       if (++anArgIter < theArgNb
9279       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9280       {
9281         --anArgIter;
9282       }
9283       aParams->ToReverseStereo = toEnable;
9284     }
9285     else if (aFlag == "-noreverse"
9286           || aFlag == "-noswap")
9287     {
9288       Standard_Boolean toDisable = Standard_True;
9289       if (++anArgIter < theArgNb
9290       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9291       {
9292         --anArgIter;
9293       }
9294       aParams->ToReverseStereo = !toDisable;
9295     }
9296     else if (aFlag == "-mode"
9297           || aFlag == "-stereomode")
9298     {
9299       if (++anArgIter >= theArgNb
9300       || !parseStereoMode (theArgVec[anArgIter], aMode))
9301       {
9302         std::cout << "Error: syntax error at '" << anArg << "'\n";
9303         return 1;
9304       }
9305
9306       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9307       {
9308         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9309       }
9310     }
9311     else if (aFlag == "-anaglyph"
9312           || aFlag == "-anaglyphfilter")
9313     {
9314       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9315       if (++anArgIter >= theArgNb
9316       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9317       {
9318         std::cout << "Error: syntax error at '" << anArg << "'\n";
9319         return 1;
9320       }
9321
9322       aMode = Graphic3d_StereoMode_Anaglyph;
9323       aParams->AnaglyphFilter = aFilter;
9324     }
9325     else if (parseStereoMode (anArg, aMode)) // short syntax
9326     {
9327       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9328       {
9329         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9330       }
9331     }
9332     else
9333     {
9334       std::cout << "Error: syntax error at '" << anArg << "'\n";
9335       return 1;
9336     }
9337   }
9338
9339   if (!aView.IsNull())
9340   {
9341     aParams->StereoMode = aMode;
9342     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9343   }
9344   return 0;
9345 }
9346
9347 //===============================================================================================
9348 //function : VDefaults
9349 //purpose  :
9350 //===============================================================================================
9351 static int VDefaults (Draw_Interpretor& theDi,
9352                       Standard_Integer  theArgsNb,
9353                       const char**      theArgVec)
9354 {
9355   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9356   if (aCtx.IsNull())
9357   {
9358     std::cerr << "No active viewer!\n";
9359     return 1;
9360   }
9361
9362   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9363   if (theArgsNb < 2)
9364   {
9365     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9366     {
9367       theDi << "DeflType:           relative\n"
9368             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9369     }
9370     else
9371     {
9372       theDi << "DeflType:           absolute\n"
9373             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9374     }
9375     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9376     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9377     return 0;
9378   }
9379
9380   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9381   {
9382     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9383     anArg.UpperCase();
9384     if (anArg == "-ABSDEFL"
9385      || anArg == "-ABSOLUTEDEFLECTION"
9386      || anArg == "-DEFL"
9387      || anArg == "-DEFLECTION")
9388     {
9389       if (++anArgIter >= theArgsNb)
9390       {
9391         std::cout << "Error: wrong syntax at " << anArg << "\n";
9392         return 1;
9393       }
9394       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9395       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9396     }
9397     else if (anArg == "-RELDEFL"
9398           || anArg == "-RELATIVEDEFLECTION"
9399           || anArg == "-DEVCOEFF"
9400           || anArg == "-DEVIATIONCOEFF"
9401           || anArg == "-DEVIATIONCOEFFICIENT")
9402     {
9403       if (++anArgIter >= theArgsNb)
9404       {
9405         std::cout << "Error: wrong syntax at " << anArg << "\n";
9406         return 1;
9407       }
9408       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9409       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9410     }
9411     else if (anArg == "-ANGDEFL"
9412           || anArg == "-ANGULARDEFL"
9413           || anArg == "-ANGULARDEFLECTION")
9414     {
9415       if (++anArgIter >= theArgsNb)
9416       {
9417         std::cout << "Error: wrong syntax at " << anArg << "\n";
9418         return 1;
9419       }
9420       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9421       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9422     }
9423     else if (anArg == "-AUTOTR"
9424           || anArg == "-AUTOTRIANG"
9425           || anArg == "-AUTOTRIANGULATION")
9426     {
9427       if (++anArgIter >= theArgsNb)
9428       {
9429         std::cout << "Error: wrong syntax at " << anArg << "\n";
9430         return 1;
9431       }
9432       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9433       aValue.LowerCase();
9434       if (aValue == "on"
9435        || aValue == "1")
9436       {
9437         aDefParams->SetAutoTriangulation (Standard_True);
9438       }
9439       else if (aValue == "off"
9440             || aValue == "0")
9441       {
9442         aDefParams->SetAutoTriangulation (Standard_False);
9443       }
9444     }
9445     else
9446     {
9447       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9448     }
9449   }
9450
9451   return 0;
9452 }
9453
9454 //! Auxiliary method
9455 inline void addLight (const Handle(V3d_Light)& theLightNew,
9456                       const Graphic3d_ZLayerId theLayer,
9457                       const Standard_Boolean   theIsGlobal)
9458 {
9459   if (theLightNew.IsNull())
9460   {
9461     return;
9462   }
9463
9464   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9465   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
9466   {
9467     aViewer->AddLight (theLightNew);
9468     if (theIsGlobal)
9469     {
9470       aViewer->SetLightOn (theLightNew);
9471     }
9472     else
9473     {
9474       ViewerTest::CurrentView()->SetLightOn (theLightNew);
9475     }
9476   }
9477   else
9478   {
9479     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
9480     if (aSettings.Lights().IsNull())
9481     {
9482       aSettings.SetLights (new Graphic3d_LightSet());
9483     }
9484     aSettings.Lights()->Add (theLightNew);
9485     aViewer->SetZLayerSettings (theLayer, aSettings);
9486   }
9487 }
9488
9489 //! Auxiliary method
9490 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9491 {
9492   TCollection_AsciiString anArgNextCase (theArgNext);
9493   anArgNextCase.UpperCase();
9494   if (anArgNextCase.Length() > 5
9495    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9496   {
9497     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9498   }
9499   else
9500   {
9501     return theArgNext.IntegerValue();
9502   }
9503 }
9504
9505 //===============================================================================================
9506 //function : VLight
9507 //purpose  :
9508 //===============================================================================================
9509 static int VLight (Draw_Interpretor& theDi,
9510                    Standard_Integer  theArgsNb,
9511                    const char**      theArgVec)
9512 {
9513   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9514   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9515   if (aView.IsNull()
9516    || aViewer.IsNull())
9517   {
9518     std::cerr << "No active viewer!\n";
9519     return 1;
9520   }
9521
9522   Standard_Real anXYZ[3]   = {};
9523   Standard_Real anAtten[2] = {};
9524   if (theArgsNb < 2)
9525   {
9526     // print lights info
9527     Standard_Integer aLightId = 0;
9528     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9529     {
9530       Handle(V3d_Light) aLight = aLightIter.Value();
9531       const Quantity_Color aColor = aLight->Color();
9532       theDi << "Light #" << aLightId
9533             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
9534             << " [" << aLight->GetId() << "]" << "\n";
9535       switch (aLight->Type())
9536       {
9537         case V3d_AMBIENT:
9538         {
9539           theDi << "  Type:       Ambient\n";
9540           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9541           break;
9542         }
9543         case V3d_DIRECTIONAL:
9544         {
9545           theDi << "  Type:       Directional\n";
9546           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9547           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9548           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9549           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9550           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9551           break;
9552         }
9553         case V3d_POSITIONAL:
9554         {
9555           theDi << "  Type:       Positional\n";
9556           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9557           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9558           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9559           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9560           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9561           aLight->Attenuation (anAtten[0], anAtten[1]);
9562           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9563           break;
9564         }
9565         case V3d_SPOT:
9566         {
9567           theDi << "  Type:       Spot\n";
9568           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9569           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9570           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9571           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9572           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9573           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9574           aLight->Attenuation (anAtten[0], anAtten[1]);
9575           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9576           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
9577           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
9578           break;
9579         }
9580         default:
9581         {
9582           theDi << "  Type:       UNKNOWN\n";
9583           break;
9584         }
9585       }
9586       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
9587     }
9588   }
9589
9590   Handle(V3d_Light) aLightNew;
9591   Handle(V3d_Light) aLightOld;
9592   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
9593   Standard_Boolean  isGlobal = Standard_True;
9594   Standard_Boolean  toCreate = Standard_False;
9595   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9596   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9597   {
9598     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9599
9600     TCollection_AsciiString aName, aValue;
9601     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9602     TCollection_AsciiString anArgCase (anArg);
9603     anArgCase.UpperCase();
9604     if (anUpdateTool.parseRedrawMode (anArg))
9605     {
9606       continue;
9607     }
9608
9609     if (anArgCase.IsEqual ("NEW")
9610      || anArgCase.IsEqual ("ADD")
9611      || anArgCase.IsEqual ("CREATE")
9612      || anArgCase.IsEqual ("-NEW")
9613      || anArgCase.IsEqual ("-ADD")
9614      || anArgCase.IsEqual ("-CREATE"))
9615     {
9616       toCreate = Standard_True;
9617     }
9618     else if (anArgCase.IsEqual ("-LAYER")
9619           || anArgCase.IsEqual ("-ZLAYER"))
9620     {
9621       if (++anArgIt >= theArgsNb)
9622       {
9623         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9624         return 1;
9625       }
9626
9627       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
9628       aValStr.LowerCase();
9629       if (aValStr == "default"
9630        || aValStr == "def")
9631       {
9632         aLayer = Graphic3d_ZLayerId_Default;
9633       }
9634       else if (aValStr == "top")
9635       {
9636         aLayer = Graphic3d_ZLayerId_Top;
9637       }
9638       else if (aValStr == "topmost")
9639       {
9640         aLayer = Graphic3d_ZLayerId_Topmost;
9641       }
9642       else if (aValStr == "toposd"
9643             || aValStr == "osd")
9644       {
9645         aLayer = Graphic3d_ZLayerId_TopOSD;
9646       }
9647       else if (aValStr == "botosd"
9648             || aValStr == "bottom")
9649       {
9650         aLayer = Graphic3d_ZLayerId_BotOSD;
9651       }
9652       else if (aValStr.IsIntegerValue())
9653       {
9654         aLayer = Draw::Atoi (theArgVec[anArgIt]);
9655       }
9656       else
9657       {
9658         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
9659         return 1;
9660       }
9661     }
9662     else if (anArgCase.IsEqual ("GLOB")
9663           || anArgCase.IsEqual ("GLOBAL")
9664           || anArgCase.IsEqual ("-GLOB")
9665           || anArgCase.IsEqual ("-GLOBAL"))
9666     {
9667       isGlobal = Standard_True;
9668     }
9669     else if (anArgCase.IsEqual ("LOC")
9670           || anArgCase.IsEqual ("LOCAL")
9671           || anArgCase.IsEqual ("-LOC")
9672           || anArgCase.IsEqual ("-LOCAL"))
9673     {
9674       isGlobal = Standard_False;
9675     }
9676     else if (anArgCase.IsEqual ("DEF")
9677           || anArgCase.IsEqual ("DEFAULTS")
9678           || anArgCase.IsEqual ("-DEF")
9679           || anArgCase.IsEqual ("-DEFAULTS"))
9680     {
9681       toCreate = Standard_False;
9682       aViewer->SetDefaultLights();
9683     }
9684     else if (anArgCase.IsEqual ("CLR")
9685           || anArgCase.IsEqual ("CLEAR")
9686           || anArgCase.IsEqual ("-CLR")
9687           || anArgCase.IsEqual ("-CLEAR"))
9688     {
9689       toCreate = Standard_False;
9690
9691       TColStd_SequenceOfInteger aLayers;
9692       aViewer->GetAllZLayers (aLayers);
9693       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9694       {
9695         if (aLayeriter.Value() == aLayer
9696          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9697         {
9698           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9699           aSettings.SetLights (Handle(Graphic3d_LightSet)());
9700           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9701           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9702           {
9703             break;
9704           }
9705         }
9706       }
9707
9708       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9709       {
9710         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
9711         {
9712           Handle(V3d_Light) aLight = aLightIter.Value();
9713           aViewer->DelLight (aLight);
9714           aLightIter = aView->ActiveLightIterator();
9715         }
9716       }
9717     }
9718     else if (anArgCase.IsEqual ("AMB")
9719           || anArgCase.IsEqual ("AMBIENT")
9720           || anArgCase.IsEqual ("AMBLIGHT"))
9721     {
9722       if (!toCreate)
9723       {
9724         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9725         return 1;
9726       }
9727
9728       addLight (aLightNew, aLayer, isGlobal);
9729       toCreate  = Standard_False;
9730       aLightNew = new V3d_AmbientLight();
9731     }
9732     else if (anArgCase.IsEqual ("DIRECTIONAL")
9733           || anArgCase.IsEqual ("DIRLIGHT"))
9734     {
9735       if (!toCreate)
9736       {
9737         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9738         return 1;
9739       }
9740
9741       addLight (aLightNew, aLayer, isGlobal);
9742       toCreate  = Standard_False;
9743       aLightNew = new V3d_DirectionalLight();
9744     }
9745     else if (anArgCase.IsEqual ("SPOT")
9746           || anArgCase.IsEqual ("SPOTLIGHT"))
9747     {
9748       if (!toCreate)
9749       {
9750         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9751         return 1;
9752       }
9753
9754       addLight (aLightNew, aLayer, isGlobal);
9755       toCreate  = Standard_False;
9756       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
9757     }
9758     else if (anArgCase.IsEqual ("POSLIGHT")
9759           || anArgCase.IsEqual ("POSITIONAL"))
9760     {
9761       if (!toCreate)
9762       {
9763         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9764         return 1;
9765       }
9766
9767       addLight (aLightNew, aLayer, isGlobal);
9768       toCreate  = Standard_False;
9769       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
9770     }
9771     else if (anArgCase.IsEqual ("CHANGE")
9772           || anArgCase.IsEqual ("-CHANGE"))
9773     {
9774       if (++anArgIt >= theArgsNb)
9775       {
9776         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9777         return 1;
9778       }
9779
9780       addLight (aLightNew, aLayer, isGlobal);
9781       aLightNew.Nullify();
9782       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
9783       Standard_Integer aLightIt = 0;
9784       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9785       {
9786         if (aLightIt == aLightId)
9787         {
9788           aLightOld = aLightIter.Value();
9789           break;
9790         }
9791       }
9792
9793       if (aLightOld.IsNull())
9794       {
9795         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
9796         return 1;
9797       }
9798     }
9799     else if (anArgCase.IsEqual ("DEL")
9800           || anArgCase.IsEqual ("DELETE")
9801           || anArgCase.IsEqual ("-DEL")
9802           || anArgCase.IsEqual ("-DELETE"))
9803     {
9804       Handle(V3d_Light) aLightDel;
9805       if (++anArgIt >= theArgsNb)
9806       {
9807         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9808         return 1;
9809       }
9810
9811       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9812       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
9813       Standard_Integer aLightIt = 0;
9814       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9815       {
9816         aLightDel = aLightIter.Value();
9817         if (aLightIt == aLightDelId)
9818         {
9819           break;
9820         }
9821       }
9822       if (aLightDel.IsNull())
9823       {
9824         continue;
9825       }
9826
9827       TColStd_SequenceOfInteger aLayers;
9828       aViewer->GetAllZLayers (aLayers);
9829       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9830       {
9831         if (aLayeriter.Value() == aLayer
9832          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9833         {
9834           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9835           if (!aSettings.Lights().IsNull())
9836           {
9837             aSettings.Lights()->Remove (aLightDel);
9838             if (aSettings.Lights()->IsEmpty())
9839             {
9840               aSettings.SetLights (Handle(Graphic3d_LightSet)());
9841             }
9842           }
9843           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9844           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9845           {
9846             break;
9847           }
9848         }
9849       }
9850
9851       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9852       {
9853         aViewer->DelLight (aLightDel);
9854       }
9855     }
9856     else if (anArgCase.IsEqual ("COLOR")
9857           || anArgCase.IsEqual ("COLOUR")
9858           || anArgCase.IsEqual ("-COLOR")
9859           || anArgCase.IsEqual ("-COLOUR"))
9860     {
9861       if (++anArgIt >= theArgsNb
9862        || aLightCurr.IsNull())
9863       {
9864         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9865         return 1;
9866       }
9867
9868       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9869       anArgNext.UpperCase();
9870       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
9871       aLightCurr->SetColor (aColor);
9872     }
9873     else if (anArgCase.IsEqual ("POS")
9874           || anArgCase.IsEqual ("POSITION")
9875           || anArgCase.IsEqual ("-POS")
9876           || anArgCase.IsEqual ("-POSITION"))
9877     {
9878       if ((anArgIt + 3) >= theArgsNb
9879        || aLightCurr.IsNull()
9880        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9881         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9882       {
9883         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9884         return 1;
9885       }
9886
9887       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9888       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9889       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9890       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9891     }
9892     else if (anArgCase.IsEqual ("DIR")
9893           || anArgCase.IsEqual ("DIRECTION")
9894           || anArgCase.IsEqual ("-DIR")
9895           || anArgCase.IsEqual ("-DIRECTION"))
9896     {
9897       if ((anArgIt + 3) >= theArgsNb
9898        || aLightCurr.IsNull()
9899        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
9900         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9901       {
9902         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9903         return 1;
9904       }
9905
9906       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9907       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9908       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9909       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9910     }
9911     else if (anArgCase.IsEqual ("SM")
9912           || anArgCase.IsEqual ("SMOOTHNESS")
9913           || anArgCase.IsEqual ("-SM")
9914           || anArgCase.IsEqual ("-SMOOTHNESS"))
9915     {
9916       if (++anArgIt >= theArgsNb
9917        || aLightCurr.IsNull())
9918       {
9919         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9920         return 1;
9921       }
9922
9923       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9924       if (Abs (aSmoothness) <= ShortRealEpsilon())
9925       {
9926         aLightCurr->SetIntensity (1.f);
9927       }
9928       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
9929       {
9930         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
9931       }
9932       else
9933       {
9934         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
9935         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
9936       }
9937
9938       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
9939       {
9940         aLightCurr->SetSmoothRadius (aSmoothness);
9941       }
9942       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
9943       {
9944         aLightCurr->SetSmoothAngle (aSmoothness);
9945       }
9946     }
9947     else if (anArgCase.IsEqual ("INT")
9948           || anArgCase.IsEqual ("INTENSITY")
9949           || anArgCase.IsEqual ("-INT")
9950           || anArgCase.IsEqual ("-INTENSITY"))
9951     {
9952       if (++anArgIt >= theArgsNb
9953        || aLightCurr.IsNull())
9954       {
9955         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9956         return 1;
9957       }
9958
9959       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9960       aLightCurr->SetIntensity (aIntensity);
9961     }
9962     else if (anArgCase.IsEqual ("ANG")
9963           || anArgCase.IsEqual ("ANGLE")
9964           || anArgCase.IsEqual ("-ANG")
9965           || anArgCase.IsEqual ("-ANGLE"))
9966     {
9967       if (++anArgIt >= theArgsNb
9968        || aLightCurr.IsNull()
9969        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
9970       {
9971         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9972         return 1;
9973       }
9974
9975       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9976       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
9977     }
9978     else if (anArgCase.IsEqual ("CONSTATTEN")
9979           || anArgCase.IsEqual ("CONSTATTENUATION")
9980           || anArgCase.IsEqual ("-CONSTATTEN")
9981           || anArgCase.IsEqual ("-CONSTATTENUATION"))
9982     {
9983       if (++anArgIt >= theArgsNb
9984        || aLightCurr.IsNull()
9985        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9986         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9987       {
9988         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9989         return 1;
9990       }
9991
9992       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
9993       anAtten[0] = Atof (theArgVec[anArgIt]);
9994       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
9995     }
9996     else if (anArgCase.IsEqual ("LINATTEN")
9997           || anArgCase.IsEqual ("LINEARATTEN")
9998           || anArgCase.IsEqual ("LINEARATTENUATION")
9999           || anArgCase.IsEqual ("-LINATTEN")
10000           || anArgCase.IsEqual ("-LINEARATTEN")
10001           || anArgCase.IsEqual ("-LINEARATTENUATION"))
10002     {
10003       if (++anArgIt >= theArgsNb
10004        || aLightCurr.IsNull()
10005        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10006         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10007       {
10008         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10009         return 1;
10010       }
10011
10012       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10013       anAtten[1] = Atof (theArgVec[anArgIt]);
10014       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10015     }
10016     else if (anArgCase.IsEqual ("EXP")
10017           || anArgCase.IsEqual ("EXPONENT")
10018           || anArgCase.IsEqual ("SPOTEXP")
10019           || anArgCase.IsEqual ("SPOTEXPONENT")
10020           || anArgCase.IsEqual ("-EXP")
10021           || anArgCase.IsEqual ("-EXPONENT")
10022           || anArgCase.IsEqual ("-SPOTEXP")
10023           || anArgCase.IsEqual ("-SPOTEXPONENT"))
10024     {
10025       if (++anArgIt >= theArgsNb
10026        || aLightCurr.IsNull()
10027        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10028       {
10029         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10030         return 1;
10031       }
10032
10033       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
10034     }
10035     else if (anArgCase.IsEqual ("HEAD")
10036           || anArgCase.IsEqual ("HEADLIGHT")
10037           || anArgCase.IsEqual ("-HEAD")
10038           || anArgCase.IsEqual ("-HEADLIGHT"))
10039     {
10040       if (aLightCurr.IsNull()
10041        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
10042       {
10043         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10044         return 1;
10045       }
10046
10047       Standard_Boolean isHeadLight = Standard_True;
10048       if (anArgIt + 1 < theArgsNb
10049        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
10050       {
10051         ++anArgIt;
10052       }
10053       aLightCurr->SetHeadlight (isHeadLight);
10054     }
10055     else
10056     {
10057       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
10058     }
10059   }
10060
10061   addLight (aLightNew, aLayer, isGlobal);
10062   return 0;
10063 }
10064
10065 //! Read Graphic3d_RenderingParams::PerfCounters flag.
10066 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10067                                             Standard_Boolean& theToReset,
10068                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10069                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10070 {
10071   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10072   TCollection_AsciiString aVal = theValue;
10073   Standard_Boolean toReverse = Standard_False;
10074   if (aVal == "none")
10075   {
10076     theToReset = Standard_True;
10077     return Standard_True;
10078   }
10079   else if (aVal.StartsWith ("-"))
10080   {
10081     toReverse = Standard_True;
10082     aVal = aVal.SubString (2, aVal.Length());
10083   }
10084   else if (aVal.StartsWith ("no"))
10085   {
10086     toReverse = Standard_True;
10087     aVal = aVal.SubString (3, aVal.Length());
10088   }
10089   else if (aVal.StartsWith ("+"))
10090   {
10091     aVal = aVal.SubString (2, aVal.Length());
10092   }
10093   else
10094   {
10095     theToReset = Standard_True;
10096   }
10097
10098   if (     aVal == "fps"
10099         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
10100   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
10101   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
10102   else if (aVal == "structs"
10103         || aVal == "structures"
10104         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
10105   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
10106   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
10107   else if (aVal == "tris"
10108         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
10109   else if (aVal == "pnts"
10110         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
10111   else if (aVal == "mem"
10112         || aVal == "gpumem"
10113         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
10114   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
10115   else if (aVal == "extended"
10116         || aVal == "verbose"
10117         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
10118   else
10119   {
10120     return Standard_False;
10121   }
10122
10123   if (toReverse)
10124   {
10125     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
10126   }
10127   else
10128   {
10129     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
10130   }
10131   return Standard_True;
10132 }
10133
10134 //! Read Graphic3d_RenderingParams::PerfCounters flags.
10135 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
10136                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
10137 {
10138   TCollection_AsciiString aValue = theValue;
10139   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
10140   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
10141   Standard_Boolean toReset = Standard_False;
10142   for (;;)
10143   {
10144     Standard_Integer aSplitPos = aValue.Search ("|");
10145     if (aSplitPos <= 0)
10146     {
10147       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
10148       {
10149         return Standard_False;
10150       }
10151       if (toReset)
10152       {
10153         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
10154       }
10155       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
10156       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
10157       return Standard_True;
10158     }
10159
10160     if (aSplitPos > 1)
10161     {
10162       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
10163       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
10164       {
10165         return Standard_False;
10166       }
10167     }
10168     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
10169   }
10170 }
10171
10172 //=======================================================================
10173 //function : VRenderParams
10174 //purpose  : Enables/disables rendering features
10175 //=======================================================================
10176
10177 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
10178                                        Standard_Integer  theArgNb,
10179                                        const char**      theArgVec)
10180 {
10181   Handle(V3d_View) aView = ViewerTest::CurrentView();
10182   if (aView.IsNull())
10183   {
10184     std::cerr << "Error: no active viewer!\n";
10185     return 1;
10186   }
10187
10188   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
10189   TCollection_AsciiString aCmdName (theArgVec[0]);
10190   aCmdName.LowerCase();
10191   if (aCmdName == "vraytrace")
10192   {
10193     if (theArgNb == 1)
10194     {
10195       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
10196       return 0;
10197     }
10198     else if (theArgNb == 2)
10199     {
10200       TCollection_AsciiString aValue (theArgVec[1]);
10201       aValue.LowerCase();
10202       if (aValue == "on"
10203        || aValue == "1")
10204       {
10205         aParams.Method = Graphic3d_RM_RAYTRACING;
10206         aView->Redraw();
10207         return 0;
10208       }
10209       else if (aValue == "off"
10210             || aValue == "0")
10211       {
10212         aParams.Method = Graphic3d_RM_RASTERIZATION;
10213         aView->Redraw();
10214         return 0;
10215       }
10216       else
10217       {
10218         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
10219         return 1;
10220       }
10221     }
10222     else
10223     {
10224       std::cout << "Error: wrong number of arguments\n";
10225       return 1;
10226     }
10227   }
10228
10229   if (theArgNb < 2)
10230   {
10231     theDI << "renderMode:  ";
10232     switch (aParams.Method)
10233     {
10234       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10235       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
10236     }
10237     theDI << "\n";
10238     theDI << "transparency:  ";
10239     switch (aParams.TransparencyMethod)
10240     {
10241       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
10242       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
10243                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
10244     }
10245     theDI << "\n";
10246     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
10247     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
10248     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
10249     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
10250     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
10251     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
10252     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
10253     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
10254     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
10255     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
10256     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
10257     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
10258     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
10259     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
10260     theDI << "shadingModel: ";
10261     switch (aView->ShadingModel())
10262     {
10263       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
10264       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
10265       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
10266       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
10267       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
10268     }
10269     {
10270       theDI << "perfCounters:";
10271       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
10272       {
10273         theDI << " fps";
10274       }
10275       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
10276       {
10277         theDI << " cpu";
10278       }
10279       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
10280       {
10281         theDI << " structs";
10282       }
10283       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
10284       {
10285         theDI << " groups";
10286       }
10287       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
10288       {
10289         theDI << " arrays";
10290       }
10291       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
10292       {
10293         theDI << " tris";
10294       }
10295       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
10296       {
10297         theDI << " pnts";
10298       }
10299       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
10300       {
10301         theDI << " gpumem";
10302       }
10303       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
10304       {
10305         theDI << " none";
10306       }
10307       theDI << "\n";
10308     }
10309     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
10310     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
10311     theDI << "\n";
10312     return 0;
10313   }
10314
10315   Standard_Boolean toPrint = Standard_False;
10316   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10317   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10318   {
10319     Standard_CString        anArg (theArgVec[anArgIter]);
10320     TCollection_AsciiString aFlag (anArg);
10321     aFlag.LowerCase();
10322     if (anUpdateTool.parseRedrawMode (aFlag))
10323     {
10324       continue;
10325     }
10326     else if (aFlag == "-echo"
10327           || aFlag == "-print")
10328     {
10329       toPrint = Standard_True;
10330       anUpdateTool.Invalidate();
10331     }
10332     else if (aFlag == "-mode"
10333           || aFlag == "-rendermode"
10334           || aFlag == "-render_mode")
10335     {
10336       if (toPrint)
10337       {
10338         switch (aParams.Method)
10339         {
10340           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10341           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
10342         }
10343         continue;
10344       }
10345       else
10346       {
10347         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10348         return 1;
10349       }
10350     }
10351     else if (aFlag == "-ray"
10352           || aFlag == "-raytrace")
10353     {
10354       if (toPrint)
10355       {
10356         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
10357         continue;
10358       }
10359
10360       aParams.Method = Graphic3d_RM_RAYTRACING;
10361     }
10362     else if (aFlag == "-rast"
10363           || aFlag == "-raster"
10364           || aFlag == "-rasterization")
10365     {
10366       if (toPrint)
10367       {
10368         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
10369         continue;
10370       }
10371
10372       aParams.Method = Graphic3d_RM_RASTERIZATION;
10373     }
10374     else if (aFlag == "-msaa")
10375     {
10376       if (toPrint)
10377       {
10378         theDI << aParams.NbMsaaSamples << " ";
10379         continue;
10380       }
10381       else if (++anArgIter >= theArgNb)
10382       {
10383         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10384         return 1;
10385       }
10386
10387       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
10388       if (aNbSamples < 0)
10389       {
10390         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
10391         return 1;
10392       }
10393       else
10394       {
10395         aParams.NbMsaaSamples = aNbSamples;
10396       }
10397     }
10398     else if (aFlag == "-oit")
10399     {
10400       if (toPrint)
10401       {
10402         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
10403         {
10404           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
10405         }
10406         else
10407         {
10408           theDI << "off" << " ";
10409         }
10410         continue;
10411       }
10412       else if (++anArgIter >= theArgNb)
10413       {
10414         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10415         return 1;
10416       }
10417
10418       TCollection_AsciiString aParam = theArgVec[anArgIter];
10419       aParam.LowerCase();
10420       if (aParam.IsRealValue())
10421       {
10422         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10423         if (aWeight < 0.f || aWeight > 1.f)
10424         {
10425           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
10426           return 1;
10427         }
10428
10429         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
10430         aParams.OitDepthFactor     = aWeight;
10431       }
10432       else if (aParam == "off")
10433       {
10434         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
10435       }
10436       else
10437       {
10438         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10439         return 1;
10440       }
10441     }
10442     else if (aFlag == "-depthprepass")
10443     {
10444       if (toPrint)
10445       {
10446         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
10447         continue;
10448       }
10449       aParams.ToEnableDepthPrepass = Standard_True;
10450       if (anArgIter + 1 < theArgNb
10451        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
10452       {
10453         ++anArgIter;
10454       }
10455     }
10456     else if (aFlag == "-samplealphatocoverage"
10457           || aFlag == "-alphatocoverage")
10458     {
10459       if (toPrint)
10460       {
10461         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
10462         continue;
10463       }
10464       aParams.ToEnableAlphaToCoverage = Standard_True;
10465       if (anArgIter + 1 < theArgNb
10466        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
10467       {
10468         ++anArgIter;
10469       }
10470     }
10471     else if (aFlag == "-rendscale"
10472           || aFlag == "-renderscale"
10473           || aFlag == "-renderresolutionscale")
10474     {
10475       if (toPrint)
10476       {
10477         theDI << aParams.RenderResolutionScale << " ";
10478         continue;
10479       }
10480       else if (++anArgIter >= theArgNb)
10481       {
10482         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10483         return 1;
10484       }
10485
10486       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
10487       if (aScale < 0.01)
10488       {
10489         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
10490         return 1;
10491       }
10492       else
10493       {
10494         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
10495       }
10496     }
10497     else if (aFlag == "-raydepth"
10498           || aFlag == "-ray_depth")
10499     {
10500       if (toPrint)
10501       {
10502         theDI << aParams.RaytracingDepth << " ";
10503         continue;
10504       }
10505       else if (++anArgIter >= theArgNb)
10506       {
10507         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10508         return 1;
10509       }
10510
10511       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
10512
10513       // We allow RaytracingDepth be more than 10 in case of GI enabled
10514       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
10515       {
10516         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
10517         return 1;
10518       }
10519       else
10520       {
10521         aParams.RaytracingDepth = aDepth;
10522       }
10523     }
10524     else if (aFlag == "-shad"
10525           || aFlag == "-shadows")
10526     {
10527       if (toPrint)
10528       {
10529         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
10530         continue;
10531       }
10532
10533       Standard_Boolean toEnable = Standard_True;
10534       if (++anArgIter < theArgNb
10535       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10536       {
10537         --anArgIter;
10538       }
10539       aParams.IsShadowEnabled = toEnable;
10540     }
10541     else if (aFlag == "-refl"
10542           || aFlag == "-reflections")
10543     {
10544       if (toPrint)
10545       {
10546         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10547         continue;
10548       }
10549
10550       Standard_Boolean toEnable = Standard_True;
10551       if (++anArgIter < theArgNb
10552       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10553       {
10554         --anArgIter;
10555       }
10556       aParams.IsReflectionEnabled = toEnable;
10557     }
10558     else if (aFlag == "-fsaa")
10559     {
10560       if (toPrint)
10561       {
10562         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10563         continue;
10564       }
10565
10566       Standard_Boolean toEnable = Standard_True;
10567       if (++anArgIter < theArgNb
10568       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10569       {
10570         --anArgIter;
10571       }
10572       aParams.IsAntialiasingEnabled = toEnable;
10573     }
10574     else if (aFlag == "-gleam")
10575     {
10576       if (toPrint)
10577       {
10578         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10579         continue;
10580       }
10581
10582       Standard_Boolean toEnable = Standard_True;
10583       if (++anArgIter < theArgNb
10584       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10585       {
10586         --anArgIter;
10587       }
10588       aParams.IsTransparentShadowEnabled = toEnable;
10589     }
10590     else if (aFlag == "-gi")
10591     {
10592       if (toPrint)
10593       {
10594         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10595         continue;
10596       }
10597
10598       Standard_Boolean toEnable = Standard_True;
10599       if (++anArgIter < theArgNb
10600       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10601       {
10602         --anArgIter;
10603       }
10604       aParams.IsGlobalIlluminationEnabled = toEnable;
10605       if (!toEnable)
10606       {
10607         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10608       }
10609     }
10610     else if (aFlag == "-blockedrng"
10611           || aFlag == "-brng")
10612     {
10613       if (toPrint)
10614       {
10615         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10616         continue;
10617       }
10618
10619       Standard_Boolean toEnable = Standard_True;
10620       if (++anArgIter < theArgNb
10621         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10622       {
10623         --anArgIter;
10624       }
10625       aParams.CoherentPathTracingMode = toEnable;
10626     }
10627     else if (aFlag == "-maxrad")
10628     {
10629       if (toPrint)
10630       {
10631         theDI << aParams.RadianceClampingValue << " ";
10632         continue;
10633       }
10634       else if (++anArgIter >= theArgNb)
10635       {
10636         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10637         return 1;
10638       }
10639
10640       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10641       if (!aMaxRadStr.IsRealValue())
10642       {
10643         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10644         return 1;
10645       }
10646
10647       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10648       if (aMaxRadiance <= 0.0)
10649       {
10650         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10651         return 1;
10652       }
10653       else
10654       {
10655         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
10656       }
10657     }
10658     else if (aFlag == "-iss")
10659     {
10660       if (toPrint)
10661       {
10662         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
10663         continue;
10664       }
10665
10666       Standard_Boolean toEnable = Standard_True;
10667       if (++anArgIter < theArgNb
10668         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10669       {
10670         --anArgIter;
10671       }
10672       aParams.AdaptiveScreenSampling = toEnable;
10673     }
10674     else if (aFlag == "-issd")
10675     {
10676       if (toPrint)
10677       {
10678         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
10679         continue;
10680       }
10681
10682       Standard_Boolean toEnable = Standard_True;
10683       if (++anArgIter < theArgNb
10684         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10685       {
10686         --anArgIter;
10687       }
10688       aParams.ShowSamplingTiles = toEnable;
10689     }
10690     else if (aFlag == "-nbtiles")
10691     {
10692       if (toPrint)
10693       {
10694         theDI << aParams.NbRayTracingTiles << " ";
10695         continue;
10696       }
10697       else if (++anArgIter >= theArgNb)
10698       {
10699         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10700         return 1;
10701       }
10702
10703       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
10704
10705       if (aNbTiles < 64)
10706       {
10707         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
10708         std::cerr << "Specify value in range [64, 1024].\n";
10709         return 1;
10710       }
10711       else
10712       {
10713         aParams.NbRayTracingTiles = aNbTiles;
10714       }
10715     }
10716     else if (aFlag == "-env")
10717     {
10718       if (toPrint)
10719       {
10720         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
10721         continue;
10722       }
10723
10724       Standard_Boolean toEnable = Standard_True;
10725       if (++anArgIter < theArgNb
10726         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10727       {
10728         --anArgIter;
10729       }
10730       aParams.UseEnvironmentMapBackground = toEnable;
10731     }
10732     else if (aFlag == "-twoside")
10733     {
10734       if (toPrint)
10735       {
10736         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
10737         continue;
10738       }
10739
10740       Standard_Boolean toEnable = Standard_True;
10741       if (++anArgIter < theArgNb
10742         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10743       {
10744         --anArgIter;
10745       }
10746       aParams.TwoSidedBsdfModels = toEnable;
10747     }
10748     else if (aFlag == "-shademodel"
10749           || aFlag == "-shadingmodel"
10750           || aFlag == "-shading")
10751     {
10752       if (toPrint)
10753       {
10754         switch (aView->ShadingModel())
10755         {
10756           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
10757           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
10758           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
10759           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
10760           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
10761         }
10762         continue;
10763       }
10764
10765       if (++anArgIter >= theArgNb)
10766       {
10767         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10768       }
10769
10770       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
10771       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
10772        && aModel != Graphic3d_TOSM_DEFAULT)
10773       {
10774         aView->SetShadingModel (aModel);
10775       }
10776       else
10777       {
10778         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
10779         return 1;
10780       }
10781     }
10782     else if (aFlag == "-resolution")
10783     {
10784       if (++anArgIter >= theArgNb)
10785       {
10786         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10787         return 1;
10788       }
10789
10790       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
10791       if (aResolution.IsIntegerValue())
10792       {
10793         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
10794       }
10795       else
10796       {
10797         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10798         return 1;
10799       }
10800     }
10801     else if (aFlag == "-rebuildglsl"
10802           || aFlag == "-rebuild")
10803     {
10804       if (toPrint)
10805       {
10806         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
10807         continue;
10808       }
10809
10810       Standard_Boolean toEnable = Standard_True;
10811       if (++anArgIter < theArgNb
10812           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10813       {
10814         --anArgIter;
10815       }
10816       aParams.RebuildRayTracingShaders = toEnable;
10817     }
10818     else if (aFlag == "-focal")
10819     {
10820       if (++anArgIter >= theArgNb)
10821       {
10822         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10823         return 1;
10824       }
10825
10826       TCollection_AsciiString aParam (theArgVec[anArgIter]);
10827       if (aParam.IsRealValue())
10828       {
10829         float aFocalDist = static_cast<float> (aParam.RealValue());
10830         if (aFocalDist < 0)
10831         {
10832           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10833           return 1;
10834         }
10835         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
10836       }
10837       else
10838       {
10839         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10840         return 1;
10841       }
10842     }
10843     else if (aFlag == "-aperture")
10844     {
10845       if (++anArgIter >= theArgNb)
10846       {
10847         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10848         return 1;
10849       }
10850
10851       TCollection_AsciiString aParam(theArgVec[anArgIter]);
10852       if (aParam.IsRealValue())
10853       {
10854         float aApertureSize = static_cast<float> (aParam.RealValue());
10855         if (aApertureSize < 0)
10856         {
10857           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10858           return 1;
10859         }
10860         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
10861       }
10862       else
10863       {
10864         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10865         return 1;
10866       }
10867     }
10868     else if (aFlag == "-exposure")
10869     {
10870       if (++anArgIter >= theArgNb)
10871       {
10872         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10873         return 1;
10874       }
10875
10876       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
10877       if (anExposure.IsRealValue())
10878       {
10879         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
10880       }
10881       else
10882       {
10883         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10884         return 1;
10885       }
10886     }
10887     else if (aFlag == "-whitepoint")
10888     {
10889       if (++anArgIter >= theArgNb)
10890       {
10891         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10892         return 1;
10893       }
10894
10895       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
10896       if (aWhitePoint.IsRealValue())
10897       {
10898         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
10899       }
10900       else
10901       {
10902         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10903         return 1;
10904       }
10905     }
10906     else if (aFlag == "-tonemapping")
10907     {
10908       if (++anArgIter >= theArgNb)
10909       {
10910         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10911         return 1;
10912       }
10913
10914       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10915       aMode.LowerCase();
10916
10917       if (aMode == "disabled")
10918       {
10919         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
10920       }
10921       else if (aMode == "filmic")
10922       {
10923         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
10924       }
10925       else
10926       {
10927         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10928         return 1;
10929       }
10930     }
10931     else if (aFlag == "-performancestats"
10932           || aFlag == "-performancecounters"
10933           || aFlag == "-perfstats"
10934           || aFlag == "-perfcounters"
10935           || aFlag == "-stats")
10936     {
10937       if (++anArgIter >= theArgNb)
10938       {
10939         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10940         return 1;
10941       }
10942
10943       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
10944       aFlagsStr.LowerCase();
10945       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
10946       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
10947       {
10948         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10949         return 1;
10950       }
10951       aView->ChangeRenderingParams().CollectedStats = aFlags;
10952       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
10953     }
10954     else if (aFlag == "-perfupdateinterval"
10955           || aFlag == "-statsupdateinterval")
10956     {
10957       if (++anArgIter >= theArgNb)
10958       {
10959         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10960         return 1;
10961       }
10962       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
10963     }
10964     else
10965     {
10966       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
10967       return 1;
10968     }
10969   }
10970
10971   return 0;
10972 }
10973
10974 //=======================================================================
10975 //function : VProgressiveMode
10976 //purpose  :
10977 //=======================================================================
10978 #if defined(_WIN32)
10979 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
10980                                           Standard_Integer  /*theNbArgs*/,
10981                                           const char**      /*theArgs*/)
10982 {
10983   Handle(V3d_View) aView = ViewerTest::CurrentView();
10984   if (aView.IsNull())
10985   {
10986     std::cerr << "Error: no active viewer!\n";
10987     return 1;
10988   }
10989
10990   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
10991
10992   for (;;)
10993   {
10994     aView->Redraw();
10995
10996     Standard_Boolean toExit = Standard_False;
10997
10998     MSG aMsg;
10999     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
11000     {
11001       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
11002       {
11003         toExit = Standard_True;
11004       }
11005
11006       TranslateMessage (&aMsg);
11007       DispatchMessageW (&aMsg);
11008     }
11009
11010     if (toExit)
11011     {
11012       break;
11013     }
11014   }
11015
11016   return 0;
11017 }
11018 #endif
11019
11020 //=======================================================================
11021 //function : VFrustumCulling
11022 //purpose  : enables/disables view volume's culling.
11023 //=======================================================================
11024 static int VFrustumCulling (Draw_Interpretor& theDI,
11025                             Standard_Integer  theArgNb,
11026                             const char**      theArgVec)
11027 {
11028   Handle(V3d_View) aView = ViewerTest::CurrentView();
11029   if (aView.IsNull())
11030   {
11031     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
11032     return 1;
11033   }
11034
11035   if (theArgNb < 2)
11036   {
11037     theDI << (aView->IsCullingEnabled() ? "on" : "off");
11038     return 0;
11039   }
11040   else if (theArgNb != 2)
11041   {
11042     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
11043     return 1;
11044   }
11045
11046   TCollection_AsciiString aModeStr (theArgVec[1]);
11047   aModeStr.LowerCase();
11048   Standard_Boolean toEnable = 0;
11049   if (aModeStr == "on")
11050   {
11051     toEnable = 1;
11052   }
11053   else if (aModeStr == "off")
11054   {
11055     toEnable = 0;
11056   }
11057   else
11058   {
11059     toEnable = Draw::Atoi (theArgVec[1]) != 0;
11060   }
11061
11062   aView->SetFrustumCulling (toEnable);
11063   aView->Redraw();
11064   return 0;
11065 }
11066
11067 //=======================================================================
11068 //function : VXRotate
11069 //purpose  :
11070 //=======================================================================
11071 static Standard_Integer VXRotate (Draw_Interpretor& di,
11072                                    Standard_Integer argc,
11073                                    const char ** argv)
11074 {
11075   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
11076   if (aContext.IsNull())
11077   {
11078     di << argv[0] << "ERROR : use 'vinit' command before \n";
11079     return 1;
11080   }
11081   
11082   if (argc != 3)
11083   {
11084     di << "ERROR : Usage : " << argv[0] << " name angle\n";
11085     return 1;
11086   }
11087
11088   TCollection_AsciiString aName (argv[1]);
11089   Standard_Real anAngle = Draw::Atof (argv[2]);
11090
11091   // find object
11092   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
11093   Handle(AIS_InteractiveObject) anIObj;
11094   if (!aMap.Find2 (aName, anIObj))
11095   {
11096     di << "Use 'vdisplay' before\n";
11097     return 1;
11098   }
11099
11100   gp_Trsf aTransform;
11101   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
11102   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
11103
11104   aContext->SetLocation (anIObj, aTransform);
11105   aContext->UpdateCurrentViewer();
11106   return 0;
11107 }
11108
11109 //===============================================================================================
11110 //class   : ViewerTest_AISManipulator
11111 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
11112 //===============================================================================================
11113 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11114
11115 class ViewerTest_AISManipulator : public AIS_Manipulator
11116 {
11117 public:
11118
11119   ViewerTest_AISManipulator() : AIS_Manipulator()
11120   {
11121     GetMapOfAISManipulators().Add (this);
11122   }
11123
11124   virtual ~ViewerTest_AISManipulator()
11125   {
11126     GetMapOfAISManipulators().Remove (this);
11127   }
11128
11129   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11130 };
11131
11132 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11133 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11134
11135 //===============================================================================================
11136 //function : VManipulator
11137 //purpose  :
11138 //===============================================================================================
11139 static int VManipulator (Draw_Interpretor& theDi,
11140                          Standard_Integer  theArgsNb,
11141                          const char**      theArgVec)
11142 {
11143   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
11144   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
11145   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
11146   if (aView.IsNull()
11147    || aViewer.IsNull())
11148   {
11149     std::cerr << "No active viewer!\n";
11150     return 1;
11151   }
11152
11153   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
11154   Standard_Integer anArgIter = 1;
11155   for (; anArgIter < theArgsNb; ++anArgIter)
11156   {
11157     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
11158   }
11159
11160   ViewerTest_CmdParser aCmd;
11161   aCmd.AddDescription ("Manages manipulator for interactive objects:");
11162   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
11163   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
11164   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
11165   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
11166   aCmd.AddOption ("detach",         "...       - detach manipulator");
11167
11168   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
11169   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
11170   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
11171
11172   aCmd.AddOption ("move",   "... x y z - move object");
11173   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
11174   aCmd.AddOption ("scale",  "... factor - scale object");
11175
11176   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
11177   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
11178   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
11179   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
11180   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
11181   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
11182   aCmd.AddOption ("size",              "... size - set size of manipulator");
11183   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
11184
11185   aCmd.Parse (theArgsNb, theArgVec);
11186
11187   if (aCmd.HasOption ("help"))
11188   {
11189     theDi.PrintHelp (theArgVec[0]);
11190     return 0;
11191   }
11192
11193   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
11194
11195   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
11196
11197   if (aName.IsEmpty())
11198   {
11199     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
11200     return 1;
11201   }
11202
11203   // ----------------------------------
11204   // detach existing manipulator object
11205   // ----------------------------------
11206
11207   if (aCmd.HasOption ("detach"))
11208   {
11209     if (!aMapAIS.IsBound2 (aName))
11210     {
11211       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
11212       return 1;
11213     }
11214
11215     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11216     if (aManipulator.IsNull())
11217     {
11218       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11219       return 1;
11220     }
11221
11222     aManipulator->Detach();
11223     aMapAIS.UnBind2 (aName);
11224     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
11225
11226     return 0;
11227   }
11228
11229   // -----------------------------------------------
11230   // find or create manipulator if it does not exist
11231   // -----------------------------------------------
11232
11233   Handle(AIS_Manipulator) aManipulator;
11234   if (!aMapAIS.IsBound2 (aName))
11235   {
11236     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
11237
11238     aManipulator = new ViewerTest_AISManipulator();
11239     aMapAIS.Bind (aManipulator, aName);
11240   }
11241   else
11242   {
11243     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11244     if (aManipulator.IsNull())
11245     {
11246       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11247       return 1;
11248     }
11249   }
11250
11251   // -----------------------------------------
11252   // change properties of manipulator instance
11253   // -----------------------------------------
11254
11255   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
11256   {
11257     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
11258   }
11259   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
11260   {
11261     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
11262   }
11263   if (aCmd.HasOption ("followRotation", 1, Standard_True))
11264   {
11265     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
11266   }
11267   if (aCmd.HasOption ("gap", 1, Standard_True))
11268   {
11269     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
11270   }
11271   if (aCmd.HasOption ("part", 3, Standard_True))
11272   {
11273     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
11274     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
11275     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
11276     if (aMode < 1 || aMode > 3)
11277     {
11278       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
11279       return 1;
11280     }
11281
11282     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
11283   }
11284   if (aCmd.HasOption ("pos", 3, Standard_True))
11285   {
11286     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
11287     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
11288     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
11289
11290     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
11291   }
11292   if (aCmd.HasOption ("size", 1, Standard_True))
11293   {
11294     aManipulator->SetSize (aCmd.ArgFloat ("size"));
11295   }
11296   if (aCmd.HasOption ("zoomable", 1, Standard_True))
11297   {
11298     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
11299
11300     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
11301     {
11302       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
11303       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
11304     }
11305   }
11306
11307   // ---------------------------------------------------
11308   // attach, detach or access manipulator from an object
11309   // ---------------------------------------------------
11310
11311   if (aCmd.HasOption ("attach"))
11312   {
11313     // Find an object and attach manipulator to it
11314     if (!aCmd.HasOption ("attach", 1, Standard_True))
11315     {
11316       return 1;
11317     }
11318
11319     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
11320     Handle(AIS_InteractiveObject) anObject;
11321     if (!aMapAIS.Find2 (anObjName, anObject))
11322     {
11323       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
11324       return 1;
11325     }
11326
11327     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
11328     {
11329       if (anIt.Value()->IsAttached()
11330        && anIt.Value()->Object() == anObject)
11331       {
11332         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
11333         return 1;
11334       }
11335     }
11336
11337     AIS_Manipulator::OptionsForAttach anOptions;
11338     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
11339     {
11340       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
11341     }
11342     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
11343     {
11344       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
11345     }
11346     if (aCmd.HasOption ("enableModes", 1, Standard_True))
11347     {
11348       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
11349     }
11350
11351     aManipulator->Attach (anObject, anOptions);
11352   }
11353
11354   // --------------------------------------
11355   // apply transformation using manipulator
11356   // --------------------------------------
11357
11358   if (aCmd.HasOption ("startTransform", 2, Standard_True))
11359   {
11360     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
11361   }
11362   if (aCmd.HasOption ("transform", 2, Standard_True))
11363   {
11364     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
11365   }
11366   if (aCmd.HasOption ("stopTransform"))
11367   {
11368     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
11369
11370     aManipulator->StopTransform (toApply);
11371   }
11372
11373   gp_Trsf aT;
11374   if (aCmd.HasOption ("move", 3, Standard_True))
11375   {
11376     aT.SetTranslationPart (aCmd.ArgVec ("move"));
11377   }
11378   if (aCmd.HasOption ("rotate", 7, Standard_True))
11379   {
11380     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
11381   }
11382   if (aCmd.HasOption ("scale", 1))
11383   {
11384     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
11385   }
11386
11387   if (aT.Form() != gp_Identity)
11388   {
11389     aManipulator->Transform (aT);
11390   }
11391
11392   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
11393
11394   return 0;
11395 }
11396
11397 //===============================================================================================
11398 //function : VSelectionProperties
11399 //purpose  :
11400 //===============================================================================================
11401 static int VSelectionProperties (Draw_Interpretor& theDi,
11402                                  Standard_Integer  theArgsNb,
11403                                  const char**      theArgVec)
11404 {
11405   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
11406   if (aCtx.IsNull())
11407   {
11408     std::cerr << "No active viewer!\n";
11409     return 1;
11410   }
11411
11412   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
11413   {
11414     // handle obsolete alias
11415     bool toEnable = true;
11416     if (theArgsNb < 2)
11417     {
11418       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
11419       return 0;
11420     }
11421     else if (theArgsNb != 2
11422          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
11423     {
11424       std::cout << "Syntax error: wrong number of parameters.";
11425       return 1;
11426     }
11427     if (toEnable != aCtx->ToHilightSelected())
11428     {
11429       aCtx->ClearDetected();
11430       aCtx->SetToHilightSelected (toEnable);
11431     }
11432     return 0;
11433   }
11434
11435   Standard_Boolean toPrint  = theArgsNb == 1;
11436   Standard_Boolean toRedraw = Standard_False;
11437   Standard_Integer anArgIter = 1;
11438   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
11439   if (anArgIter < theArgsNb)
11440   {
11441     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
11442     anArgFirst.LowerCase();
11443     ++anArgIter;
11444     if (anArgFirst == "dynhighlight"
11445      || anArgFirst == "dynhilight"
11446      || anArgFirst == "dynamichighlight"
11447      || anArgFirst == "dynamichilight")
11448     {
11449       aType = Prs3d_TypeOfHighlight_Dynamic;
11450     }
11451     else if (anArgFirst == "localdynhighlight"
11452           || anArgFirst == "localdynhilight"
11453           || anArgFirst == "localdynamichighlight"
11454           || anArgFirst == "localdynamichilight")
11455     {
11456       aType = Prs3d_TypeOfHighlight_LocalDynamic;
11457     }
11458     else if (anArgFirst == "selhighlight"
11459           || anArgFirst == "selhilight"
11460           || anArgFirst == "selectedhighlight"
11461           || anArgFirst == "selectedhilight")
11462     {
11463       aType = Prs3d_TypeOfHighlight_Selected;
11464     }
11465     else if (anArgFirst == "localselhighlight"
11466           || anArgFirst == "localselhilight"
11467           || anArgFirst == "localselectedhighlight"
11468           || anArgFirst == "localselectedhilight")
11469     {
11470       aType = Prs3d_TypeOfHighlight_LocalSelected;
11471     }
11472     else
11473     {
11474       --anArgIter;
11475     }
11476   }
11477   for (; anArgIter < theArgsNb; ++anArgIter)
11478   {
11479     TCollection_AsciiString anArg (theArgVec[anArgIter]);
11480     anArg.LowerCase();
11481     if (anArg == "-help")
11482     {
11483       theDi.PrintHelp (theArgVec[0]);
11484       return 0;
11485     }
11486     else if (anArg == "-print")
11487     {
11488       toPrint = Standard_True;
11489     }
11490     else if (anArg == "-autoactivate")
11491     {
11492       Standard_Boolean toEnable = Standard_True;
11493       if (anArgIter + 1 < theArgsNb
11494        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11495       {
11496         ++anArgIter;
11497       }
11498       aCtx->SetAutoActivateSelection (toEnable);
11499     }
11500     else if (anArg == "-automatichighlight"
11501           || anArg == "-automatichilight"
11502           || anArg == "-autohighlight"
11503           || anArg == "-autohilight")
11504     {
11505       Standard_Boolean toEnable = Standard_True;
11506       if (anArgIter + 1 < theArgsNb
11507        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11508       {
11509         ++anArgIter;
11510       }
11511       aCtx->ClearSelected (false);
11512       aCtx->ClearDetected();
11513       aCtx->SetAutomaticHilight (toEnable);
11514       toRedraw = true;
11515     }
11516     else if (anArg == "-highlightselected"
11517           || anArg == "-hilightselected")
11518     {
11519       Standard_Boolean toEnable = Standard_True;
11520       if (anArgIter + 1 < theArgsNb
11521        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11522       {
11523         ++anArgIter;
11524       }
11525       aCtx->ClearDetected();
11526       aCtx->SetToHilightSelected (toEnable);
11527       toRedraw = true;
11528     }
11529     else if (anArg == "-pickstrategy"
11530           || anArg == "-pickingstrategy")
11531     {
11532       if (++anArgIter >= theArgsNb)
11533       {
11534         std::cout << "Syntax error: type of highlighting is undefined\n";
11535         return 1;
11536       }
11537
11538       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11539       TCollection_AsciiString aVal (theArgVec[anArgIter]);
11540       aVal.LowerCase();
11541       if (aVal == "first"
11542        || aVal == "firstaccepted"
11543        || aVal == "firstacceptable")
11544       {
11545         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11546       }
11547       else if (aVal == "topmost"
11548             || aVal == "onlyTopmost")
11549       {
11550         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
11551       }
11552       else
11553       {
11554         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
11555         return 1;
11556       }
11557
11558       aCtx->SetPickingStrategy (aStrategy);
11559     }
11560     else if (anArg == "-pixtol"
11561           && anArgIter + 1 < theArgsNb)
11562     {
11563       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
11564     }
11565     else if ((anArg == "-mode"
11566            || anArg == "-dispmode")
11567           && anArgIter + 1 < theArgsNb)
11568     {
11569       if (aType == Prs3d_TypeOfHighlight_None)
11570       {
11571         std::cout << "Syntax error: type of highlighting is undefined\n";
11572         return 1;
11573       }
11574
11575       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
11576       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11577       aStyle->SetDisplayMode (aDispMode);
11578       toRedraw = Standard_True;
11579     }
11580     else if (anArg == "-layer"
11581           && anArgIter + 1 < theArgsNb)
11582     {
11583       if (aType == Prs3d_TypeOfHighlight_None)
11584       {
11585         std::cout << "Syntax error: type of highlighting is undefined\n";
11586         return 1;
11587       }
11588
11589       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
11590       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
11591       {
11592         TColStd_SequenceOfInteger aLayers;
11593         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
11594         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
11595         {
11596           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
11597           return 1;
11598         }
11599       }
11600
11601       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11602       aStyle->SetZLayer (aNewLayer);
11603       toRedraw = Standard_True;
11604     }
11605     else if (anArg == "-hicolor"
11606           || anArg == "-selcolor"
11607           || anArg == "-color")
11608     {
11609       if (anArg.StartsWith ("-hi"))
11610       {
11611         aType = Prs3d_TypeOfHighlight_Dynamic;
11612       }
11613       else if (anArg.StartsWith ("-sel"))
11614       {
11615         aType = Prs3d_TypeOfHighlight_Selected;
11616       }
11617       else if (aType == Prs3d_TypeOfHighlight_None)
11618       {
11619         std::cout << "Syntax error: type of highlighting is undefined\n";
11620         return 1;
11621       }
11622
11623       Quantity_Color aColor;
11624       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
11625                                                            theArgVec + anArgIter + 1,
11626                                                            aColor);
11627       if (aNbParsed == 0)
11628       {
11629         std::cout << "Syntax error: need more arguments.\n";
11630         return 1;
11631       }
11632       anArgIter += aNbParsed;
11633
11634       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11635       aStyle->SetColor (aColor);
11636       toRedraw = Standard_True;
11637     }
11638     else if ((anArg == "-transp"
11639            || anArg == "-transparency"
11640            || anArg == "-hitransp"
11641            || anArg == "-seltransp"
11642            || anArg == "-hitransplocal"
11643            || anArg == "-seltransplocal")
11644           && anArgIter + 1 < theArgsNb)
11645     {
11646       if (anArg.StartsWith ("-hi"))
11647       {
11648         aType = Prs3d_TypeOfHighlight_Dynamic;
11649       }
11650       else if (anArg.StartsWith ("-sel"))
11651       {
11652         aType = Prs3d_TypeOfHighlight_Selected;
11653       }
11654       else if (aType == Prs3d_TypeOfHighlight_None)
11655       {
11656         std::cout << "Syntax error: type of highlighting is undefined\n";
11657         return 1;
11658       }
11659
11660       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
11661       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11662       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
11663       toRedraw = Standard_True;
11664     }
11665     else if ((anArg == "-mat"
11666            || anArg == "-material")
11667           && anArgIter + 1 < theArgsNb)
11668     {
11669       if (aType == Prs3d_TypeOfHighlight_None)
11670       {
11671         std::cout << "Syntax error: type of highlighting is undefined\n";
11672         return 1;
11673       }
11674
11675       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11676       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
11677       if (aMatName != Graphic3d_NOM_DEFAULT)
11678       {
11679         ++anArgIter;
11680         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
11681         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
11682         Graphic3d_MaterialAspect aMat (aMatName);
11683         aMat.SetColor (aStyle->Color());
11684         aMat.SetTransparency (aStyle->Transparency());
11685         anAspect->SetFrontMaterial (aMat);
11686         anAspect->SetInteriorColor (aStyle->Color());
11687         aStyle->SetBasicFillAreaAspect (anAspect);
11688       }
11689       else
11690       {
11691         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
11692       }
11693       toRedraw = Standard_True;
11694     }
11695     else
11696     {
11697       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
11698     }
11699   }
11700
11701   if (toPrint)
11702   {
11703     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
11704     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
11705     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
11706     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
11707     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
11708     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
11709     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
11710     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
11711     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
11712     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
11713     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
11714     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
11715     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
11716     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
11717   }
11718
11719   if (aCtx->NbSelected() != 0 && toRedraw)
11720   {
11721     aCtx->HilightSelected (Standard_True);
11722   }
11723
11724   return 0;
11725 }
11726
11727 //===============================================================================================
11728 //function : VDumpSelectionImage
11729 //purpose  :
11730 //===============================================================================================
11731 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
11732                                 Standard_Integer  theArgsNb,
11733                                 const char**      theArgVec)
11734 {
11735   if (theArgsNb < 2)
11736   {
11737     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
11738     return 1;
11739   }
11740
11741   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
11742   if (aContext.IsNull())
11743   {
11744     std::cout << "Error: no active view.\n";
11745     return 1;
11746   }
11747
11748   TCollection_AsciiString aFile;
11749   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11750   Image_Format anImgFormat = Image_Format_BGR;
11751   Standard_Integer aPickedIndex = 1;
11752   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
11753   {
11754     TCollection_AsciiString aParam (theArgVec[anArgIter]);
11755     aParam.LowerCase();
11756     if (aParam == "-type")
11757     {
11758       if (++anArgIter >= theArgsNb)
11759       {
11760         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
11761         return 1;
11762       }
11763
11764       TCollection_AsciiString aValue (theArgVec[anArgIter]);
11765       aValue.LowerCase();
11766       if (aValue == "depth"
11767        || aValue == "normdepth"
11768        || aValue == "normalizeddepth")
11769       {
11770         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11771         anImgFormat = Image_Format_GrayF;
11772       }
11773       if (aValue == "depthinverted"
11774        || aValue == "normdepthinverted"
11775        || aValue == "normalizeddepthinverted"
11776        || aValue == "inverted")
11777       {
11778         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
11779         anImgFormat = Image_Format_GrayF;
11780       }
11781       else if (aValue == "unnormdepth"
11782             || aValue == "unnormalizeddepth")
11783       {
11784         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
11785         anImgFormat = Image_Format_GrayF;
11786       }
11787       else if (aValue == "objectcolor"
11788             || aValue == "object"
11789             || aValue == "color")
11790       {
11791         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
11792       }
11793       else if (aValue == "entitycolor"
11794             || aValue == "entity")
11795       {
11796         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
11797       }
11798       else if (aValue == "ownercolor"
11799             || aValue == "owner")
11800       {
11801         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
11802       }
11803       else if (aValue == "selectionmodecolor"
11804             || aValue == "selectionmode"
11805             || aValue == "selmodecolor"
11806             || aValue == "selmode")
11807       {
11808         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
11809       }
11810     }
11811     else if (aParam == "-picked"
11812           || aParam == "-pickeddepth"
11813           || aParam == "-pickedindex")
11814     {
11815       if (++anArgIter >= theArgsNb)
11816       {
11817         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
11818         return 1;
11819       }
11820
11821       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
11822     }
11823     else if (aFile.IsEmpty())
11824     {
11825       aFile = theArgVec[anArgIter];
11826     }
11827     else
11828     {
11829       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
11830       return 1;
11831     }
11832   }
11833   if (aFile.IsEmpty())
11834   {
11835     std::cout << "Syntax error: image file name is missing.\n";
11836     return 1;
11837   }
11838
11839   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
11840   Standard_Integer aWidth = 0, aHeight = 0;
11841   aView->Window()->Size (aWidth, aHeight);
11842
11843   Image_AlienPixMap aPixMap;
11844   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
11845   {
11846     std::cout << "Error: can't allocate image.\n";
11847     return 1;
11848   }
11849   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
11850   {
11851     std::cout << "Error: can't generate selection image.\n";
11852     return 1;
11853   }
11854   if (!aPixMap.Save (aFile))
11855   {
11856     std::cout << "Error: can't save selection image.\n";
11857     return 0;
11858   }
11859   return 0;
11860 }
11861
11862 //=======================================================================
11863 //function : ViewerCommands
11864 //purpose  :
11865 //=======================================================================
11866
11867 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
11868 {
11869
11870   const char *group = "ZeViewer";
11871   theCommands.Add("vinit",
11872           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
11873     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
11874   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11875     "\n\t\t:     [-display displayName]"
11876   #endif
11877     "\n\t\t: Creates new View window with specified name viewName."
11878     "\n\t\t: By default the new view is created in the viewer and in"
11879     "\n\t\t: graphic driver shared with active view."
11880     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
11881     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
11882     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
11883 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11884     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
11885     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
11886 #endif
11887     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
11888     "\n\t\t:  -width, -height width and heigth of window respectively."
11889     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
11890     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
11891     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
11892     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
11893     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
11894     __FILE__,VInit,group);
11895   theCommands.Add("vclose" ,
11896     "[view_id [keep_context=0|1]]\n"
11897     "or vclose ALL - to remove all created views\n"
11898     " - removes view(viewer window) defined by its view_id.\n"
11899     " - keep_context: by default 0; if 1 and the last view is deleted"
11900     " the current context is not removed.",
11901     __FILE__,VClose,group);
11902   theCommands.Add("vactivate" ,
11903     "view_id"
11904     " - activates view(viewer window) defined by its view_id",
11905     __FILE__,VActivate,group);
11906   theCommands.Add("vviewlist",
11907     "vviewlist [format={tree, long}]"
11908     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
11909     " - format: format of result output, if tree the output is a tree view;"
11910     "otherwise it's a list of full view names. By default format = tree",
11911     __FILE__,VViewList,group);
11912   theCommands.Add("vhelp" ,
11913     "vhelp            : display help on the viewer commands",
11914     __FILE__,VHelp,group);
11915   theCommands.Add("vtop" ,
11916     "vtop or <T>      : Top view. Orientation +X+Y" ,
11917     __FILE__,VTop,group);
11918   theCommands.Add("vbottom" ,
11919     "vbottom          : Bottom view. Orientation +X-Y" ,
11920     __FILE__,VBottom,group);
11921   theCommands.Add("vleft" ,
11922     "vleft            : Left view. Orientation -Y+Z" ,
11923     __FILE__,VLeft,group);
11924   theCommands.Add("vright" ,
11925     "vright           : Right view. Orientation +Y+Z" ,
11926     __FILE__,VRight,group);
11927   theCommands.Add("vaxo" ,
11928     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
11929     __FILE__,VAxo,group);
11930   theCommands.Add("vfront" ,
11931     "vfront           : Front view. Orientation +X+Z" ,
11932     __FILE__,VFront,group);
11933   theCommands.Add("vback" ,
11934     "vback            : Back view. Orientation -X+Z" ,
11935     __FILE__,VBack,group);
11936   theCommands.Add("vpick" ,
11937     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
11938     VPick,group);
11939   theCommands.Add("vfit",
11940     "vfit or <F> [-selected] [-noupdate]"
11941     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
11942     __FILE__,VFit,group);
11943   theCommands.Add ("vfitarea",
11944     "vfitarea x1 y1 x2 y2"
11945     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
11946     "\n\t\t: Fit view to show area located between two points"
11947     "\n\t\t: given in world 2D or 3D corrdinates.",
11948     __FILE__, VFitArea, group);
11949   theCommands.Add ("vzfit", "vzfit [scale]\n"
11950     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
11951     "   \"scale\" - specifies factor to scale computed z range.\n",
11952     __FILE__, VZFit, group);
11953   theCommands.Add("vrepaint",
11954             "vrepaint [-immediate]"
11955     "\n\t\t: force redraw",
11956     __FILE__,VRepaint,group);
11957   theCommands.Add("vclear",
11958     "vclear          : vclear"
11959     "\n\t\t: remove all the object from the viewer",
11960     __FILE__,VClear,group);
11961   theCommands.Add("vsetbg",
11962     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
11963     __FILE__,VSetBg,group);
11964   theCommands.Add("vsetbgmode",
11965     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
11966     __FILE__,VSetBgMode,group);
11967   theCommands.Add("vsetgradientbg",
11968     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
11969     __FILE__,VSetGradientBg,group);
11970   theCommands.Add("vsetgrbgmode",
11971     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
11972     __FILE__,VSetGradientBgMode,group);
11973   theCommands.Add("vsetcolorbg",
11974     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
11975     __FILE__,VSetColorBg,group);
11976   theCommands.Add("vsetdefaultbg",
11977     "vsetdefaultbg r g b\n"
11978     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
11979     "\n\t\t: Set default viewer background fill color (flat/gradient).",
11980     __FILE__,VSetDefaultBg,group);
11981   theCommands.Add("vscale",
11982     "vscale          : vscale X Y Z",
11983     __FILE__,VScale,group);
11984   theCommands.Add("vzbufftrihedron",
11985             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
11986     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
11987     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
11988     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
11989     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
11990     "\n\t\t: Displays a trihedron",
11991     __FILE__,VZBuffTrihedron,group);
11992   theCommands.Add("vrotate",
11993     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
11994     "\n                : Option -mouseStart starts rotation according to the mouse position"
11995     "\n                : Option -mouseMove continues rotation with angle computed"
11996     "\n                : from last and new mouse position."
11997     "\n                : vrotate AX AY AZ [X Y Z]",
11998     __FILE__,VRotate,group);
11999   theCommands.Add("vzoom",
12000     "vzoom           : vzoom coef",
12001     __FILE__,VZoom,group);
12002   theCommands.Add("vpan",
12003     "vpan            : vpan dx dy",
12004     __FILE__,VPan,group);
12005   theCommands.Add("vcolorscale",
12006     "vcolorscale name [-noupdate|-update] [-demo]"
12007     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
12008     "\n\t\t:       [-font HeightFont=20]"
12009     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
12010     "\n\t\t:       [-smoothTransition {on|off}=off]"
12011     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
12012     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
12013     "\n\t\t:       [-textpos {left|right|center|none}=right]"
12014     "\n\t\t:       [-labelAtBorder {on|off}=on]"
12015     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
12016     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
12017     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
12018     "\n\t\t:       [-xy Left=0 Bottom=0]"
12019     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
12020     "\n\t\t:  -colors   - set colors for all intervals"
12021     "\n\t\t:  -color    - set color for specific interval"
12022     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
12023     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
12024     "\n\t\t:              at border means the value inbetween neighbor intervals,"
12025     "\n\t\t:              at center means the center value within current interval"
12026     "\n\t\t:  -labels   - set labels for all intervals"
12027     "\n\t\t:  -freeLabels - same as -labels but does not require"
12028     "\n\t\t:              matching the number of intervals"
12029     "\n\t\t:  -label    - set label for specific interval"
12030     "\n\t\t:  -title    - set title"
12031     "\n\t\t:  -reversed - setup smooth color transition between intervals"
12032     "\n\t\t:  -smoothTransition - swap colorscale direction"
12033     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
12034     __FILE__, VColorScale, group);
12035   theCommands.Add("vgraduatedtrihedron",
12036     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
12037     "\t[-namefont Name] [-valuesfont Name]\n"
12038     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
12039     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
12040     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
12041     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
12042     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
12043     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
12044     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
12045     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
12046     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
12047     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
12048     " - Displays or erases graduated trihedron"
12049     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
12050     " - namefont - font of axes names. Default: Arial\n"
12051     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
12052     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
12053     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
12054     " - valuesfont - font of axes values. Default: Arial\n"
12055     " - xcolor, ycolor, zcolor - color of axis and values\n"
12056     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
12057     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
12058     __FILE__,VGraduatedTrihedron,group);
12059   theCommands.Add("vtile" ,
12060             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
12061     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
12062     "\n\t\t:  -totalSize the size of virtual bigger viewport"
12063     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
12064     "\n\t\t:  -lowerLeft tile offset as lower left corner"
12065     "\n\t\t:  -upperLeft tile offset as upper left corner",
12066     __FILE__, VTile, group);
12067   theCommands.Add("vzlayer",
12068               "vzlayer [layerId]"
12069       "\n\t\t:         [-add|-delete|-get|-settings]"
12070       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
12071       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
12072       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
12073       "\n\t\t: ZLayer list management:"
12074       "\n\t\t:   -add      add new z layer to viewer and print its id"
12075       "\n\t\t:   -delete   delete z layer"
12076       "\n\t\t:   -get      print sequence of z layers"
12077       "\n\t\t:   -settings print status of z layer settings"
12078       "\n\t\t:   -disable  disables given setting"
12079       "\n\t\t:   -enable   enables  given setting",
12080     __FILE__,VZLayer,group);
12081   theCommands.Add("vlayerline",
12082     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
12083     __FILE__,VLayerLine,group);
12084   theCommands.Add ("vgrid",
12085     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
12086     " : Mode - rectangular or circular"
12087     " : Type - lines or points",
12088     __FILE__, VGrid, group);
12089   theCommands.Add ("vpriviledgedplane",
12090     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
12091     "\n\t\t:   Ox, Oy, Oz - plane origin"
12092     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
12093     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
12094     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
12095     __FILE__, VPriviledgedPlane, group);
12096   theCommands.Add ("vconvert",
12097     "vconvert v [Mode={window|view}]"
12098     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
12099     "\n\t\t: vconvert x y z [Mode={window|grid}]"
12100     "\n\t\t:   window - convert to window coordinates, pixels"
12101     "\n\t\t:   view   - convert to view projection plane"
12102     "\n\t\t:   grid   - convert to model coordinates, given on grid"
12103     "\n\t\t:   ray    - convert projection ray to model coordiantes"
12104     "\n\t\t: - vconvert v window : convert view to window;"
12105     "\n\t\t: - vconvert v view   : convert window to view;"
12106     "\n\t\t: - vconvert x y window : convert view to window;"
12107     "\n\t\t: - vconvert x y view : convert window to view;"
12108     "\n\t\t: - vconvert x y : convert window to model;"
12109     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
12110     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
12111     "\n\t\t: - vconvert x y z window : convert model to window;"
12112     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
12113     "\n\t\t: Converts the given coordinates to window/view/model space.",
12114     __FILE__, VConvert, group);
12115   theCommands.Add ("vfps",
12116     "vfps [framesNb=100] : estimate average frame rate for active view",
12117     __FILE__, VFps, group);
12118   theCommands.Add ("vgldebug",
12119             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
12120     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
12121     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
12122     "\n\t\t: Debug context can be requested only on Windows"
12123     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
12124     "\n\t\t:  -sync     - request synchronized debug GL context"
12125     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
12126     "\n\t\t:              which are suppressed by default,"
12127     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
12128     "\n\t\t:              which are suppressed by default",
12129     __FILE__, VGlDebug, group);
12130   theCommands.Add ("vvbo",
12131     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
12132     __FILE__, VVbo, group);
12133   theCommands.Add ("vstereo",
12134             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
12135     "\n\t\t:         [-anaglyph Filter]"
12136     "\n\t\t: Control stereo output mode. Available modes for -mode:"
12137     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
12138     "\n\t\t:                     requires driver support."
12139     "\n\t\t:                     Should be called BEFORE vinit!"
12140     "\n\t\t:  anaglyph         - Anaglyph glasses"
12141     "\n\t\t:  rowInterlaced    - row-interlaced display"
12142     "\n\t\t:  columnInterlaced - column-interlaced display"
12143     "\n\t\t:  chessBoard       - chess-board output"
12144     "\n\t\t:  sideBySide       - horizontal pair"
12145     "\n\t\t:  overUnder        - vertical   pair"
12146     "\n\t\t: Available Anaglyph filters for -anaglyph:"
12147     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
12148     "\n\t\t:  greenMagentaSimple",
12149     __FILE__, VStereo, group);
12150   theCommands.Add ("vcaps",
12151             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
12152     "\n\t\t:       [-compatibleProfile {0|1}]"
12153     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
12154     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
12155     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
12156     "\n\t\t: Modify particular graphic driver options:"
12157     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
12158     "\n\t\t:             built-in GLSL programs"
12159     "\n\t\t:            (requires compatible profile)"
12160     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
12161     "\n\t\t:             arrays to GPU memory)"
12162     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
12163     "\n\t\t:  vsync    - switch VSync on or off"
12164     "\n\t\t:  winBuffer - allow using window buffer for rendering"
12165     "\n\t\t: Context creation options:"
12166     "\n\t\t:  softMode          - software OpenGL implementation"
12167     "\n\t\t:  compatibleProfile - backward-compatible profile"
12168     "\n\t\t:  quadbuffer        - QuadBuffer"
12169     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
12170     "\n\t\t: rendering paths producing the same visual result when"
12171     "\n\t\t: possible."
12172     "\n\t\t: Command is intended for testing old hardware compatibility.",
12173     __FILE__, VCaps, group);
12174   theCommands.Add ("vmemgpu",
12175     "vmemgpu [f]: print system-dependent GPU memory information if available;"
12176     " with f option returns free memory in bytes",
12177     __FILE__, VMemGpu, group);
12178   theCommands.Add ("vreadpixel",
12179     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
12180     " : Read pixel value for active view",
12181     __FILE__, VReadPixel, group);
12182   theCommands.Add("diffimage",
12183             "diffimage imageFile1 imageFile2 [diffImageFile]"
12184     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
12185     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
12186     "\n\t\t: Compare two images by content and generate difference image."
12187     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
12188     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
12189     __FILE__, VDiffImage, group);
12190   theCommands.Add ("vselect",
12191     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
12192     "- emulates different types of selection:\n"
12193     "- 1) single click selection\n"
12194     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
12195     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
12196     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
12197     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
12198     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
12199     " (partial inclusion - overlap - is not allowed by default)\n"
12200     "- 5) any of these selections with shift button pressed",
12201     __FILE__, VSelect, group);
12202   theCommands.Add ("vmoveto",
12203     "vmoveto [x y] [-reset]"
12204     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
12205     "\n\t\t:   -reset resets current highlighting",
12206     __FILE__, VMoveTo, group);
12207   theCommands.Add ("vviewparams",
12208               "vviewparams [-args] [-scale [s]]"
12209       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
12210       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
12211       "\n\t\t: Manage current view parameters or prints all"
12212       "\n\t\t: current values when called without argument."
12213       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
12214       "\n\t\t:   -eye  [x y z] prints or sets eye location"
12215       "\n\t\t:   -at   [x y z] prints or sets center of look"
12216       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
12217       "\n\t\t:   -proj [x y z] prints or sets direction of look"
12218       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
12219       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
12220       "\n\t\t:                 or changes the size of its maximum dimension"
12221       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
12222     __FILE__, VViewParams, group);
12223
12224   theCommands.Add("v2dmode",
12225     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
12226     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
12227     "\n\t\t:   mode   - switches On/Off rotation mode"
12228     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
12229     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
12230     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
12231     "\n\t\t: View camera position might be changed only by commands.",
12232     __FILE__, V2DMode, group);
12233
12234   theCommands.Add("vanimation", "Alias for vanim",
12235     __FILE__, VAnimation, group);
12236
12237   theCommands.Add("vanim",
12238             "List existing animations:"
12239     "\n\t\t:  vanim"
12240     "\n\t\t: Animation playback:"
12241     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
12242     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
12243     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
12244     "\n\t\t:   -freeLook skip camera animations"
12245     "\n\t\t:   -lockLoop disable any interactions"
12246     "\n\t\t:"
12247     "\n\t\t: Animation definition:"
12248     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
12249     "\n\t\t:        [start TimeSec] [duration TimeSec]"
12250     "\n\t\t:"
12251     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
12252     "\n\t\t: specifies nested animations."
12253     "\n\t\t: There is no syntax to explicitly add new animation,"
12254     "\n\t\t: and all non-existing animations within the name will be"
12255     "\n\t\t: implicitly created on first use (including parents)."
12256     "\n\t\t:"
12257     "\n\t\t: Each animation might define the SINGLE action (see below),"
12258     "\n\t\t: like camera transition, object transformation or custom callback."
12259     "\n\t\t: Child animations can be used for defining concurrent actions."
12260     "\n\t\t:"
12261     "\n\t\t: Camera animation:"
12262     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
12263     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
12264     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
12265     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
12266     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
12267     "\n\t\t:   -atX    camera Center positions pair"
12268     "\n\t\t:   -upX    camera Up directions pair"
12269     "\n\t\t:   -scaleX camera Scale factors pair"
12270     "\n\t\t: Object animation:"
12271     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
12272     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
12273     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
12274     "\n\t\t:   -locX   object Location points pair (translation)"
12275     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
12276     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
12277     "\n\t\t: Custom callback:"
12278     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
12279     "\n\t\t:   %Pts        overall animation presentation timestamp"
12280     "\n\t\t:   %LocalPts   local animation timestamp"
12281     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
12282     "\n\t\t:"
12283     "\n\t\t: Video recording:"
12284     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
12285     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
12286     "\n\t\t:             [-crf Value] [-preset Preset]"
12287     "\n\t\t:   -fps     video framerate"
12288     "\n\t\t:   -format  file format, container (matroska, etc.)"
12289     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
12290     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
12291     "\n\t\t:   -crf     constant rate factor (specific to codec)"
12292     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
12293     __FILE__, VAnimation, group);
12294
12295   theCommands.Add("vchangeselected",
12296     "vchangeselected shape"
12297     "- adds to shape to selection or remove one from it",
12298                 __FILE__, VChangeSelected, group);
12299   theCommands.Add ("vnbselected",
12300     "vnbselected"
12301     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
12302   theCommands.Add ("vcamera",
12303               "vcamera [-ortho] [-projtype]"
12304       "\n\t\t:         [-persp]"
12305       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
12306       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
12307       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
12308       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
12309       "\n\t\t: Manage camera parameters."
12310       "\n\t\t: Prints current value when option called without argument."
12311       "\n\t\t: Orthographic camera:"
12312       "\n\t\t:   -ortho      activate orthographic projection"
12313       "\n\t\t: Perspective camera:"
12314       "\n\t\t:   -persp      activate perspective  projection (mono)"
12315       "\n\t\t:   -fovy       field of view in y axis, in degrees"
12316       "\n\t\t:   -distance   distance of eye from camera center"
12317       "\n\t\t: Stereoscopic camera:"
12318       "\n\t\t:   -stereo     perspective  projection (stereo)"
12319       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
12320       "\n\t\t:   -rightEye   perspective  projection (right eye)"
12321       "\n\t\t:   -iod        intraocular distance value"
12322       "\n\t\t:   -iodType    distance type, absolute or relative"
12323       "\n\t\t:   -zfocus     stereographic focus value"
12324       "\n\t\t:   -zfocusType focus type, absolute or relative",
12325     __FILE__, VCamera, group);
12326   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
12327     "- vautozfit [on={1|0}] [scale]\n"
12328     "    Prints or changes parameters of automatic z-fit mode:\n"
12329     "   \"on\" - turns automatic z-fit on or off\n"
12330     "   \"scale\" - specifies factor to scale computed z range.\n",
12331     __FILE__, VAutoZFit, group);
12332   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
12333     "   vzrange                - without parameters shows current values\n"
12334     "   vzrange [znear] [zfar] - applies provided values to view",
12335     __FILE__,VZRange, group);
12336   theCommands.Add ("vpurgedisplay",
12337     "vpurgedisplay"
12338     "- removes structures which don't belong to objects displayed in neutral point",
12339     __FILE__, VPurgeDisplay, group);
12340   theCommands.Add("vsetviewsize",
12341     "vsetviewsize size",
12342     __FILE__,VSetViewSize,group);
12343   theCommands.Add("vmoveview",
12344     "vmoveview Dx Dy Dz [Start = 1|0]",
12345     __FILE__,VMoveView,group);
12346   theCommands.Add("vtranslateview",
12347     "vtranslateview Dx Dy Dz [Start = 1|0)]",
12348     __FILE__,VTranslateView,group);
12349   theCommands.Add("vturnview",
12350     "vturnview Ax Ay Az [Start = 1|0]",
12351     __FILE__,VTurnView,group);
12352   theCommands.Add("vtextureenv",
12353     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
12354     "or user-defined file and optionally applying texture mapping parameters\n"
12355     "                  Usage:\n"
12356     "                  vtextureenv off - disables environment mapping\n"
12357     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
12358     "                              std_texture = (0..7)\n"
12359     "                              rep         = {clamp|repeat}\n"
12360     "                              mod         = {decal|modulate}\n"
12361     "                              flt         = {nearest|bilinear|trilinear}\n"
12362     "                              ss, st      - scale factors for s and t texture coordinates\n"
12363     "                              ts, tt      - translation for s and t texture coordinates\n"
12364     "                              rot         - texture rotation angle in degrees",
12365     __FILE__, VTextureEnv, group);
12366   theCommands.Add("vhlr",
12367             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
12368       "\n\t\t: Hidden Line Removal algorithm."
12369       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
12370       "\n\t\t:   -algoType   type of HLR algorithm.\n",
12371     __FILE__,VHLR,group);
12372   theCommands.Add("vhlrtype",
12373               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
12374       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
12375       "\n\t\t:   'algo' - exact HLR algorithm is applied"
12376       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
12377       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
12378     __FILE__,VHLRType,group);
12379   theCommands.Add("vclipplane",
12380               "vclipplane planeName [{0|1}]"
12381       "\n\t\t:   [-equation1 A B C D]"
12382       "\n\t\t:   [-equation2 A B C D]"
12383       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
12384       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
12385       "\n\t\t:   [-maxPlanes]"
12386       "\n\t\t:   [-capping {0|1}]"
12387       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
12388       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
12389       "\n\t\t:       [-texRotate Angle]"
12390       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
12391       "\n\t\t:       [-useObjShader {0|1}]"
12392       "\n\t\t: Clipping planes management:"
12393       "\n\t\t:   -maxPlanes   print plane limit for view"
12394       "\n\t\t:   -delete      delete plane with given name"
12395       "\n\t\t:   {off|on|0|1} turn clipping on/off"
12396       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
12397       "\n\t\t:                applied to active View when list is omitted"
12398       "\n\t\t:   -equation A B C D change plane equation"
12399       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
12400       "\n\t\t: Capping options:"
12401       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
12402       "\n\t\t:   -color R G B          set capping color"
12403       "\n\t\t:   -transparency Value   set capping transparency 0..1"
12404       "\n\t\t:   -texName Texture      set capping texture"
12405       "\n\t\t:   -texScale SX SY       set capping tex scale"
12406       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
12407       "\n\t\t:   -texRotate Angle      set capping tex rotation"
12408       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
12409       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
12410       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
12411       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
12412       __FILE__, VClipPlane, group);
12413   theCommands.Add("vdefaults",
12414                "vdefaults [-absDefl value]"
12415        "\n\t\t:           [-devCoeff value]"
12416        "\n\t\t:           [-angDefl value]"
12417        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
12418     , __FILE__, VDefaults, group);
12419   theCommands.Add("vlight",
12420     "tool to manage light sources, without arguments shows list of lights."
12421     "\n    Main commands: "
12422     "\n      '-clear' to clear lights"
12423     "\n      '-{def}aults' to load deafault lights"
12424     "\n      '-add' <type> to add any light source"
12425     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
12426     "\n      'change' <lightId> to edit light source with specified lightId"
12427     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
12428     "\n        -layer Id"
12429     "\n        -{pos}ition X Y Z"
12430     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
12431     "\n        -color colorName"
12432     "\n        -{head}light 0|1"
12433     "\n        -{sm}oothness value"
12434     "\n        -{int}ensity value"
12435     "\n        -{constAtten}uation value"
12436     "\n        -{linearAtten}uation value"
12437     "\n        -angle angleDeg"
12438     "\n        -{spotexp}onent value"
12439     "\n        -local|-global"
12440     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
12441     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
12442     __FILE__, VLight, group);
12443   theCommands.Add("vraytrace",
12444             "vraytrace [0|1]"
12445     "\n\t\t: Turns on/off ray-tracing renderer."
12446     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
12447     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
12448     __FILE__, VRenderParams, group);
12449   theCommands.Add("vrenderparams",
12450     "\n    Manages rendering parameters: "
12451     "\n      '-raster'                   Disables GPU ray-tracing"
12452     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
12453     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
12454     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
12455     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
12456     "\n      '-rendScale    value        Rendering resolution scale factor"
12457     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
12458     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
12459     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
12460     "\n      '-reflections  on|off'      Enables/disables specular reflections"
12461     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
12462     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
12463     "\n      '-gi           on|off'      Enables/disables global illumination effects"
12464     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
12465     "\n      '-env          on|off'      Enables/disables environment map background"
12466     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
12467     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
12468     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
12469     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
12470     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
12471     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
12472     "\n      '-shadingModel model'       Controls shading model from enumeration"
12473     "\n                                  color, flat, gouraud, phong"
12474     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
12475     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
12476     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
12477     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
12478     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
12479     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
12480     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points|gpuMem|basic|extended|nofps'"
12481     "\n                                  Show/hide performance counters (flags can be combined)"
12482     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
12483     "\n    Unlike vcaps, these parameters dramatically change visual properties."
12484     "\n    Command is intended to control presentation quality depending on"
12485     "\n    hardware capabilities and performance.",
12486     __FILE__, VRenderParams, group);
12487   theCommands.Add("vfrustumculling",
12488     "vfrustumculling [toEnable]: enables/disables objects clipping",
12489     __FILE__,VFrustumCulling,group);
12490   theCommands.Add ("vplace",
12491             "vplace dx dy"
12492     "\n\t\t: Places the point (in pixels) at the center of the window",
12493     __FILE__, VPlace, group);
12494   theCommands.Add("vxrotate",
12495     "vxrotate",
12496     __FILE__,VXRotate,group);
12497
12498     theCommands.Add("vmanipulator",
12499       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
12500       "\n    tool to create and manage AIS manipulators."
12501       "\n    Options: "
12502       "\n      '-attach AISObject'                 attach manipulator to AISObject"
12503       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
12504       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
12505       "\n      '-enableModes    {0|1}'             enable modes when attaching"
12506       "\n      '-detach'                           detach manipulator"
12507       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
12508       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
12509       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
12510       "\n      '-move x y z'                     - move attached object"
12511       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
12512       "\n      '-scale factor'                   - scale attached object"
12513       "\n      '-autoActivate      {0|1}'        - set activation on detection"
12514       "\n      '-followTranslation {0|1}'        - set following translation transform"
12515       "\n      '-followRotation    {0|1}'        - set following rotation transform"
12516       "\n      '-gap value'                      - set gap between sub-parts"
12517       "\n      '-part axis mode    {0|1}'        - set visual part"
12518       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
12519       "\n      '-size value'                     - set size of manipulator"
12520       "\n      '-zoomable {0|1}'                 - set zoom persistence",
12521     __FILE__, VManipulator, group);
12522
12523   theCommands.Add("vselprops",
12524     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
12525     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
12526     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
12527     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
12528     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
12529     "\n    -pickStrategy {first|topmost} : defines picking strategy"
12530     "\n                            'first'   to pick first acceptable (default)"
12531     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
12532     "\n    -pixTol    value        : sets up pixel tolerance"
12533     "\n    -dispMode  dispMode     : sets display mode for highlighting"
12534     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
12535     "\n    -color     {name|r g b} : sets highlight color"
12536     "\n    -transp    value        : sets transparency coefficient for highlight"
12537     "\n    -material  material     : sets highlight material"
12538     "\n    -print                  : prints current state of all mentioned parameters",
12539     __FILE__, VSelectionProperties, group);
12540   theCommands.Add ("vhighlightselected",
12541                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
12542                    __FILE__, VSelectionProperties, group);
12543
12544   theCommands.Add ("vseldump",
12545                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
12546                    "\n\t\t: Generate an image based on detection results:"
12547                    "\n\t\t:   depth       normalized depth values"
12548                    "\n\t\t:   unnormDepth unnormalized depth values"
12549                    "\n\t\t:   object      color of detected object"
12550                    "\n\t\t:   owner       color of detected owner"
12551                    "\n\t\t:   selMode     color of selection mode"
12552                    "\n\t\t:   entity      color of etected entity",
12553                    __FILE__, VDumpSelectionImage, group);
12554
12555 #if defined(_WIN32)
12556   theCommands.Add("vprogressive",
12557     "vprogressive",
12558     __FILE__, VProgressiveMode, group);
12559 #endif
12560 }