0030437: Visualization, TKV3d - add Draw command to print rendering statistics
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_CameraFrustum.hxx>
23 #include <AIS_ColorScale.hxx>
24 #include <AIS_Manipulator.hxx>
25 #include <AIS_RubberBand.hxx>
26 #include <AIS_Shape.hxx>
27 #include <AIS_InteractiveObject.hxx>
28 #include <AIS_ListOfInteractive.hxx>
29 #include <AIS_ListIteratorOfListOfInteractive.hxx>
30 #include <Aspect_Grid.hxx>
31 #include <DBRep.hxx>
32 #include <Draw_ProgressIndicator.hxx>
33 #include <Graphic3d_ArrayOfPolylines.hxx>
34 #include <Graphic3d_AspectMarker3d.hxx>
35 #include <Graphic3d_NameOfTextureEnv.hxx>
36 #include <Graphic3d_GraduatedTrihedron.hxx>
37 #include <Graphic3d_TextureEnv.hxx>
38 #include <Graphic3d_TextureParams.hxx>
39 #include <Graphic3d_TypeOfTextureFilter.hxx>
40 #include <Graphic3d_AspectFillArea3d.hxx>
41 #include <ViewerTest.hxx>
42 #include <ViewerTest_AutoUpdater.hxx>
43 #include <ViewerTest_EventManager.hxx>
44 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
45 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
46 #include <ViewerTest_CmdParser.hxx>
47 #include <V3d_AmbientLight.hxx>
48 #include <V3d_DirectionalLight.hxx>
49 #include <V3d_PositionalLight.hxx>
50 #include <V3d_SpotLight.hxx>
51 #include <Message_ProgressSentry.hxx>
52 #include <NCollection_DoubleMap.hxx>
53 #include <NCollection_List.hxx>
54 #include <NCollection_Vector.hxx>
55 #include <AIS_InteractiveContext.hxx>
56 #include <Draw_Interpretor.hxx>
57 #include <Draw.hxx>
58 #include <Draw_Appli.hxx>
59 #include <Image_AlienPixMap.hxx>
60 #include <Image_VideoRecorder.hxx>
61 #include <OpenGl_GraphicDriver.hxx>
62 #include <OSD_Timer.hxx>
63 #include <TColStd_HSequenceOfAsciiString.hxx>
64 #include <TColStd_SequenceOfInteger.hxx>
65 #include <TColStd_HSequenceOfReal.hxx>
66 #include <TColgp_Array1OfPnt2d.hxx>
67 #include <TColStd_MapOfAsciiString.hxx>
68 #include <Aspect_TypeOfLine.hxx>
69 #include <Image_Diff.hxx>
70 #include <Aspect_DisplayConnection.hxx>
71 #include <gp_Pnt.hxx>
72 #include <gp_Dir.hxx>
73 #include <gp_Pln.hxx>
74 #include <PrsMgr_PresentableObject.hxx>
75 #include <Graphic3d_ClipPlane.hxx>
76 #include <NCollection_DataMap.hxx>
77 #include <Graphic3d_Texture2Dmanual.hxx>
78 #include <Prs3d_ShadingAspect.hxx>
79 #include <Prs3d_Drawer.hxx>
80 #include <Prs3d_LineAspect.hxx>
81 #include <Prs3d_Root.hxx>
82 #include <Prs3d_Text.hxx>
83 #include <Select3D_SensitivePrimitiveArray.hxx>
84
85 #ifdef _WIN32
86 #undef DrawText
87 #endif
88
89 #include <cstdlib>
90
91 #if defined(_WIN32)
92   #include <WNT_WClass.hxx>
93   #include <WNT_Window.hxx>
94 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
95   #include <Cocoa_Window.hxx>
96 #else
97   #include <Xw_Window.hxx>
98   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
99   #include <X11/Xutil.h>
100   #include <tk.h>
101 #endif
102
103 // Auxiliary definitions
104 static const char THE_KEY_DELETE = 127;
105 static const char THE_KEY_ESCAPE = 27;
106
107 //==============================================================================
108 //  VIEWER GLOBAL VARIABLES
109 //==============================================================================
110
111 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
112 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
113
114 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
115 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
116
117 extern int VErase (Draw_Interpretor& theDI,
118                    Standard_Integer  theArgNb,
119                    const char**      theArgVec);
120
121 #if defined(_WIN32)
122 static Handle(WNT_Window)& VT_GetWindow() {
123   static Handle(WNT_Window) WNTWin;
124   return WNTWin;
125 }
126 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
127 static Handle(Cocoa_Window)& VT_GetWindow()
128 {
129   static Handle(Cocoa_Window) aWindow;
130   return aWindow;
131 }
132 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
133 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
134 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
135
136 #else
137 static Handle(Xw_Window)& VT_GetWindow(){
138   static Handle(Xw_Window) XWWin;
139   return XWWin;
140 }
141
142 static void VProcessEvents(ClientData,int);
143 #endif
144
145 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
146 {
147   static Handle(Aspect_DisplayConnection) aDisplayConnection;
148   return aDisplayConnection;
149 }
150
151 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
152 {
153   GetDisplayConnection() = theDisplayConnection;
154 }
155
156 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
157 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
158 {
159   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
160 #if defined(_WIN32)
161   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
162   if (!aWindow.IsNull())
163     return aWindow->HWindow();
164 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
165   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
166   if (!aWindow.IsNull())
167   return aWindow->XWindow();
168 #endif
169   return aWindowHandle;
170 }
171 #endif
172
173 //! Setting additional flag to store 2D mode of the View to avoid scene rotation by mouse/key events
174 class ViewerTest_V3dView : public V3d_View
175 {
176   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_V3dView, V3d_View)
177 public:
178   //! Initializes the view.
179   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType = V3d_ORTHOGRAPHIC,
180                       bool theIs2dMode = false)
181   : V3d_View (theViewer, theType), myIs2dMode (theIs2dMode) {}
182
183   //! Initializes the view by copying.
184   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
185   : V3d_View (theViewer, theView), myIs2dMode (false)
186   {
187     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (theView))
188     {
189       myIs2dMode = aV3dView->IsViewIn2DMode();
190     }
191   }
192
193   //! Returns true if 2D mode is set for the view
194   bool IsViewIn2DMode() const { return myIs2dMode; }
195
196   //! Sets 2D mode for the view
197   void SetView2DMode (bool the2dMode) { myIs2dMode = the2dMode; }
198
199 public:
200
201   //! Returns true if active view in 2D mode.
202   static bool IsCurrentViewIn2DMode()
203   {
204     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
205     {
206       return aV3dView->IsViewIn2DMode();
207     }
208     return false;
209   }
210
211   //! Set if active view in 2D mode.
212   static void SetCurrentView2DMode (bool theIs2d)
213   {
214     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
215     {
216       aV3dView->SetView2DMode (theIs2d);
217     }
218   }
219
220 private:
221
222   Standard_Boolean myIs2dMode; //!< 2D mode flag
223
224 };
225
226 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
227 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
228 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
229 static OpenGl_Caps ViewerTest_myDefaultCaps;
230
231 static void OSWindowSetup();
232
233 static struct
234 {
235   Quantity_Color FlatColor;
236   Quantity_Color GradientColor1;
237   Quantity_Color GradientColor2;
238   Aspect_GradientFillMethod FillMethod;
239 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
240
241 //==============================================================================
242 //  EVENT GLOBAL VARIABLES
243 //==============================================================================
244
245 static int Start_Rot = 0;
246 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
247 int X_Motion = 0; // Current cursor position
248 int Y_Motion = 0;
249 int X_ButtonPress = 0; // Last ButtonPress position
250 int Y_ButtonPress = 0;
251 Standard_Boolean IsDragged = Standard_False;
252 Standard_Boolean DragFirst = Standard_False;
253 Standard_Boolean TheIsAnimating = Standard_False;
254 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
255 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
256
257
258 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
259 {
260   static Handle(AIS_RubberBand) aBand;
261   if (aBand.IsNull())
262   {
263     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
264     aBand->SetDisplayMode (0);
265   }
266   return aBand;
267 }
268
269 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
270
271 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
272 {
273   static ViewerTest_MapOfAISManipulators aMap;
274   return aMap;
275 }
276
277 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
278 {
279   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
280   for (; anIt.More(); anIt.Next())
281   {
282     if (anIt.Value()->HasActiveMode())
283     {
284       return anIt.Value();
285     }
286   }
287   return NULL;
288 }
289
290 //==============================================================================
291
292 #ifdef _WIN32
293 static LRESULT WINAPI ViewerWindowProc(
294                                        HWND hwnd,
295                                        UINT uMsg,
296                                        WPARAM wParam,
297                                        LPARAM lParam );
298 static LRESULT WINAPI AdvViewerWindowProc(
299   HWND hwnd,
300   UINT uMsg,
301   WPARAM wParam,
302   LPARAM lParam );
303 #endif
304
305
306 //==============================================================================
307 //function : WClass
308 //purpose  :
309 //==============================================================================
310
311 const Handle(Standard_Transient)& ViewerTest::WClass()
312 {
313   static Handle(Standard_Transient) theWClass;
314 #if defined(_WIN32)
315   if (theWClass.IsNull())
316   {
317     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
318                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
319                                 ::LoadCursor (NULL, IDC_ARROW));
320   }
321 #endif
322   return theWClass;
323 }
324
325 //==============================================================================
326 //function : CreateName
327 //purpose  : Create numerical name for new object in theMap
328 //==============================================================================
329 template <typename ObjectType>
330 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
331                                     const TCollection_AsciiString& theDefaultString)
332 {
333   if (theObjectMap.IsEmpty())
334     return theDefaultString + TCollection_AsciiString(1);
335
336   Standard_Integer aNextKey = 1;
337   Standard_Boolean isFound = Standard_False;
338   while (!isFound)
339   {
340     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
341     // Look for objects with default names
342     if (theObjectMap.IsBound1(aStringKey))
343     {
344       aNextKey++;
345     }
346     else
347       isFound = Standard_True;
348   }
349
350   return theDefaultString + TCollection_AsciiString(aNextKey);
351 }
352
353 //==============================================================================
354 //structure : ViewerTest_Names
355 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
356 //==============================================================================
357 struct ViewerTest_Names
358 {
359 private:
360   TCollection_AsciiString myDriverName;
361   TCollection_AsciiString myViewerName;
362   TCollection_AsciiString myViewName;
363
364 public:
365
366   const TCollection_AsciiString& GetDriverName () const
367   {
368     return myDriverName;
369   }
370   void SetDriverName (const TCollection_AsciiString& theDriverName)
371   {
372     myDriverName = theDriverName;
373   }
374   const TCollection_AsciiString& GetViewerName () const
375   {
376     return myViewerName;
377   }
378   void SetViewerName (const TCollection_AsciiString& theViewerName)
379   {
380     myViewerName = theViewerName;
381   }
382   const TCollection_AsciiString& GetViewName () const
383   {
384     return myViewName;
385   }
386   void SetViewName (const TCollection_AsciiString& theViewName)
387   {
388     myViewName = theViewName;
389   }
390
391   //===========================================================================
392   //function : Constructor for ViewerTest_Names
393   //purpose  : Get view, viewer, driver names from custom string
394   //===========================================================================
395
396   ViewerTest_Names (const TCollection_AsciiString& theInputString)
397   {
398     TCollection_AsciiString aName(theInputString);
399     if (theInputString.IsEmpty())
400     {
401       // Get current configuration
402       if (ViewerTest_myDrivers.IsEmpty())
403         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
404           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
405       else
406         myDriverName = ViewerTest_myDrivers.Find2
407         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
408
409       if(ViewerTest_myContexts.IsEmpty())
410       {
411         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
412           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
413       }
414       else
415       {
416         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
417       }
418
419       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
420     }
421     else
422     {
423       // There is at least view name
424       Standard_Integer aParserNumber = 0;
425       for (Standard_Integer i = 0; i < 3; ++i)
426       {
427         Standard_Integer aParserPos = aName.SearchFromEnd("/");
428         if(aParserPos != -1)
429         {
430           aParserNumber++;
431           aName.Split(aParserPos-1);
432         }
433         else
434           break;
435       }
436       if (aParserNumber == 0)
437       {
438         // Only view name
439         if (!ViewerTest::GetAISContext().IsNull())
440         {
441           myDriverName = ViewerTest_myDrivers.Find2
442           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
443           myViewerName = ViewerTest_myContexts.Find2
444           (ViewerTest::GetAISContext());
445         }
446         else
447         {
448           // There is no opened contexts here, need to create names for viewer and driver
449           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
450             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
451
452           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
453             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
454         }
455         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
456       }
457       else if (aParserNumber == 1)
458       {
459         // Here is viewerName/viewName
460         if (!ViewerTest::GetAISContext().IsNull())
461           myDriverName = ViewerTest_myDrivers.Find2
462           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
463         else
464         {
465           // There is no opened contexts here, need to create name for driver
466           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
467             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
468         }
469         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
470
471         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
472       }
473       else
474       {
475         //Here is driverName/viewerName/viewName
476         myDriverName = TCollection_AsciiString(aName);
477
478         TCollection_AsciiString aViewerName(theInputString);
479         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
480         myViewerName = TCollection_AsciiString(aViewerName);
481
482         myViewName = TCollection_AsciiString(theInputString);
483       }
484     }
485   }
486 };
487
488 //==============================================================================
489 //function : FindContextByView
490 //purpose  : Find AIS_InteractiveContext by View
491 //==============================================================================
492
493 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
494 {
495   Handle(AIS_InteractiveContext) anAISContext;
496
497   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
498        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
499   {
500     if (anIter.Value()->CurrentViewer() == theView->Viewer())
501        return anIter.Key2();
502   }
503   return anAISContext;
504 }
505
506
507 //==============================================================================
508 //function : SetWindowTitle
509 //purpose  : Set window title
510 //==============================================================================
511
512 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
513                      Standard_CString theTitle)
514 {
515 #if defined(_WIN32)
516   const TCollection_ExtendedString theTitleW (theTitle);
517   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
518 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
519   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
520 #else
521   if(GetDisplayConnection()->GetDisplay())
522   {
523     Window aWindow =
524       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
525     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
526   }
527 #endif
528 }
529
530 //==============================================================================
531 //function : IsWindowOverlapped
532 //purpose  : Check if theWindow overlapp another view
533 //==============================================================================
534
535 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
536                                      const Standard_Integer thePxTop,
537                                      const Standard_Integer thePxRight,
538                                      const Standard_Integer thePxBottom,
539                                      TCollection_AsciiString& theViewId)
540 {
541   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
542       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
543   {
544     Standard_Integer aTop = 0,
545       aLeft = 0,
546       aRight = 0,
547       aBottom = 0;
548     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
549     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
550         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
551         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
552         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
553     {
554       theViewId = anIter.Key1();
555       return Standard_True;
556     }
557   }
558   return Standard_False;
559 }
560
561 // Workaround: to create and delete non-orthographic views outside ViewerTest
562 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
563 {
564   ViewerTest_myViews.UnBind1 (theName);
565 }
566
567 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
568                                const Handle(V3d_View)& theView)
569 {
570   ViewerTest_myViews.Bind (theName, theView);
571 }
572
573 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
574 {
575   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
576 }
577 //==============================================================================
578 //function : ViewerInit
579 //purpose  : Create the window viewer and initialize all the global variable
580 //==============================================================================
581
582 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
583                                                 const Standard_Integer thePxTop,
584                                                 const Standard_Integer thePxWidth,
585                                                 const Standard_Integer thePxHeight,
586                                                 const TCollection_AsciiString& theViewName,
587                                                 const TCollection_AsciiString& theDisplayName,
588                                                 const Handle(V3d_View)& theViewToClone)
589 {
590   // Default position and dimension of the viewer window.
591   // Note that left top corner is set to be sufficiently small to have
592   // window fit in the small screens (actual for remote desktops, see #23003).
593   // The position corresponds to the window's client area, thus some
594   // gap is added for window frame to be visible.
595   Standard_Integer aPxLeft   = 20;
596   Standard_Integer aPxTop    = 40;
597   Standard_Integer aPxWidth  = 409;
598   Standard_Integer aPxHeight = 409;
599   Standard_Boolean toCreateViewer = Standard_False;
600   if (!theViewToClone.IsNull())
601   {
602     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
603   }
604
605   Handle(OpenGl_GraphicDriver) aGraphicDriver;
606   ViewerTest_Names aViewNames(theViewName);
607   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
608     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
609
610   if (thePxLeft != 0)
611     aPxLeft = thePxLeft;
612   if (thePxTop != 0)
613     aPxTop = thePxTop;
614   if (thePxWidth != 0)
615     aPxWidth = thePxWidth;
616   if (thePxHeight != 0)
617     aPxHeight = thePxHeight;
618
619   // Get graphic driver (create it or get from another view)
620   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
621   {
622     // Get connection string
623   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
624     TCollection_AsciiString aDisplayName(theDisplayName);
625     if (!aDisplayName.IsEmpty())
626       SetDisplayConnection (new Aspect_DisplayConnection ());
627     else
628       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
629   #else
630     (void)theDisplayName; // avoid warning on unused argument
631     SetDisplayConnection (new Aspect_DisplayConnection ());
632   #endif
633
634     if (Draw_VirtualWindows)
635     {
636       // don't waste the time waiting for VSync when window is not displayed on the screen
637       ViewerTest_myDefaultCaps.swapInterval = 0;
638       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
639       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
640     }
641     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
642     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
643
644     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
645     toCreateViewer = Standard_True;
646   }
647   else
648   {
649     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
650   }
651
652   //Dispose the window if input parameters are default
653   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
654   {
655     Standard_Integer aTop = 0,
656                      aLeft = 0,
657                      aRight = 0,
658                      aBottom = 0,
659                      aScreenWidth = 0,
660                      aScreenHeight = 0;
661
662     // Get screen resolution
663 #if defined(_WIN32) || defined(__WIN32__)
664     RECT aWindowSize;
665     GetClientRect(GetDesktopWindow(), &aWindowSize);
666     aScreenHeight = aWindowSize.bottom;
667     aScreenWidth = aWindowSize.right;
668 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
669     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
670 #else
671     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
672     aScreenWidth = WidthOfScreen(aScreen);
673     aScreenHeight = HeightOfScreen(aScreen);
674 #endif
675
676     TCollection_AsciiString anOverlappedViewId("");
677
678     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
679     {
680       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
681
682       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
683         && aRight + 2*aPxWidth + 40 > aScreenWidth)
684       {
685         if (aBottom + aPxHeight + 40 > aScreenHeight)
686         {
687           aPxLeft = 20;
688           aPxTop = 40;
689           break;
690         }
691         aPxLeft = 20;
692         aPxTop = aBottom + 40;
693       }
694       else
695         aPxLeft = aRight + 20;
696     }
697   }
698
699   // Get viewer name
700   TCollection_AsciiString aTitle("3D View - ");
701   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
702
703   // Change name of current active window
704   if (!ViewerTest::CurrentView().IsNull())
705   {
706     TCollection_AsciiString anActiveWindowTitle("3D View - ");
707     anActiveWindowTitle = anActiveWindowTitle
708       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
709     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
710   }
711
712   // Create viewer
713   Handle(V3d_Viewer) a3DViewer;
714   // If it's the single view, we first look for empty context
715   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
716   {
717     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
718       anIter(ViewerTest_myContexts);
719     if (anIter.More())
720       ViewerTest::SetAISContext (anIter.Value());
721     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
722   }
723   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
724   {
725     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
726     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
727   }
728   else if (a3DViewer.IsNull())
729   {
730     toCreateViewer = Standard_True;
731     a3DViewer = new V3d_Viewer(aGraphicDriver);
732     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
733     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
734                                            ViewerTest_DefaultBackground.GradientColor2,
735                                            ViewerTest_DefaultBackground.FillMethod);
736   }
737
738   // AIS context setup
739   if (ViewerTest::GetAISContext().IsNull() ||
740       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
741   {
742     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
743     ViewerTest::SetAISContext (aContext);
744     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
745   }
746   else
747   {
748     ViewerTest::ResetEventManager();
749   }
750
751   // Create window
752 #if defined(_WIN32)
753   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
754                                     Handle(WNT_WClass)::DownCast (WClass()),
755                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
756                                     aPxLeft, aPxTop,
757                                     aPxWidth, aPxHeight,
758                                     Quantity_NOC_BLACK);
759 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
760   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
761                                      aPxLeft, aPxTop,
762                                      aPxWidth, aPxHeight);
763   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
764 #else
765   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
766                                   aTitle.ToCString(),
767                                   aPxLeft, aPxTop,
768                                   aPxWidth, aPxHeight);
769 #endif
770   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
771
772   // View setup
773   Handle(V3d_View) aView;
774   if (!theViewToClone.IsNull())
775   {
776     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
777   }
778   else
779   {
780     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
781   }
782
783   aView->SetWindow (VT_GetWindow());
784   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
785
786   ViewerTest::CurrentView(aView);
787   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
788
789   // Setup for X11 or NT
790   OSWindowSetup();
791
792   // Set parameters for V3d_View and V3d_Viewer
793   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
794   aV3dView->SetComputedMode(Standard_False);
795
796   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
797   if (toCreateViewer)
798   {
799     a3DViewer->SetDefaultLights();
800     a3DViewer->SetLightOn();
801   }
802
803   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
804   #if TCL_MAJOR_VERSION  < 8
805   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
806       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
807   #else
808   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
809       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
810   #endif
811   #endif
812
813   VT_GetWindow()->Map();
814
815   // Set the handle of created view in the event manager
816   ViewerTest::ResetEventManager();
817
818   ViewerTest::CurrentView()->Redraw();
819
820   aView.Nullify();
821   a3DViewer.Nullify();
822
823   return aViewNames.GetViewName();
824 }
825
826 //==============================================================================
827 //function : RedrawAllViews
828 //purpose  : Redraw all created views
829 //==============================================================================
830 void ViewerTest::RedrawAllViews()
831 {
832   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
833   for (; aViewIt.More(); aViewIt.Next())
834   {
835     const Handle(V3d_View)& aView = aViewIt.Key2();
836     aView->Redraw();
837   }
838 }
839
840 //==============================================================================
841 //function : Vinit
842 //purpose  : Create the window viewer and initialize all the global variable
843 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
844 //==============================================================================
845
846 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
847 {
848   TCollection_AsciiString aViewName, aDisplayName;
849   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
850   Handle(V3d_View) aCopyFrom;
851   TCollection_AsciiString aName, aValue;
852   int is2dMode = -1;
853   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
854   {
855     const TCollection_AsciiString anArg = theArgVec[anArgIt];
856     TCollection_AsciiString anArgCase = anArg;
857     anArgCase.LowerCase();
858     if (anArgIt + 1 < theArgsNb
859      && anArgCase == "-name")
860     {
861       aViewName = theArgVec[++anArgIt];
862     }
863     else if (anArgIt + 1 < theArgsNb
864           && (anArgCase == "-left"
865            || anArgCase == "-l"))
866     {
867       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
868     }
869     else if (anArgIt + 1 < theArgsNb
870           && (anArgCase == "-top"
871            || anArgCase == "-t"))
872     {
873       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
874     }
875     else if (anArgIt + 1 < theArgsNb
876           && (anArgCase == "-width"
877            || anArgCase == "-w"))
878     {
879       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
880     }
881     else if (anArgIt + 1 < theArgsNb
882           && (anArgCase == "-height"
883            || anArgCase == "-h"))
884     {
885       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
886     }
887     else if (anArgCase == "-exitonclose")
888     {
889       Draw_ToExitOnCloseView = true;
890       if (anArgIt + 1 < theArgsNb
891        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
892       {
893         ++anArgIt;
894       }
895     }
896     else if (anArgCase == "-closeonescape"
897           || anArgCase == "-closeonesc")
898     {
899       Draw_ToCloseViewOnEsc = true;
900       if (anArgIt + 1 < theArgsNb
901        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
902       {
903         ++anArgIt;
904       }
905     }
906     else if (anArgCase == "-2d_mode"
907           || anArgCase == "-2dmode"
908           || anArgCase == "-2d")
909     {
910       bool toEnable = true;
911       if (anArgIt + 1 < theArgsNb
912        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
913       {
914         ++anArgIt;
915       }
916       is2dMode = toEnable ? 1 : 0;
917     }
918     else if (anArgIt + 1 < theArgsNb
919           && (anArgCase == "-disp"
920            || anArgCase == "-display"))
921     {
922       aDisplayName = theArgVec[++anArgIt];
923     }
924     else if (!ViewerTest::CurrentView().IsNull()
925           &&  aCopyFrom.IsNull()
926           && (anArgCase == "-copy"
927            || anArgCase == "-clone"
928            || anArgCase == "-cloneactive"
929            || anArgCase == "-cloneactiveview"))
930     {
931       aCopyFrom = ViewerTest::CurrentView();
932     }
933     // old syntax
934     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
935     {
936       aName.LowerCase();
937       if (aName == "name")
938       {
939         aViewName = aValue;
940       }
941       else if (aName == "l"
942             || aName == "left")
943       {
944         aPxLeft = aValue.IntegerValue();
945       }
946       else if (aName == "t"
947             || aName == "top")
948       {
949         aPxTop = aValue.IntegerValue();
950       }
951       else if (aName == "disp"
952             || aName == "display")
953       {
954         aDisplayName = aValue;
955       }
956       else if (aName == "w"
957             || aName == "width")
958       {
959         aPxWidth = aValue.IntegerValue();
960       }
961       else if (aName == "h"
962             || aName == "height")
963       {
964         aPxHeight = aValue.IntegerValue();
965       }
966       else
967       {
968         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
969         return 1;
970       }
971     }
972     else if (aViewName.IsEmpty())
973     {
974       aViewName = anArg;
975     }
976     else
977     {
978       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
979       return 1;
980     }
981   }
982
983 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
984   if (!aDisplayName.IsEmpty())
985   {
986     aDisplayName.Clear();
987     std::cout << "Warning: display parameter will be ignored.\n";
988   }
989 #endif
990
991   ViewerTest_Names aViewNames (aViewName);
992   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
993   {
994     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
995     theDi.Eval (aCommand.ToCString());
996     if (is2dMode != -1)
997     {
998       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
999     }
1000     return 0;
1001   }
1002
1003   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
1004                                                             aViewName, aDisplayName, aCopyFrom);
1005   if (is2dMode != -1)
1006   {
1007     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1008   }
1009   theDi << aViewId;
1010   return 0;
1011 }
1012
1013 //! Parse HLR algo type.
1014 static Standard_Boolean parseHlrAlgoType (const char* theName,
1015                                           Prs3d_TypeOfHLR& theType)
1016 {
1017   TCollection_AsciiString aName (theName);
1018   aName.LowerCase();
1019   if (aName == "polyalgo")
1020   {
1021     theType = Prs3d_TOH_PolyAlgo;
1022   }
1023   else if (aName == "algo")
1024   {
1025     theType = Prs3d_TOH_Algo;
1026   }
1027   else
1028   {
1029     return Standard_False;
1030   }
1031   return Standard_True;
1032 }
1033
1034 //==============================================================================
1035 //function : VHLR
1036 //purpose  : hidden lines removal algorithm
1037 //==============================================================================
1038
1039 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1040 {
1041   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1042   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1043   if (aView.IsNull())
1044   {
1045     std::cerr << "Error: No opened viewer!\n";
1046     return 1;
1047   }
1048
1049   Standard_Boolean hasHlrOnArg = Standard_False;
1050   Standard_Boolean hasShowHiddenArg = Standard_False;
1051   Standard_Boolean isHLROn = Standard_False;
1052   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
1053   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
1054   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1055   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1056   {
1057     TCollection_AsciiString anArg (argv[anArgIter]);
1058     anArg.LowerCase();
1059     if (anUpdateTool.parseRedrawMode (anArg))
1060     {
1061       continue;
1062     }
1063     else if (anArg == "-showhidden"
1064           && anArgIter + 1 < argc
1065           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
1066     {
1067       ++anArgIter;
1068       hasShowHiddenArg = Standard_True;
1069       continue;
1070     }
1071     else if ((anArg == "-type"
1072            || anArg == "-algo"
1073            || anArg == "-algotype")
1074           && anArgIter + 1 < argc
1075           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1076     {
1077       ++anArgIter;
1078       continue;
1079     }
1080     else if (!hasHlrOnArg
1081           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
1082     {
1083       hasHlrOnArg = Standard_True;
1084       continue;
1085     }
1086     // old syntax
1087     else if (!hasShowHiddenArg
1088           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
1089     {
1090       hasShowHiddenArg = Standard_True;
1091       continue;
1092     }
1093     else
1094     {
1095       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
1096       return 1;
1097     }
1098   }
1099   if (!hasHlrOnArg)
1100   {
1101     di << "HLR:        " << aView->ComputedMode() << "\n";
1102     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1103     di << "HlrAlgo:    ";
1104     switch (aCtx->DefaultDrawer()->TypeOfHLR())
1105     {
1106       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
1107       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1108       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
1109     }
1110     anUpdateTool.Invalidate();
1111     return 0;
1112   }
1113
1114   Standard_Boolean toRecompute = Standard_False;
1115   if (aTypeOfHLR != Prs3d_TOH_NotSet
1116    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
1117   {
1118     toRecompute = Standard_True;
1119     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1120   }
1121   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1122   {
1123     toRecompute = Standard_True;
1124     if (toShowHidden)
1125     {
1126       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
1127     }
1128     else
1129     {
1130       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
1131     }
1132   }
1133
1134   // redisplay shapes
1135   if (aView->ComputedMode() && isHLROn && toRecompute)
1136   {
1137     AIS_ListOfInteractive aListOfShapes;
1138     aCtx->DisplayedObjects (aListOfShapes);
1139     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
1140     {
1141       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
1142       {
1143         aCtx->Redisplay (aShape, Standard_False);
1144       }
1145     }
1146   }
1147
1148   aView->SetComputedMode (isHLROn);
1149   return 0;
1150 }
1151
1152 //==============================================================================
1153 //function : VHLRType
1154 //purpose  : change type of using HLR algorithm
1155 //==============================================================================
1156
1157 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1158 {
1159   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1160   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1161   if (aView.IsNull())
1162   {
1163     std::cerr << "Error: No opened viewer!\n";
1164     return 1;
1165   }
1166
1167   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1168   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1169   AIS_ListOfInteractive aListOfShapes;
1170   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1171   {
1172     TCollection_AsciiString anArg (argv[anArgIter]);
1173     anArg.LowerCase();
1174     if (anUpdateTool.parseRedrawMode (anArg))
1175     {
1176       continue;
1177     }
1178     else if ((anArg == "-type"
1179            || anArg == "-algo"
1180            || anArg == "-algotype")
1181           && anArgIter + 1 < argc
1182           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1183     {
1184       ++anArgIter;
1185       continue;
1186     }
1187     // old syntax
1188     else if (aTypeOfHLR == Prs3d_TOH_NotSet
1189           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1190     {
1191       continue;
1192     }
1193     else
1194     {
1195       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1196       TCollection_AsciiString aName (argv[anArgIter]);
1197       if (!aMap.IsBound2 (aName))
1198       {
1199         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
1200         return 1;
1201       }
1202
1203       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1204       if (aShape.IsNull())
1205       {
1206         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
1207         return 1;
1208       }
1209       aListOfShapes.Append (aShape);
1210       continue;
1211     }
1212   }
1213   if (aTypeOfHLR == Prs3d_TOH_NotSet)
1214   {
1215     std::cout << "Syntax error: wrong number of arguments!\n";
1216     return 1;
1217   }
1218
1219   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1220   if (isGlobal)
1221   {
1222     aCtx->DisplayedObjects (aListOfShapes);
1223     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1224   }
1225
1226   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1227   {
1228     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1229     if (aShape.IsNull())
1230     {
1231       continue;
1232     }
1233
1234     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1235                             && aView->ComputedMode();
1236     if (!isGlobal
1237      || aShape->TypeOfHLR() != aTypeOfHLR)
1238     {
1239       aShape->SetTypeOfHLR (aTypeOfHLR);
1240     }
1241     if (toUpdateShape)
1242     {
1243       aCtx->Redisplay (aShape, Standard_False);
1244     }
1245   }
1246   return 0;
1247 }
1248
1249 //==============================================================================
1250 //function : FindViewIdByWindowHandle
1251 //purpose  : Find theView Id in the map of views by window handle
1252 //==============================================================================
1253 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1254 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1255 {
1256   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1257        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1258   {
1259     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1260     if (aWindowHandle == theWindowHandle)
1261       return anIter.Key1();
1262   }
1263   return TCollection_AsciiString("");
1264 }
1265 #endif
1266
1267 //==============================================================================
1268 //function : ActivateView
1269 //purpose  : Make the view active
1270 //==============================================================================
1271
1272 void ActivateView (const TCollection_AsciiString& theViewName)
1273 {
1274   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1275   if (!aView.IsNull())
1276   {
1277     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1278     if (!anAISContext.IsNull())
1279     {
1280       if (!ViewerTest::CurrentView().IsNull())
1281       {
1282         TCollection_AsciiString aTitle("3D View - ");
1283         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1284         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1285       }
1286
1287       ViewerTest::CurrentView (aView);
1288       ViewerTest::SetAISContext (anAISContext);
1289       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
1290       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1291 #if defined(_WIN32)
1292       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1293 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1294       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1295 #else
1296       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1297 #endif
1298       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1299       ViewerTest::CurrentView()->Redraw();
1300     }
1301   }
1302 }
1303
1304 //==============================================================================
1305 //function : RemoveView
1306 //purpose  :
1307 //==============================================================================
1308 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1309                              const Standard_Boolean  theToRemoveContext)
1310 {
1311   if (!ViewerTest_myViews.IsBound2 (theView))
1312   {
1313     return;
1314   }
1315
1316   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1317   RemoveView (aViewName, theToRemoveContext);
1318 }
1319
1320 //==============================================================================
1321 //function : RemoveView
1322 //purpose  : Close and remove view from display, clear maps if neccessary
1323 //==============================================================================
1324 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1325 {
1326   if (!ViewerTest_myViews.IsBound1(theViewName))
1327   {
1328     cout << "Wrong view name\n";
1329     return;
1330   }
1331
1332   // Activate another view if it's active now
1333   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1334   {
1335     if (ViewerTest_myViews.Extent() > 1)
1336     {
1337       TCollection_AsciiString aNewViewName;
1338       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1339            anIter.More(); anIter.Next())
1340       {
1341         if (anIter.Key1() != theViewName)
1342         {
1343           aNewViewName = anIter.Key1();
1344           break;
1345         }
1346       }
1347       ActivateView (aNewViewName);
1348     }
1349     else
1350     {
1351       Handle(V3d_View) anEmptyView;
1352 #if defined(_WIN32) || defined(__WIN32__)
1353       Handle(WNT_Window) anEmptyWindow;
1354 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1355       Handle(Cocoa_Window) anEmptyWindow;
1356 #else
1357       Handle(Xw_Window) anEmptyWindow;
1358 #endif
1359       VT_GetWindow() = anEmptyWindow;
1360       ViewerTest::CurrentView (anEmptyView);
1361       if (isContextRemoved)
1362       {
1363         Handle(AIS_InteractiveContext) anEmptyContext;
1364         ViewerTest::SetAISContext(anEmptyContext);
1365       }
1366     }
1367   }
1368
1369   // Delete view
1370   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1371   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1372
1373   // Remove view resources
1374   ViewerTest_myViews.UnBind1(theViewName);
1375   aView->Window()->Unmap();
1376   aView->Remove();
1377
1378 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1379   XFlush (GetDisplayConnection()->GetDisplay());
1380 #endif
1381
1382   // Keep context opened only if the closed view is last to avoid
1383   // unused empty contexts
1384   if (!aCurrentContext.IsNull())
1385   {
1386     // Check if there are more difined views in the viewer
1387     aCurrentContext->CurrentViewer()->InitDefinedViews();
1388     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1389     {
1390       // Remove driver if there is no viewers that use it
1391       Standard_Boolean isRemoveDriver = Standard_True;
1392       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1393           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1394       {
1395         if (aCurrentContext != anIter.Key2() &&
1396           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1397         {
1398           isRemoveDriver = Standard_False;
1399           break;
1400         }
1401       }
1402
1403       aCurrentContext->RemoveAll (Standard_False);
1404       if(isRemoveDriver)
1405       {
1406         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1407       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1408         #if TCL_MAJOR_VERSION  < 8
1409         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1410         #else
1411         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1412         #endif
1413       #endif
1414       }
1415
1416       ViewerTest_myContexts.UnBind2(aCurrentContext);
1417     }
1418   }
1419   cout << "3D View - " << theViewName << " was deleted.\n";
1420   if (Draw_ToExitOnCloseView)
1421   {
1422     Draw_Interprete ("exit");
1423   }
1424 }
1425
1426 //==============================================================================
1427 //function : VClose
1428 //purpose  : Remove the view defined by its name
1429 //==============================================================================
1430
1431 static int VClose (Draw_Interpretor& /*theDi*/,
1432                    Standard_Integer  theArgsNb,
1433                    const char**      theArgVec)
1434 {
1435   NCollection_List<TCollection_AsciiString> aViewList;
1436   if (theArgsNb > 1)
1437   {
1438     TCollection_AsciiString anArg (theArgVec[1]);
1439     anArg.UpperCase();
1440     if (anArg.IsEqual ("ALL")
1441      || anArg.IsEqual ("*"))
1442     {
1443       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1444            anIter.More(); anIter.Next())
1445       {
1446         aViewList.Append (anIter.Key1());
1447       }
1448       if (aViewList.IsEmpty())
1449       {
1450         std::cout << "No view to close\n";
1451         return 0;
1452       }
1453     }
1454     else
1455     {
1456       ViewerTest_Names aViewName (theArgVec[1]);
1457       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1458       {
1459         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1460         return 1;
1461       }
1462       aViewList.Append (aViewName.GetViewName());
1463     }
1464   }
1465   else
1466   {
1467     // close active view
1468     if (ViewerTest::CurrentView().IsNull())
1469     {
1470       std::cerr << "No active view!\n";
1471       return 1;
1472     }
1473     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1474   }
1475
1476   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1477   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1478        anIter.More(); anIter.Next())
1479   {
1480     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1481   }
1482
1483   return 0;
1484 }
1485
1486 //==============================================================================
1487 //function : VActivate
1488 //purpose  : Activate the view defined by its ID
1489 //==============================================================================
1490
1491 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1492 {
1493   if (theArgsNb > 2)
1494   {
1495     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1496     << "Usage: " << theArgVec[0] << " ViewID\n";
1497     return 1;
1498   }
1499   if(theArgsNb == 1)
1500   {
1501     theDi.Eval("vviewlist");
1502     return 0;
1503   }
1504
1505   TCollection_AsciiString aNameString(theArgVec[1]);
1506   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1507   {
1508     TCollection_AsciiString aTitle("3D View - ");
1509     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1510     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1511     Handle(V3d_View) anEmptyView;
1512 #if defined(_WIN32) || defined(__WIN32__)
1513     Handle(WNT_Window) anEmptyWindow;
1514 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1515     Handle(Cocoa_Window) anEmptyWindow;
1516 #else
1517     Handle(Xw_Window) anEmptyWindow;
1518 #endif
1519     VT_GetWindow() = anEmptyWindow;
1520     ViewerTest::CurrentView (anEmptyView);
1521     ViewerTest::ResetEventManager();
1522     theDi << theArgVec[0] << ": all views are inactive\n";
1523     return 0;
1524   }
1525
1526   ViewerTest_Names aViewNames(aNameString);
1527
1528   // Check if this view exists in the viewer with the driver
1529   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1530   {
1531     theDi << "Wrong view name\n";
1532     return 1;
1533   }
1534
1535   // Check if it is active already
1536   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1537   {
1538     theDi << theArgVec[0] << ": the view is active already\n";
1539     return 0;
1540   }
1541
1542   ActivateView (aViewNames.GetViewName());
1543   return 0;
1544 }
1545
1546 //==============================================================================
1547 //function : VViewList
1548 //purpose  : Print current list of views per viewer and graphic driver ID
1549 //           shared between viewers
1550 //==============================================================================
1551
1552 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1553 {
1554   if (theArgsNb > 2)
1555   {
1556     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1557           << "Usage: " << theArgVec[0] << " name";
1558     return 1;
1559   }
1560   if (ViewerTest_myContexts.Size() < 1)
1561     return 0;
1562
1563   Standard_Boolean isTreeView =
1564     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1565
1566   if (isTreeView)
1567   {
1568     theDi << theArgVec[0] <<":\n";
1569   }
1570
1571   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1572        aDriverIter.More(); aDriverIter.Next())
1573   {
1574     if (isTreeView)
1575       theDi << aDriverIter.Key1() << ":\n";
1576
1577     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1578       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1579     {
1580       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1581       {
1582         if (isTreeView)
1583         {
1584           TCollection_AsciiString aContextName(aContextIter.Key1());
1585           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1586         }
1587
1588         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1589              aViewIter.More(); aViewIter.Next())
1590         {
1591           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1592           {
1593             TCollection_AsciiString aViewName(aViewIter.Key1());
1594             if (isTreeView)
1595             {
1596               if (aViewIter.Value() == ViewerTest::CurrentView())
1597                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1598               else
1599                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1600             }
1601             else
1602             {
1603               theDi << aViewName << " ";
1604             }
1605           }
1606         }
1607       }
1608     }
1609   }
1610   return 0;
1611 }
1612
1613 //==============================================================================
1614 //function : VT_ProcessKeyPress
1615 //purpose  : Handle KeyPress event from a CString
1616 //==============================================================================
1617 void VT_ProcessKeyPress (const char* buf_ret)
1618 {
1619   //cout << "KeyPress" << endl;
1620   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1621   // Letter in alphabetic order
1622
1623   if (!strcasecmp (buf_ret, "A")
1624    && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1625   {
1626     // AXO
1627     aView->SetProj(V3d_XposYnegZpos);
1628   }
1629   else if (!strcasecmp (buf_ret, "D")
1630         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1631   {
1632     // Reset
1633     aView->Reset();
1634   }
1635   else if (!strcasecmp (buf_ret, "F"))
1636   {
1637     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1638     {
1639       ViewerTest::GetAISContext()->FitSelected (aView);
1640     }
1641     else
1642     {
1643       // FitAll
1644       aView->FitAll();
1645     }
1646   }
1647   else if (!strcasecmp (buf_ret, "H"))
1648   {
1649     // HLR
1650     std::cout << "HLR" << std::endl;
1651     aView->SetComputedMode (!aView->ComputedMode());
1652     aView->Redraw();
1653   }
1654   else if (!strcasecmp (buf_ret, "P"))
1655   {
1656     // Type of HLR
1657     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1658     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1659       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1660     else
1661       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1662     if (aContext->NbSelected()==0)
1663     {
1664       AIS_ListOfInteractive aListOfShapes;
1665       aContext->DisplayedObjects(aListOfShapes);
1666       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1667         anIter.More(); anIter.Next())
1668       {
1669         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1670         if (aShape.IsNull())
1671           continue;
1672         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1673           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1674         else
1675           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1676         aContext->Redisplay (aShape, Standard_False);
1677       }
1678     }
1679     else
1680     {
1681       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1682       {
1683         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1684         if (aShape.IsNull())
1685           continue;
1686         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1687           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1688         else
1689           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1690         aContext->Redisplay (aShape, Standard_False);
1691       }
1692     }
1693
1694     aContext->UpdateCurrentViewer();
1695
1696   }
1697   else if (!strcasecmp (buf_ret, "S"))
1698   {
1699     std::cout << "setup Shaded display mode" << std::endl;
1700
1701     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1702     if(Ctx->NbSelected()==0)
1703       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1704     else{
1705       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1706         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1707       Ctx->UpdateCurrentViewer();
1708     }
1709   }
1710   else if (!strcasecmp (buf_ret, "U"))
1711   {
1712     // Unset display mode
1713     std::cout << "reset display mode to defaults" << std::endl;
1714
1715     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1716     if(Ctx->NbSelected()==0)
1717       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1718     else{
1719       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1720         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1721       Ctx->UpdateCurrentViewer();
1722     }
1723
1724   }
1725   else if (!strcasecmp (buf_ret, "T")
1726         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1727   {
1728     // Top
1729     aView->SetProj(V3d_Zpos);
1730   }
1731   else if (!strcasecmp (buf_ret, "B")
1732         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1733   {
1734     // Bottom
1735     aView->SetProj(V3d_Zneg);
1736   }
1737   else if (!strcasecmp (buf_ret, "L")
1738         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1739   {
1740     // Left
1741     aView->SetProj(V3d_Xneg);
1742   }
1743   else if (!strcasecmp (buf_ret, "R")
1744         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
1745   {
1746     // Right
1747     aView->SetProj(V3d_Xpos);
1748   }
1749   else if (!strcasecmp (buf_ret, "W"))
1750   {
1751     std::cout << "setup WireFrame display mode" << std::endl;
1752     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1753     if(Ctx->NbSelected()==0)
1754       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1755     else{
1756       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1757         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1758       Ctx->UpdateCurrentViewer();
1759     }
1760   }
1761   else if (!strcasecmp (buf_ret, ","))
1762   {
1763     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1764   }
1765   else if (!strcasecmp (buf_ret, "."))
1766   {
1767     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1768   }
1769   else if (!strcasecmp (buf_ret, "/"))
1770   {
1771     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1772     if (aCamera->IsStereo())
1773     {
1774       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1775       aView->Redraw();
1776     }
1777   }
1778   else if (!strcasecmp (buf_ret, "*"))
1779   {
1780     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1781     if (aCamera->IsStereo())
1782     {
1783       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1784       aView->Redraw();
1785     }
1786   }
1787   else if (*buf_ret == THE_KEY_DELETE)
1788   {
1789     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1790     if (!aCtx.IsNull()
1791      && aCtx->NbSelected() > 0)
1792     {
1793       Draw_Interprete ("verase");
1794     }
1795   }
1796   else if (*buf_ret == THE_KEY_ESCAPE)
1797   {
1798     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1799     if (!aCtx.IsNull()
1800      && Draw_ToCloseViewOnEsc)
1801     {
1802       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
1803     }
1804   }
1805   else
1806   {
1807     // Number
1808     const Standard_Integer aSelMode = Draw::Atoi(buf_ret);
1809     if (aSelMode >= 0 && aSelMode <= 7)
1810     {
1811       bool toEnable = true;
1812       if (const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext())
1813       {
1814         AIS_ListOfInteractive aPrsList;
1815         aCtx->DisplayedObjects (aPrsList);
1816         for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
1817         {
1818           TColStd_ListOfInteger aModes;
1819           aCtx->ActivatedModes (aPrsIter.Value(), aModes);
1820           for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
1821           {
1822             if (aModeIter.Value() == aSelMode)
1823             {
1824               toEnable = false;
1825             }
1826           }
1827         }
1828       }
1829       TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
1830       Draw_Interprete (aCmd.ToCString());
1831     }
1832   }
1833 }
1834
1835 //==============================================================================
1836 //function : VT_ProcessExpose
1837 //purpose  : Redraw the View on an Expose Event
1838 //==============================================================================
1839 void VT_ProcessExpose()
1840 {
1841   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1842   if (!aView3d.IsNull())
1843   {
1844     aView3d->Redraw();
1845   }
1846 }
1847
1848 //==============================================================================
1849 //function : VT_ProcessConfigure
1850 //purpose  : Resize the View on an Configure Event
1851 //==============================================================================
1852 void VT_ProcessConfigure()
1853 {
1854   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1855   if (aView3d.IsNull())
1856   {
1857     return;
1858   }
1859
1860   aView3d->MustBeResized();
1861   aView3d->Update();
1862   aView3d->Redraw();
1863 }
1864
1865 //==============================================================================
1866 //function : VT_ProcessButton1Press
1867 //purpose  : Picking
1868 //==============================================================================
1869 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1870                                          const char**     theArgVec,
1871                                          Standard_Boolean theToPick,
1872                                          Standard_Boolean theIsShift)
1873 {
1874   if (TheIsAnimating)
1875   {
1876     TheIsAnimating = Standard_False;
1877     return Standard_False;
1878   }
1879
1880   if (theToPick)
1881   {
1882     Standard_Real X, Y, Z;
1883     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1884
1885     Draw::Set (theArgVec[1], X);
1886     Draw::Set (theArgVec[2], Y);
1887     Draw::Set (theArgVec[3], Z);
1888   }
1889
1890   if (theIsShift)
1891   {
1892     ViewerTest::CurrentEventManager()->ShiftSelect();
1893   }
1894   else
1895   {
1896     ViewerTest::CurrentEventManager()->Select();
1897   }
1898
1899   return Standard_False;
1900 }
1901
1902 //==============================================================================
1903 //function : VT_ProcessButton1Release
1904 //purpose  : End selecting
1905 //==============================================================================
1906 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1907 {
1908   if (IsDragged)
1909   {
1910     IsDragged = Standard_False;
1911     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1912     if (theIsShift)
1913     {
1914       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1915                        X_Motion, Y_Motion);
1916     }
1917     else
1918     {
1919       EM->Select (X_ButtonPress, Y_ButtonPress,
1920                   X_Motion, Y_Motion);
1921     }
1922   }
1923 }
1924
1925 //==============================================================================
1926 //function : VT_ProcessButton3Press
1927 //purpose  : Start Rotation
1928 //==============================================================================
1929 void VT_ProcessButton3Press()
1930 {
1931   if (ViewerTest_V3dView::IsCurrentViewIn2DMode())
1932   {
1933     return;
1934   }
1935
1936   Start_Rot = 1;
1937   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
1938   if (HasHlrOnBeforeRotation)
1939   {
1940     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1941   }
1942   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1943 }
1944
1945 //==============================================================================
1946 //function : VT_ProcessButton3Release
1947 //purpose  : End rotation
1948 //==============================================================================
1949 void VT_ProcessButton3Release()
1950 {
1951   if (Start_Rot)
1952   {
1953     Start_Rot = 0;
1954     if (HasHlrOnBeforeRotation)
1955     {
1956       HasHlrOnBeforeRotation = Standard_False;
1957       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1958       ViewerTest::CurrentView()->Redraw();
1959     }
1960   }
1961 }
1962
1963 //==============================================================================
1964 //function : ProcessControlButton1Motion
1965 //purpose  : Zoom
1966 //==============================================================================
1967
1968 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1969 static void ProcessControlButton1Motion()
1970 {
1971   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1972
1973   X_ButtonPress = X_Motion;
1974   Y_ButtonPress = Y_Motion;
1975 }
1976 #endif
1977
1978 //==============================================================================
1979 //function : VT_ProcessControlButton2Motion
1980 //purpose  : Panning
1981 //==============================================================================
1982 void VT_ProcessControlButton2Motion()
1983 {
1984   Standard_Integer aDx = X_Motion - X_ButtonPress;
1985   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1986
1987   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1988
1989   ViewerTest::CurrentView()->Pan (aDx, aDy);
1990
1991   X_ButtonPress = X_Motion;
1992   Y_ButtonPress = Y_Motion;
1993 }
1994
1995 //==============================================================================
1996 //function : VT_ProcessControlButton3Motion
1997 //purpose  : Rotation
1998 //==============================================================================
1999 void VT_ProcessControlButton3Motion()
2000 {
2001   if (Start_Rot)
2002   {
2003     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
2004   }
2005 }
2006
2007 //==============================================================================
2008 //function : VT_ProcessMotion
2009 //purpose  :
2010 //==============================================================================
2011 void VT_ProcessMotion()
2012 {
2013   //pre-hilights detected objects at mouse position
2014
2015   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
2016   EM->MoveTo(X_Motion, Y_Motion);
2017 }
2018
2019
2020 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
2021 {
2022   Xpix = X_Motion;Ypix=Y_Motion;
2023 }
2024
2025 //==============================================================================
2026 //function : ViewProject: implements VAxo, VTop, VLeft, ...
2027 //purpose  : Switches to an axonometric, top, left and other views
2028 //==============================================================================
2029
2030 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
2031 {
2032   if ( ViewerTest::CurrentView().IsNull() )
2033   {
2034     di<<"Call vinit before this command, please\n";
2035     return 1;
2036   }
2037
2038   ViewerTest::CurrentView()->SetProj(ori);
2039   return 0;
2040 }
2041
2042 //==============================================================================
2043 //function : VAxo
2044 //purpose  : Switch to an Axonometric view
2045 //Draw arg : No args
2046 //==============================================================================
2047
2048 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
2049 {
2050   return ViewProject(di, V3d_XposYnegZpos);
2051 }
2052
2053 //==============================================================================
2054 //function : VTop
2055 //purpose  : Switch to a Top View
2056 //Draw arg : No args
2057 //==============================================================================
2058
2059 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
2060 {
2061   return ViewProject(di, V3d_Zpos);
2062 }
2063
2064 //==============================================================================
2065 //function : VBottom
2066 //purpose  : Switch to a Bottom View
2067 //Draw arg : No args
2068 //==============================================================================
2069
2070 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
2071 {
2072   return ViewProject(di, V3d_Zneg);
2073 }
2074
2075 //==============================================================================
2076 //function : VLeft
2077 //purpose  : Switch to a Left View
2078 //Draw arg : No args
2079 //==============================================================================
2080
2081 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
2082 {
2083   return ViewProject(di, V3d_Xneg);
2084 }
2085
2086 //==============================================================================
2087 //function : VRight
2088 //purpose  : Switch to a Right View
2089 //Draw arg : No args
2090 //==============================================================================
2091
2092 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
2093 {
2094   return ViewProject(di, V3d_Xpos);
2095 }
2096
2097 //==============================================================================
2098 //function : VFront
2099 //purpose  : Switch to a Front View
2100 //Draw arg : No args
2101 //==============================================================================
2102
2103 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
2104 {
2105   return ViewProject(di, V3d_Yneg);
2106 }
2107
2108 //==============================================================================
2109 //function : VBack
2110 //purpose  : Switch to a Back View
2111 //Draw arg : No args
2112 //==============================================================================
2113
2114 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
2115 {
2116   return ViewProject(di, V3d_Ypos);
2117 }
2118
2119 //==============================================================================
2120 //function : VHelp
2121 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
2122 //Draw arg : No args
2123 //==============================================================================
2124
2125 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
2126 {
2127
2128   di << "Q : Quit the application\n";
2129
2130   di << "=========================\n";
2131   di << "F : FitAll\n";
2132   di << "T : TopView\n";
2133   di << "B : BottomView\n";
2134   di << "R : RightView\n";
2135   di << "L : LeftView\n";
2136   di << "A : AxonometricView\n";
2137   di << "D : ResetView\n";
2138
2139   di << "=========================\n";
2140   di << "S : Shading\n";
2141   di << "W : Wireframe\n";
2142   di << "H : HidelLineRemoval\n";
2143   di << "U : Unset display mode\n";
2144   di << "Delete : Remove selection from viewer\n";
2145
2146   di << "=========================\n";
2147   di << "Selection mode \n";
2148   di << "0 : Shape\n";
2149   di << "1 : Vertex\n";
2150   di << "2 : Edge\n";
2151   di << "3 : Wire\n";
2152   di << "4 : Face\n";
2153   di << "5 : Shell\n";
2154   di << "6 : Solid\n";
2155   di << "7 : Compound\n";
2156
2157   di << "=========================\n";
2158   di << "Z : Switch Z clipping On/Off\n";
2159   di << ", : Hilight next detected\n";
2160   di << ". : Hilight previous detected\n";
2161
2162   return 0;
2163 }
2164
2165 #ifdef _WIN32
2166
2167 static Standard_Boolean Ppick = 0;
2168 static Standard_Integer Pargc = 0;
2169 static const char**           Pargv = NULL;
2170
2171
2172 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
2173                                           UINT Msg,
2174                                           WPARAM wParam,
2175                                           LPARAM lParam )
2176 {
2177   if (!ViewerTest_myViews.IsEmpty()) {
2178
2179     WPARAM fwKeys = wParam;
2180
2181     switch( Msg ) {
2182     case WM_CLOSE:
2183        {
2184          // Delete view from map of views
2185          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
2186          return 0;
2187        }
2188        break;
2189     case WM_ACTIVATE:
2190       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
2191         || ViewerTest::CurrentView().IsNull())
2192       {
2193         // Activate inactive window
2194         if(GetWindowHandle(VT_GetWindow()) != hwnd)
2195         {
2196           ActivateView (FindViewIdByWindowHandle(hwnd));
2197         }
2198       }
2199       break;
2200
2201     case WM_LBUTTONUP:
2202       if (IsDragged && !DragFirst)
2203       {
2204         if (!GetActiveAISManipulator().IsNull())
2205         {
2206           GetActiveAISManipulator()->StopTransform();
2207           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2208         }
2209
2210         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2211         {
2212           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2213           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2214         }
2215
2216         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
2217       }
2218       IsDragged = Standard_False;
2219       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2220
2221     case WM_RBUTTONUP:
2222       if (IsDragged && !DragFirst)
2223       {
2224         if (!GetActiveAISManipulator().IsNull())
2225         {
2226           GetActiveAISManipulator()->StopTransform (Standard_False);
2227           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2228         }
2229         IsDragged = Standard_False;
2230       }
2231       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
2232
2233     case WM_LBUTTONDOWN:
2234       if (!GetActiveAISManipulator().IsNull())
2235       {
2236         IsDragged = ( fwKeys == MK_LBUTTON );
2237       }
2238       else
2239       {
2240         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
2241       }
2242
2243       if (IsDragged)
2244       {
2245         DragFirst = Standard_True;
2246         X_ButtonPress = LOWORD(lParam);
2247         Y_ButtonPress = HIWORD(lParam);
2248       }
2249       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2250
2251     case WM_MOUSEMOVE:
2252       if (IsDragged)
2253       {
2254         X_Motion = LOWORD (lParam);
2255         Y_Motion = HIWORD (lParam);
2256         if (!GetActiveAISManipulator().IsNull())
2257         {
2258           if (DragFirst)
2259           {
2260             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
2261           }
2262           else
2263           {
2264             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
2265             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
2266           }
2267         }
2268         else
2269         {
2270           bool toRedraw = false;
2271           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2272           {
2273             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2274             toRedraw = true;
2275           }
2276
2277           RECT aRect;
2278           if (GetClientRect (hwnd, &aRect))
2279           {
2280             int aHeight = aRect.bottom - aRect.top;
2281             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2282             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2283             toRedraw = true;
2284           }
2285           if (toRedraw)
2286           {
2287             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2288           }
2289         }
2290
2291         DragFirst = Standard_False;
2292       }
2293       else
2294         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2295       break;
2296
2297     default:
2298       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2299     }
2300     return 0;
2301   }
2302   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2303 }
2304
2305
2306 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2307                                        UINT Msg,
2308                                        WPARAM wParam,
2309                                        LPARAM lParam )
2310 {
2311   static int Up = 1;
2312   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2313   if (aView.IsNull())
2314   {
2315     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2316   }
2317
2318     PAINTSTRUCT    ps;
2319
2320     switch( Msg ) {
2321     case WM_PAINT:
2322       BeginPaint(hwnd, &ps);
2323       EndPaint(hwnd, &ps);
2324       VT_ProcessExpose();
2325       break;
2326
2327     case WM_SIZE:
2328       VT_ProcessConfigure();
2329       break;
2330     case WM_MOVE:
2331     case WM_MOVING:
2332     case WM_SIZING:
2333       switch (aView->RenderingParams().StereoMode)
2334       {
2335         case Graphic3d_StereoMode_RowInterlaced:
2336         case Graphic3d_StereoMode_ColumnInterlaced:
2337         case Graphic3d_StereoMode_ChessBoard:
2338           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2339           break;
2340         default:
2341           break;
2342       }
2343       break;
2344
2345     case WM_KEYDOWN:
2346       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2347       {
2348         char c[2];
2349         c[0] = (char) wParam;
2350         c[1] = '\0';
2351         if (wParam == VK_DELETE)
2352         {
2353           c[0] = THE_KEY_DELETE;
2354         }
2355         else if (wParam == VK_ESCAPE)
2356         {
2357           c[0] = THE_KEY_ESCAPE;
2358         }
2359         // comma
2360         else if (wParam == VK_OEM_COMMA)
2361         {
2362           c[0] = ',';
2363         }
2364         // dot
2365         else if (wParam == VK_OEM_PERIOD)
2366         {
2367           c[0] = '.';
2368         }
2369         else if (wParam == VK_DIVIDE)
2370         {
2371           c[0] = '/';
2372         }
2373         // dot
2374         else if (wParam == VK_MULTIPLY)
2375         {
2376           c[0] = '*';
2377         }
2378         VT_ProcessKeyPress (c);
2379       }
2380       break;
2381
2382     case WM_LBUTTONUP:
2383     case WM_MBUTTONUP:
2384     case WM_RBUTTONUP:
2385       Up = 1;
2386       VT_ProcessButton3Release();
2387       break;
2388
2389     case WM_LBUTTONDOWN:
2390     case WM_MBUTTONDOWN:
2391     case WM_RBUTTONDOWN:
2392       {
2393         WPARAM fwKeys = wParam;
2394
2395         Up = 0;
2396
2397         X_ButtonPress = LOWORD(lParam);
2398         Y_ButtonPress = HIWORD(lParam);
2399
2400         if (Msg == WM_LBUTTONDOWN)
2401         {
2402           if ((fwKeys & MK_CONTROL) != 0)
2403           {
2404             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2405           }
2406           else
2407           {
2408             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2409           }
2410         }
2411         else if (Msg == WM_RBUTTONDOWN)
2412         {
2413           // Start rotation
2414           VT_ProcessButton3Press();
2415         }
2416       }
2417       break;
2418
2419     case WM_MOUSEWHEEL:
2420     {
2421       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2422       if (wParam & MK_CONTROL)
2423       {
2424         if (aView->Camera()->IsStereo())
2425         {
2426           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2427           if (aFocus > 0.2
2428            && aFocus < 2.0)
2429           {
2430             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2431             aView->Redraw();
2432           }
2433         }
2434       }
2435       else
2436       {
2437         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2438       }
2439       break;
2440     }
2441
2442     case WM_MOUSEMOVE:
2443       {
2444         //cout << "\t WM_MOUSEMOVE" << endl;
2445         WPARAM fwKeys = wParam;
2446         X_Motion = LOWORD(lParam);
2447         Y_Motion = HIWORD(lParam);
2448
2449         if ( Up &&
2450           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2451           {
2452             Up = 0;
2453             X_ButtonPress = LOWORD(lParam);
2454             Y_ButtonPress = HIWORD(lParam);
2455
2456             if ((fwKeys & MK_RBUTTON) != 0) {
2457               // Start rotation
2458               VT_ProcessButton3Press();
2459             }
2460           }
2461
2462           if ((fwKeys & MK_CONTROL) != 0)
2463           {
2464             if ((fwKeys & MK_LBUTTON) != 0)
2465             {
2466               ProcessControlButton1Motion();
2467             }
2468             else if ((fwKeys & MK_MBUTTON) != 0
2469                  || ((fwKeys & MK_LBUTTON) != 0
2470                   && (fwKeys & MK_RBUTTON) != 0))
2471             {
2472               VT_ProcessControlButton2Motion();
2473             }
2474             else if ((fwKeys & MK_RBUTTON) != 0)
2475             {
2476               VT_ProcessControlButton3Motion();
2477             }
2478           }
2479           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2480           {
2481             VT_ProcessMotion();
2482           }
2483       }
2484       break;
2485
2486     default:
2487       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2488     }
2489     return 0L;
2490 }
2491
2492 //==============================================================================
2493 //function : ViewerMainLoop
2494 //purpose  : Get a Event on the view and dispatch it
2495 //==============================================================================
2496
2497
2498 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2499 {
2500   Ppick = (argc > 0)? 1 : 0;
2501   Pargc = argc;
2502   Pargv = argv;
2503
2504   if ( Ppick ) {
2505     MSG msg;
2506     msg.wParam = 1;
2507
2508     cout << "Start picking" << endl;
2509
2510     while ( Ppick == 1 ) {
2511       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2512       if (GetMessageW (&msg, NULL, 0, 0))
2513       {
2514         TranslateMessage (&msg);
2515         DispatchMessageW (&msg);
2516       }
2517     }
2518
2519     cout << "Picking done" << endl;
2520   }
2521
2522   return Ppick;
2523 }
2524
2525 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2526
2527 int min( int a, int b )
2528 {
2529   if( a<b )
2530     return a;
2531   else
2532     return b;
2533 }
2534
2535 int max( int a, int b )
2536 {
2537   if( a>b )
2538     return a;
2539   else
2540     return b;
2541 }
2542
2543 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2544
2545 {
2546   static XEvent aReport;
2547   Standard_Boolean pick = argc > 0;
2548   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2549   XNextEvent (aDisplay, &aReport);
2550
2551   // Handle event for the chosen display connection
2552   switch (aReport.type) {
2553       case ClientMessage:
2554         {
2555           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2556           {
2557             // Close the window
2558             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2559           }
2560         }
2561         return 0;
2562      case FocusIn:
2563       {
2564          // Activate inactive view
2565          Window aWindow = GetWindowHandle(VT_GetWindow());
2566          if(aWindow != aReport.xfocus.window)
2567          {
2568            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2569          }
2570       }
2571       break;
2572       case Expose:
2573         {
2574           VT_ProcessExpose();
2575         }
2576         break;
2577       case ConfigureNotify:
2578         {
2579           VT_ProcessConfigure();
2580         }
2581         break;
2582       case KeyPress:
2583         {
2584
2585           KeySym ks_ret ;
2586           char buf_ret[11] ;
2587           int ret_len ;
2588           XComposeStatus status_in_out;
2589
2590           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2591             (char *) buf_ret , 10 ,
2592             &ks_ret , &status_in_out ) ;
2593
2594
2595           buf_ret[ret_len] = '\0' ;
2596
2597           if (ret_len)
2598           {
2599             VT_ProcessKeyPress (buf_ret);
2600           }
2601         }
2602         break;
2603       case ButtonPress:
2604         {
2605           X_ButtonPress = aReport.xbutton.x;
2606           Y_ButtonPress = aReport.xbutton.y;
2607
2608           if (aReport.xbutton.button == Button1)
2609           {
2610             if (aReport.xbutton.state & ControlMask)
2611             {
2612               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2613             }
2614             else
2615             {
2616               IsDragged = Standard_True;
2617               DragFirst = Standard_True;
2618             }
2619           }
2620           else if (aReport.xbutton.button == Button3)
2621           {
2622             // Start rotation
2623             VT_ProcessButton3Press();
2624           }
2625         }
2626         break;
2627       case ButtonRelease:
2628         {
2629           if( IsDragged )
2630           {
2631             if( !DragFirst )
2632             {
2633               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2634               {
2635                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2636                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2637               }
2638             }
2639
2640             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2641             if( aContext.IsNull() )
2642             {
2643               cout << "The context is null. Please use vinit before createmesh" << endl;
2644               return 0;
2645             }
2646
2647             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2648             if( aReport.xbutton.button==1 )
2649               if( DragFirst )
2650                 if( ShiftPressed )
2651                 {
2652                   aContext->ShiftSelect (Standard_True);
2653                 }
2654                 else
2655                 {
2656                   aContext->Select (Standard_True);
2657                 }
2658               else
2659                 if( ShiftPressed )
2660                 {
2661                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2662                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2663                                         ViewerTest::CurrentView(), Standard_True);
2664                 }
2665                 else
2666                 {
2667                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2668                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2669                                    ViewerTest::CurrentView(), Standard_True);
2670                 }
2671             else
2672               VT_ProcessButton3Release();
2673
2674             IsDragged = Standard_False;
2675           }
2676           else
2677             VT_ProcessButton3Release();
2678         }
2679         break;
2680       case MotionNotify:
2681         {
2682           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2683           {
2684             break;
2685           }
2686           if( IsDragged )
2687           {
2688             if( !DragFirst )
2689             {
2690               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2691               {
2692                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2693               }
2694             }
2695
2696             X_Motion = aReport.xmotion.x;
2697             Y_Motion = aReport.xmotion.y;
2698             DragFirst = Standard_False;
2699
2700             Window aWindow = GetWindowHandle(VT_GetWindow());
2701             Window aRoot;
2702             int anX, anY;
2703             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2704             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2705             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2706             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
2707             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2708           }
2709           else
2710           {
2711             X_Motion = aReport.xmotion.x;
2712             Y_Motion = aReport.xmotion.y;
2713
2714             // remove all the ButtonMotionMaskr
2715             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2716
2717             if ( aReport.xmotion.state & ControlMask ) {
2718               if ( aReport.xmotion.state & Button1Mask ) {
2719                 ProcessControlButton1Motion();
2720               }
2721               else if ( aReport.xmotion.state & Button2Mask ) {
2722                 VT_ProcessControlButton2Motion();
2723               }
2724               else if ( aReport.xmotion.state & Button3Mask ) {
2725                 VT_ProcessControlButton3Motion();
2726               }
2727             }
2728             else
2729             {
2730               VT_ProcessMotion();
2731             }
2732           }
2733         }
2734         break;
2735 }
2736 return pick;
2737 }
2738
2739 //==============================================================================
2740 //function : VProcessEvents
2741 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2742 //       event in the Viewer window
2743 //==============================================================================
2744
2745 static void VProcessEvents(ClientData,int)
2746 {
2747   NCollection_Vector<int> anEventNumbers;
2748   // Get number of messages from every display
2749   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2750        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2751   {
2752     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2753   }
2754     // Handle events for every display
2755   int anEventIter = 0;
2756   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2757        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2758   {
2759     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2760          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2761     {
2762       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2763       int anEventResult = ViewerMainLoop( 0, NULL);
2764       // If window is closed or context was not found finish current event processing loop
2765       if (!anEventResult)
2766         return;
2767     }
2768   }
2769
2770   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2771
2772 }
2773 #endif
2774
2775 //==============================================================================
2776 //function : OSWindowSetup
2777 //purpose  : Setup for the X11 window to be able to cath the event
2778 //==============================================================================
2779
2780
2781 static void OSWindowSetup()
2782 {
2783 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2784   // X11
2785
2786   Window  window   = VT_GetWindow()->XWindow();
2787   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2788   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2789   XSynchronize(aDisplay, 1);
2790
2791   // X11 : For keyboard on SUN
2792   XWMHints wmhints;
2793   wmhints.flags = InputHint;
2794   wmhints.input = 1;
2795
2796   XSetWMHints( aDisplay, window, &wmhints);
2797
2798   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2799     ButtonPressMask | ButtonReleaseMask |
2800     StructureNotifyMask |
2801     PointerMotionMask |
2802     Button1MotionMask | Button2MotionMask |
2803     Button3MotionMask | FocusChangeMask
2804     );
2805   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2806   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2807
2808   XSynchronize(aDisplay, 0);
2809
2810 #else
2811   // _WIN32
2812 #endif
2813
2814 }
2815
2816 //==============================================================================
2817 //function : VFit
2818 //purpose  :
2819 //==============================================================================
2820
2821 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2822 {
2823   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2824   if (aView.IsNull())
2825   {
2826     std::cout << "Error: no active viewer!\n";
2827     return 1;
2828   }
2829
2830   Standard_Boolean toFit = Standard_True;
2831   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2832   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2833   {
2834     TCollection_AsciiString anArg (theArgv[anArgIter]);
2835     anArg.LowerCase();
2836     if (anUpdateTool.parseRedrawMode (anArg))
2837     {
2838       continue;
2839     }
2840     else if (anArg == "-selected")
2841     {
2842       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2843       toFit = Standard_False;
2844     }
2845     else
2846     {
2847       std::cout << "Syntax error at '" << anArg << "'\n";
2848     }
2849   }
2850
2851   if (toFit)
2852   {
2853     aView->FitAll (0.01, Standard_False);
2854   }
2855   return 0;
2856 }
2857
2858 //=======================================================================
2859 //function : VFitArea
2860 //purpose  : Fit view to show area located between two points
2861 //         : given in world 2D or 3D coordinates.
2862 //=======================================================================
2863 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2864 {
2865   Handle(V3d_View) aView = ViewerTest::CurrentView();
2866   if (aView.IsNull())
2867   {
2868     std::cerr << theArgVec[0] << "Error: No active view.\n";
2869     return 1;
2870   }
2871
2872   // Parse arguments.
2873   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2874   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2875
2876   if (theArgNb == 5)
2877   {
2878     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2879     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2880     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2881     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2882   }
2883   else if (theArgNb == 7)
2884   {
2885     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2886     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2887     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2888     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2889     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2890     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2891   }
2892   else
2893   {
2894     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2895     theDI.PrintHelp(theArgVec[0]);
2896     return 1;
2897   }
2898
2899   // Convert model coordinates to view space
2900   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2901   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2902   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2903
2904   // Determine fit area
2905   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2906   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2907
2908   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2909
2910   if (aDiagonal < Precision::Confusion())
2911   {
2912     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2913     return 1;
2914   }
2915
2916   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2917   return 0;
2918 }
2919
2920 //==============================================================================
2921 //function : VZFit
2922 //purpose  : ZFitall, no DRAW arguments
2923 //Draw arg : No args
2924 //==============================================================================
2925 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2926 {
2927   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2928
2929   if (aCurrentView.IsNull())
2930   {
2931     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2932     return 1;
2933   }
2934
2935   if (theArgsNb == 1)
2936   {
2937     aCurrentView->ZFitAll();
2938     aCurrentView->Redraw();
2939     return 0;
2940   }
2941
2942   Standard_Real aScale = 1.0;
2943
2944   if (theArgsNb >= 2)
2945   {
2946     aScale = Draw::Atoi (theArgVec[1]);
2947   }
2948
2949   aCurrentView->ZFitAll (aScale);
2950   aCurrentView->Redraw();
2951
2952   return 0;
2953 }
2954
2955 //==============================================================================
2956 //function : VRepaint
2957 //purpose  :
2958 //==============================================================================
2959 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2960 {
2961   Handle(V3d_View) aView = ViewerTest::CurrentView();
2962   if (aView.IsNull())
2963   {
2964     std::cout << "Error: no active viewer!\n";
2965     return 1;
2966   }
2967
2968   Standard_Boolean isImmediateUpdate = Standard_False;
2969   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2970   {
2971     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2972     anArg.LowerCase();
2973     if (anArg == "-immediate")
2974     {
2975       isImmediateUpdate = Standard_True;
2976       if (anArgIter + 1 < theArgNb
2977        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2978       {
2979         ++anArgIter;
2980       }
2981     }
2982     else
2983     {
2984       std::cout << "Syntax error at '" << anArg << "'\n";
2985     }
2986   }
2987
2988   if (isImmediateUpdate)
2989   {
2990     aView->RedrawImmediate();
2991   }
2992   else
2993   {
2994     aView->Redraw();
2995   }
2996   return 0;
2997 }
2998
2999 //==============================================================================
3000 //function : VClear
3001 //purpose  : Remove all the object from the viewer
3002 //Draw arg : No args
3003 //==============================================================================
3004
3005 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3006 {
3007   Handle(V3d_View) V = ViewerTest::CurrentView();
3008   if(!V.IsNull())
3009     ViewerTest::Clear();
3010   return 0;
3011 }
3012
3013 //==============================================================================
3014 //function : VPick
3015 //purpose  :
3016 //==============================================================================
3017
3018 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3019 { if (ViewerTest::CurrentView().IsNull() ) return 1;
3020
3021 if ( argc < 4 ) {
3022   di << argv[0] << "Invalid number of arguments\n";
3023   return 1;
3024 }
3025
3026 while (ViewerMainLoop( argc, argv)) {
3027 }
3028
3029 return 0;
3030 }
3031
3032 //==============================================================================
3033 //function : VSetBg
3034 //purpose  : Load image as background
3035 //==============================================================================
3036
3037 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3038 {
3039   if (argc < 2 || argc > 3)
3040   {
3041     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
3042     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
3043     return 1;
3044   }
3045
3046   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3047   if(AISContext.IsNull())
3048   {
3049     di << "use 'vinit' command before " << argv[0] << "\n";
3050     return 1;
3051   }
3052
3053   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
3054   if (argc == 3)
3055   {
3056     const char* szType = argv[2];
3057     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3058     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3059     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3060     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3061     else
3062     {
3063       di << "Wrong fill type : " << szType << "\n";
3064       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3065       return 1;
3066     }
3067   }
3068
3069   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3070   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
3071
3072   return 0;
3073 }
3074
3075 //==============================================================================
3076 //function : VSetBgMode
3077 //purpose  : Change background image fill type
3078 //==============================================================================
3079
3080 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3081 {
3082   if (argc != 2)
3083   {
3084     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
3085     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
3086     return 1;
3087   }
3088
3089   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3090   if(AISContext.IsNull())
3091   {
3092     di << "use 'vinit' command before " << argv[0] << "\n";
3093     return 1;
3094   }
3095   Aspect_FillMethod aFillType = Aspect_FM_NONE;
3096   const char* szType = argv[1];
3097   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
3098   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
3099   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
3100   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
3101   else
3102   {
3103     di << "Wrong fill type : " << szType << "\n";
3104     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
3105     return 1;
3106   }
3107   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3108   V3dView->SetBgImageStyle(aFillType, Standard_True);
3109   return 0;
3110 }
3111
3112 //==============================================================================
3113 //function : VSetGradientBg
3114 //purpose  : Mount gradient background
3115 //==============================================================================
3116 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3117 {
3118   if (argc != 8 )
3119   {
3120     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
3121     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
3122     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3123     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3124     return 1;
3125   }
3126
3127   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3128   if(AISContext.IsNull())
3129   {
3130     di << "use 'vinit' command before " << argv[0] << "\n";
3131     return 1;
3132   }
3133   if (argc == 8)
3134   {
3135
3136     Standard_Real R1 = Draw::Atof(argv[1])/255.;
3137     Standard_Real G1 = Draw::Atof(argv[2])/255.;
3138     Standard_Real B1 = Draw::Atof(argv[3])/255.;
3139     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
3140
3141     Standard_Real R2 = Draw::Atof(argv[4])/255.;
3142     Standard_Real G2 = Draw::Atof(argv[5])/255.;
3143     Standard_Real B2 = Draw::Atof(argv[6])/255.;
3144
3145     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
3146     int aType = Draw::Atoi(argv[7]);
3147     if( aType < 0 || aType > 8 )
3148     {
3149       di << "Wrong fill type \n";
3150       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3151       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3152       return 1;
3153     }
3154
3155     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3156
3157     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3158     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
3159   }
3160
3161   return 0;
3162 }
3163
3164 //==============================================================================
3165 //function : VSetGradientBgMode
3166 //purpose  : Change gradient background fill style
3167 //==============================================================================
3168 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3169 {
3170   if (argc != 2 )
3171   {
3172     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
3173     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3174     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3175     return 1;
3176   }
3177
3178   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3179   if(AISContext.IsNull())
3180   {
3181     di << "use 'vinit' command before " << argv[0] << "\n";
3182     return 1;
3183   }
3184   if (argc == 2)
3185   {
3186     int aType = Draw::Atoi(argv[1]);
3187     if( aType < 0 || aType > 8 )
3188     {
3189       di << "Wrong fill type \n";
3190       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3191       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3192       return 1;
3193     }
3194
3195     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3196
3197     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3198     V3dView->SetBgGradientStyle( aMethod, 1 );
3199   }
3200
3201   return 0;
3202 }
3203
3204 //==============================================================================
3205 //function : VSetColorBg
3206 //purpose  : Set color background
3207 //==============================================================================
3208 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3209 {
3210   if (argc != 4 )
3211   {
3212     di << "Usage : " << argv[0] << " R G B : Set color background\n";
3213     di << "R,G,B = [0..255]\n";
3214     return 1;
3215   }
3216
3217   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3218   if(AISContext.IsNull())
3219   {
3220     di << "use 'vinit' command before " << argv[0] << "\n";
3221     return 1;
3222   }
3223   if (argc == 4)
3224   {
3225
3226     Standard_Real R = Draw::Atof(argv[1])/255.;
3227     Standard_Real G = Draw::Atof(argv[2])/255.;
3228     Standard_Real B = Draw::Atof(argv[3])/255.;
3229     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
3230
3231     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3232     V3dView->SetBackgroundColor( aColor );
3233     V3dView->Update();
3234   }
3235
3236   return 0;
3237 }
3238
3239 //==============================================================================
3240 //function : VSetDefaultBg
3241 //purpose  : Set default viewer background fill color
3242 //==============================================================================
3243 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3244 {
3245   if (theArgNb != 4
3246    && theArgNb != 8)
3247   {
3248     std::cout << "Error: wrong syntax! See usage:\n";
3249     theDI.PrintHelp (theArgVec[0]);
3250     return 1;
3251   }
3252
3253   ViewerTest_DefaultBackground.FillMethod =
3254     theArgNb == 4 ? Aspect_GFM_NONE
3255                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
3256
3257   if (theArgNb == 4)
3258   {
3259     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
3260     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
3261     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
3262     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
3263   }
3264   else
3265   {
3266     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
3267     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
3268     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
3269     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
3270
3271     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
3272     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
3273     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
3274     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
3275   }
3276
3277   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
3278        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
3279   {
3280     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
3281     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
3282     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
3283                                          ViewerTest_DefaultBackground.GradientColor2,
3284                                          ViewerTest_DefaultBackground.FillMethod);
3285   }
3286
3287   return 0;
3288 }
3289
3290 //==============================================================================
3291 //function : VScale
3292 //purpose  : View Scaling
3293 //==============================================================================
3294
3295 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3296 {
3297   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3298   if ( V3dView.IsNull() ) return 1;
3299
3300   if ( argc != 4 ) {
3301     di << argv[0] << "Invalid number of arguments\n";
3302     return 1;
3303   }
3304   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3305   return 0;
3306 }
3307 //==============================================================================
3308 //function : VZBuffTrihedron
3309 //purpose  :
3310 //==============================================================================
3311
3312 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3313                             Standard_Integer  theArgNb,
3314                             const char**      theArgVec)
3315 {
3316   Handle(V3d_View) aView = ViewerTest::CurrentView();
3317   if (aView.IsNull())
3318   {
3319     std::cout << "Error: no active viewer!\n";
3320     return 1;
3321   }
3322
3323   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3324
3325   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3326   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3327   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3328   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3329   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3330   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3331   Standard_Real                 aScale        = 0.1;
3332   Standard_Real                 aSizeRatio    = 0.8;
3333   Standard_Real                 anArrowDiam   = 0.05;
3334   Standard_Integer              aNbFacets     = 12;
3335   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3336   {
3337     Standard_CString        anArg = theArgVec[anArgIter];
3338     TCollection_AsciiString aFlag (anArg);
3339     aFlag.LowerCase();
3340     if (anUpdateTool.parseRedrawMode (aFlag))
3341     {
3342       continue;
3343     }
3344     else if (aFlag == "-on")
3345     {
3346       continue;
3347     }
3348     else if (aFlag == "-off")
3349     {
3350       aView->TriedronErase();
3351       return 0;
3352     }
3353     else if (aFlag == "-pos"
3354           || aFlag == "-position"
3355           || aFlag == "-corner")
3356     {
3357       if (++anArgIter >= theArgNb)
3358       {
3359         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3360         return 1;
3361       }
3362
3363       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3364       aPosName.LowerCase();
3365       if (aPosName == "center")
3366       {
3367         aPosition = Aspect_TOTP_CENTER;
3368       }
3369       else if (aPosName == "left_lower"
3370             || aPosName == "lower_left"
3371             || aPosName == "leftlower"
3372             || aPosName == "lowerleft")
3373       {
3374         aPosition = Aspect_TOTP_LEFT_LOWER;
3375       }
3376       else if (aPosName == "left_upper"
3377             || aPosName == "upper_left"
3378             || aPosName == "leftupper"
3379             || aPosName == "upperleft")
3380       {
3381         aPosition = Aspect_TOTP_LEFT_UPPER;
3382       }
3383       else if (aPosName == "right_lower"
3384             || aPosName == "lower_right"
3385             || aPosName == "rightlower"
3386             || aPosName == "lowerright")
3387       {
3388         aPosition = Aspect_TOTP_RIGHT_LOWER;
3389       }
3390       else if (aPosName == "right_upper"
3391             || aPosName == "upper_right"
3392             || aPosName == "rightupper"
3393             || aPosName == "upperright")
3394       {
3395         aPosition = Aspect_TOTP_RIGHT_UPPER;
3396       }
3397       else
3398       {
3399         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3400         return 1;
3401       }
3402     }
3403     else if (aFlag == "-type")
3404     {
3405       if (++anArgIter >= theArgNb)
3406       {
3407         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3408         return 1;
3409       }
3410
3411       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3412       aTypeName.LowerCase();
3413       if (aTypeName == "wireframe"
3414        || aTypeName == "wire")
3415       {
3416         aVisType = V3d_WIREFRAME;
3417       }
3418       else if (aTypeName == "zbuffer"
3419             || aTypeName == "shaded")
3420       {
3421         aVisType = V3d_ZBUFFER;
3422       }
3423       else
3424       {
3425         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3426       }
3427     }
3428     else if (aFlag == "-scale")
3429     {
3430       if (++anArgIter >= theArgNb)
3431       {
3432         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3433         return 1;
3434       }
3435
3436       aScale = Draw::Atof (theArgVec[anArgIter]);
3437     }
3438     else if (aFlag == "-size"
3439           || aFlag == "-sizeratio")
3440     {
3441       if (++anArgIter >= theArgNb)
3442       {
3443         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3444         return 1;
3445       }
3446
3447       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3448     }
3449     else if (aFlag == "-arrowdiam"
3450           || aFlag == "-arrowdiameter")
3451     {
3452       if (++anArgIter >= theArgNb)
3453       {
3454         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3455         return 1;
3456       }
3457
3458       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3459     }
3460     else if (aFlag == "-nbfacets")
3461     {
3462       if (++anArgIter >= theArgNb)
3463       {
3464         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3465         return 1;
3466       }
3467
3468       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3469     }
3470     else if (aFlag == "-colorlabel"
3471           || aFlag == "-colorlabels")
3472     {
3473       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3474                                                            theArgVec + anArgIter + 1,
3475                                                            aLabelsColor);
3476       if (aNbParsed == 0)
3477       {
3478         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3479         return 1;
3480       }
3481       anArgIter += aNbParsed;
3482     }
3483     else if (aFlag == "-colorarrowx")
3484     {
3485       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3486                                                            theArgVec + anArgIter + 1,
3487                                                            anArrowColorX);
3488       if (aNbParsed == 0)
3489       {
3490         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3491         return 1;
3492       }
3493       anArgIter += aNbParsed;
3494     }
3495     else if (aFlag == "-colorarrowy")
3496     {
3497       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3498                                                            theArgVec + anArgIter + 1,
3499                                                            anArrowColorY);
3500       if (aNbParsed == 0)
3501       {
3502         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3503         return 1;
3504       }
3505       anArgIter += aNbParsed;
3506     }
3507     else if (aFlag == "-colorarrowz")
3508     {
3509       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3510                                                            theArgVec + anArgIter + 1,
3511                                                            anArrowColorZ);
3512       if (aNbParsed == 0)
3513       {
3514         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3515         return 1;
3516       }
3517       anArgIter += aNbParsed;
3518     }
3519     else
3520     {
3521       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3522       return 1;
3523     }
3524   }
3525
3526   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3527                                aSizeRatio, anArrowDiam, aNbFacets);
3528   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3529   aView->ZFitAll();
3530   return 0;
3531 }
3532
3533 //==============================================================================
3534 //function : VRotate
3535 //purpose  : Camera Rotating
3536 //==============================================================================
3537
3538 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3539 {
3540   Handle(V3d_View) aView = ViewerTest::CurrentView();
3541   if (aView.IsNull())
3542   {
3543     std::cout << "No active view!\n";
3544     return 1;
3545   }
3546
3547   Standard_Boolean hasFlags = Standard_False;
3548   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3549   {
3550     Standard_CString        anArg (theArgVec[anArgIter]);
3551     TCollection_AsciiString aFlag (anArg);
3552     aFlag.LowerCase();
3553     if (aFlag == "-mousestart"
3554      || aFlag == "-mousefrom")
3555     {
3556       hasFlags = Standard_True;
3557       if (anArgIter + 2 >= theArgNb)
3558       {
3559         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3560         return 1;
3561       }
3562
3563       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3564       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3565       aView->StartRotation (anX, anY);
3566     }
3567     else if (aFlag == "-mousemove")
3568     {
3569       hasFlags = Standard_True;
3570       if (anArgIter + 2 >= theArgNb)
3571       {
3572         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3573         return 1;
3574       }
3575
3576       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3577       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3578       aView->Rotation (anX, anY);
3579     }
3580     else if (theArgNb != 4
3581           && theArgNb != 7)
3582     {
3583       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3584       return 1;
3585     }
3586   }
3587
3588   if (hasFlags)
3589   {
3590     return 0;
3591   }
3592   else if (theArgNb == 4)
3593   {
3594     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3595     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3596     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3597     aView->Rotate (anAX, anAY, anAZ);
3598     return 0;
3599   }
3600   else if (theArgNb == 7)
3601   {
3602     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3603     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3604     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3605
3606     Standard_Real anX = Draw::Atof (theArgVec[4]);
3607     Standard_Real anY = Draw::Atof (theArgVec[5]);
3608     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3609
3610     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3611     return 0;
3612   }
3613
3614   std::cout << "Error: Invalid number of arguments\n";
3615   return 1;
3616 }
3617
3618 //==============================================================================
3619 //function : VZoom
3620 //purpose  : View zoom in / out (relative to current zoom)
3621 //==============================================================================
3622
3623 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3624   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3625   if ( V3dView.IsNull() ) {
3626     return 1;
3627   }
3628
3629   if ( argc == 2 ) {
3630     Standard_Real coef = Draw::Atof(argv[1]);
3631     if ( coef <= 0.0 ) {
3632       di << argv[1] << "Invalid value\n";
3633       return 1;
3634     }
3635     V3dView->SetZoom( Draw::Atof(argv[1]) );
3636     return 0;
3637   } else {
3638     di << argv[0] << " Invalid number of arguments\n";
3639     return 1;
3640   }
3641 }
3642
3643 //==============================================================================
3644 //function : VPan
3645 //purpose  : View panning (in pixels)
3646 //==============================================================================
3647
3648 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3649   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3650   if ( V3dView.IsNull() ) return 1;
3651
3652   if ( argc == 3 ) {
3653     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3654     return 0;
3655   } else {
3656     di << argv[0] << " Invalid number of arguments\n";
3657     return 1;
3658   }
3659 }
3660
3661 //==============================================================================
3662 //function : VPlace
3663 //purpose  : Place the point (in pixels) at the center of the window
3664 //==============================================================================
3665 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3666 {
3667   Handle(V3d_View) aView = ViewerTest::CurrentView();
3668   if (aView.IsNull())
3669   {
3670     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3671     return 1;
3672   }
3673
3674   if (theArgNb != 3)
3675   {
3676     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3677     return 1;
3678   }
3679
3680   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3681
3682   return 0;
3683 }
3684
3685 static int VColorScale (Draw_Interpretor& theDI,
3686                         Standard_Integer  theArgNb,
3687                         const char**      theArgVec)
3688 {
3689   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3690   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3691   if (aContext.IsNull())
3692   {
3693     std::cout << "Error: no active view!\n";
3694     return 1;
3695   }
3696   if (theArgNb <= 1)
3697   {
3698     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3699     return 1;
3700   }
3701
3702   Handle(AIS_ColorScale) aColorScale;
3703   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3704   {
3705     // find existing object
3706     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3707     if (aColorScale.IsNull())
3708     {
3709       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3710       return 1;
3711     }
3712   }
3713
3714   if (theArgNb <= 2)
3715   {
3716     if (aColorScale.IsNull())
3717     {
3718       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3719       return 1;
3720     }
3721
3722     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3723           << "Min range: "            << aColorScale->GetMin() << "\n"
3724           << "Max range: "            << aColorScale->GetMax() << "\n"
3725           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3726           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3727           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3728           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3729           << "Label position: ";
3730     switch (aColorScale->GetLabelPosition())
3731     {
3732       case Aspect_TOCSP_NONE:
3733         theDI << "None\n";
3734         break;
3735       case Aspect_TOCSP_LEFT:
3736         theDI << "Left\n";
3737         break;
3738       case Aspect_TOCSP_RIGHT:
3739         theDI << "Right\n";
3740         break;
3741       case Aspect_TOCSP_CENTER:
3742         theDI << "Center\n";
3743         break;
3744     }
3745     return 0;
3746   }
3747
3748   if (aColorScale.IsNull())
3749   {
3750     aColorScale = new AIS_ColorScale();
3751     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3752     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3753   }
3754
3755   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3756   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3757   {
3758     Standard_CString        anArg = theArgVec[anArgIter];
3759     TCollection_AsciiString aFlag (anArg);
3760     aFlag.LowerCase();
3761     if (anUpdateTool.parseRedrawMode (aFlag))
3762     {
3763       continue;
3764     }
3765     else if (aFlag == "-range")
3766     {
3767       if (anArgIter + 3 >= theArgNb)
3768       {
3769         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3770         return 1;
3771       }
3772
3773       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3774       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3775       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3776       if (!aRangeMin.IsRealValue()
3777        || !aRangeMax.IsRealValue())
3778       {
3779         std::cout << "Error: the range values should be real!\n";
3780         return 1;
3781       }
3782       else if (!aNbIntervals.IsIntegerValue())
3783       {
3784         std::cout << "Error: the number of intervals should be integer!\n";
3785         return 1;
3786       }
3787
3788       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3789       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3790     }
3791     else if (aFlag == "-font")
3792     {
3793       if (anArgIter + 1 >= theArgNb)
3794       {
3795         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3796         return 1;
3797       }
3798       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3799       if (!aFontArg.IsIntegerValue())
3800       {
3801         std::cout << "Error: HeightFont value should be integer!\n";
3802         return 1;
3803       }
3804
3805       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3806       anArgIter += 1;
3807     }
3808     else if (aFlag == "-textpos")
3809     {
3810       if (anArgIter + 1 >= theArgNb)
3811       {
3812         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3813         return 1;
3814       }
3815
3816       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3817       aTextPosArg.LowerCase();
3818       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3819       if (aTextPosArg == "none")
3820       {
3821         aLabPosition = Aspect_TOCSP_NONE;
3822       }
3823       else if (aTextPosArg == "left")
3824       {
3825         aLabPosition = Aspect_TOCSP_LEFT;
3826       }
3827       else if (aTextPosArg == "right")
3828       {
3829         aLabPosition = Aspect_TOCSP_RIGHT;
3830       }
3831       else if (aTextPosArg == "center")
3832       {
3833         aLabPosition = Aspect_TOCSP_CENTER;
3834       }
3835       else
3836       {
3837         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3838         return 1;
3839       }
3840       aColorScale->SetLabelPosition (aLabPosition);
3841     }
3842     else if (aFlag == "-logarithmic"
3843           || aFlag == "-log")
3844     {
3845       if (anArgIter + 1 >= theArgNb)
3846       {
3847         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3848         return 1;
3849       }
3850
3851       Standard_Boolean IsLog;
3852       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3853       {
3854         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3855         return 1;
3856       }
3857       aColorScale->SetLogarithmic (IsLog);
3858     }
3859     else if (aFlag == "-huerange"
3860           || aFlag == "-hue")
3861     {
3862       if (anArgIter + 2 >= theArgNb)
3863       {
3864         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3865         return 1;
3866       }
3867
3868       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3869       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3870       aColorScale->SetHueRange (aHueMin, aHueMax);
3871     }
3872     else if (aFlag == "-colorrange")
3873     {
3874       Quantity_Color aColorMin, aColorMax;
3875       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3876                                                             theArgVec + (anArgIter + 1),
3877                                                             aColorMin);
3878       anArgIter += aNbParsed1;
3879       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3880                                                             theArgVec + (anArgIter + 1),
3881                                                             aColorMax);
3882       anArgIter += aNbParsed2;
3883       if (aNbParsed1 == 0
3884        || aNbParsed2 == 0)
3885       {
3886         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3887         return 1;
3888       }
3889
3890       aColorScale->SetColorRange (aColorMin, aColorMax);
3891     }
3892     else if (aFlag == "-reversed"
3893           || aFlag == "-inverted"
3894           || aFlag == "-topdown"
3895           || aFlag == "-bottomup")
3896     {
3897       Standard_Boolean toEnable = Standard_True;
3898       if (anArgIter + 1 < theArgNb
3899        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3900       {
3901         ++anArgIter;
3902       }
3903       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3904     }
3905     else if (aFlag == "-smooth"
3906           || aFlag == "-smoothtransition")
3907     {
3908       Standard_Boolean toEnable = Standard_True;
3909       if (anArgIter + 1 < theArgNb
3910        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3911       {
3912         ++anArgIter;
3913       }
3914       aColorScale->SetSmoothTransition (toEnable);
3915     }
3916     else if (aFlag == "-xy")
3917     {
3918       if (anArgIter + 2 >= theArgNb)
3919       {
3920         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3921         return 1;
3922       }
3923
3924       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3925       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3926       if (!anX.IsIntegerValue()
3927        || !anY.IsIntegerValue())
3928       {
3929         std::cout << "Error: coordinates should be integer values!\n";
3930         return 1;
3931       }
3932
3933       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3934     }
3935     else if (aFlag == "-width"
3936           || aFlag == "-w"
3937           || aFlag == "-breadth")
3938     {
3939       if (anArgIter + 1 >= theArgNb)
3940       {
3941         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3942         return 1;
3943       }
3944
3945       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3946       if (!aBreadth.IsIntegerValue())
3947       {
3948         std::cout << "Error: a width should be an integer value!\n";
3949         return 1;
3950       }
3951       aColorScale->SetBreadth (aBreadth.IntegerValue());
3952     }
3953     else if (aFlag == "-height"
3954           || aFlag == "-h")
3955     {
3956       if (anArgIter + 1 >= theArgNb)
3957       {
3958         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3959         return 1;
3960       }
3961
3962       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3963       if (!aHeight.IsIntegerValue())
3964       {
3965         std::cout << "Error: a width should be an integer value!\n";
3966         return 1;
3967       }
3968       aColorScale->SetHeight (aHeight.IntegerValue());
3969     }
3970     else if (aFlag == "-color")
3971     {
3972       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3973       {
3974         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3975         return 1;
3976       }
3977       else if (anArgIter + 2 >= theArgNb)
3978       {
3979         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3980         return 1;
3981       }
3982
3983       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3984       if (!anInd.IsIntegerValue())
3985       {
3986         std::cout << "Error: Index value should be integer!\n";
3987         return 1;
3988       }
3989       const Standard_Integer anIndex = anInd.IntegerValue();
3990       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3991       {
3992         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3993         return 1;
3994       }
3995
3996       Quantity_Color aColor;
3997       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3998                                                            theArgVec + (anArgIter + 1),
3999                                                            aColor);
4000       if (aNbParsed == 0)
4001       {
4002         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4003         return 1;
4004       }
4005       aColorScale->SetIntervalColor (aColor, anIndex);
4006       aColorScale->SetColorType (Aspect_TOCSD_USER);
4007       anArgIter += aNbParsed;
4008     }
4009     else if (aFlag == "-label")
4010     {
4011       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4012       {
4013         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4014         return 1;
4015       }
4016       else if (anArgIter + 2 >= theArgNb)
4017       {
4018         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4019         return 1;
4020       }
4021
4022       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4023       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4024       {
4025         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4026         return 1;
4027       }
4028
4029       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4030       aColorScale->SetLabel     (aText, anIndex);
4031       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4032       anArgIter += 2;
4033     }
4034     else if (aFlag == "-labelat"
4035           || aFlag == "-labat"
4036           || aFlag == "-labelatborder"
4037           || aFlag == "-labatborder"
4038           || aFlag == "-labelatcenter"
4039           || aFlag == "-labatcenter")
4040     {
4041       Standard_Boolean toEnable = Standard_True;
4042       if (aFlag == "-labelat"
4043        || aFlag == "-labat")
4044       {
4045         Standard_Integer aLabAtBorder = -1;
4046         if (++anArgIter >= theArgNb)
4047         {
4048           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4049           anAtBorder.LowerCase();
4050           if (anAtBorder == "border")
4051           {
4052             aLabAtBorder = 1;
4053           }
4054           else if (anAtBorder == "center")
4055           {
4056             aLabAtBorder = 0;
4057           }
4058         }
4059         if (aLabAtBorder == -1)
4060         {
4061           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4062           return 1;
4063         }
4064         toEnable = (aLabAtBorder == 1);
4065       }
4066       else if (anArgIter + 1 < theArgNb
4067             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4068       {
4069         ++anArgIter;
4070       }
4071       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4072                                   || aFlag == "-labatcenter"
4073                                    ? !toEnable
4074                                    :  toEnable);
4075     }
4076     else if (aFlag == "-colors")
4077     {
4078       Aspect_SequenceOfColor aSeq;
4079       for (;;)
4080       {
4081         Quantity_Color aColor;
4082         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4083                                                              theArgVec + (anArgIter + 1),
4084                                                              aColor);
4085         if (aNbParsed == 0)
4086         {
4087           break;
4088         }
4089         anArgIter += aNbParsed;
4090         aSeq.Append (aColor);
4091       }
4092       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4093       {
4094         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4095                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4096         return 1;
4097       }
4098
4099       aColorScale->SetColors    (aSeq);
4100       aColorScale->SetColorType (Aspect_TOCSD_USER);
4101     }
4102     else if (aFlag == "-labels"
4103           || aFlag == "-freelabels")
4104     {
4105       if (anArgIter + 1 >= theArgNb)
4106       {
4107         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4108         return 1;
4109       }
4110
4111       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4112                                  ? aColorScale->GetNumberOfIntervals() + 1
4113                                  : aColorScale->GetNumberOfIntervals();
4114       if (aFlag == "-freelabels")
4115       {
4116         ++anArgIter;
4117         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4118       }
4119       if (anArgIter + aNbLabels >= theArgNb)
4120       {
4121         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4122         return 1;
4123       }
4124
4125       TColStd_SequenceOfExtendedString aSeq;
4126       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4127       {
4128         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4129       }
4130       aColorScale->SetLabels (aSeq);
4131       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4132     }
4133     else if (aFlag == "-title")
4134     {
4135       if (anArgIter + 1 >= theArgNb)
4136       {
4137         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4138         return 1;
4139       }
4140
4141       Standard_Boolean isTwoArgs = Standard_False;
4142       if (anArgIter + 2 < theArgNb)
4143       {
4144         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4145         aSecondArg.LowerCase();
4146       Standard_DISABLE_DEPRECATION_WARNINGS
4147         if (aSecondArg == "none")
4148         {
4149           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4150           isTwoArgs = Standard_True;
4151         }
4152         else if (aSecondArg == "left")
4153         {
4154           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4155           isTwoArgs = Standard_True;
4156         }
4157         else if (aSecondArg == "right")
4158         {
4159           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4160           isTwoArgs = Standard_True;
4161         }
4162         else if (aSecondArg == "center")
4163         {
4164           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4165           isTwoArgs = Standard_True;
4166         }
4167       Standard_ENABLE_DEPRECATION_WARNINGS
4168       }
4169
4170       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4171       if (isTwoArgs)
4172       {
4173         anArgIter += 1;
4174       }
4175       anArgIter += 1;
4176     }
4177     else if (aFlag == "-demoversion"
4178           || aFlag == "-demo")
4179     {
4180       aColorScale->SetPosition (0, 0);
4181       aColorScale->SetTextHeight (16);
4182       aColorScale->SetRange (0.0, 100.0);
4183       aColorScale->SetNumberOfIntervals (10);
4184       aColorScale->SetBreadth (0);
4185       aColorScale->SetHeight  (0);
4186       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4187       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4188       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4189     }
4190     else if (aFlag == "-findcolor")
4191     {
4192       if (anArgIter + 1 >= theArgNb)
4193       {
4194         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4195         return 1;
4196       }
4197
4198       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4199
4200       if (!anArg1.IsRealValue())
4201       {
4202         std::cout << "Error: the value should be real!\n";
4203         return 1;
4204       }
4205
4206       Quantity_Color aColor;
4207       aColorScale->FindColor (anArg1.RealValue(), aColor);
4208       theDI << Quantity_Color::StringName (aColor.Name());
4209       return 0;
4210     }
4211     else
4212     {
4213       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4214       return 1;
4215     }
4216   }
4217
4218   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4219   aView->Window()->Size (aWinWidth, aWinHeight);
4220   if (aColorScale->GetBreadth() == 0)
4221   {
4222     aColorScale->SetBreadth (aWinWidth);
4223   }
4224   if (aColorScale->GetHeight() == 0)
4225   {
4226     aColorScale->SetHeight (aWinHeight);
4227   }
4228   aColorScale->SetToUpdate();
4229   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4230   return 0;
4231 }
4232
4233 //==============================================================================
4234 //function : VGraduatedTrihedron
4235 //purpose  : Displays or hides a graduated trihedron
4236 //==============================================================================
4237 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4238                                   Quantity_Color& theColor)
4239 {
4240   Quantity_NameOfColor aColorName;
4241   TCollection_AsciiString aVal = theValue;
4242   aVal.UpperCase();
4243   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4244   {
4245     return Standard_False;
4246   }
4247   theColor = Quantity_Color (aColorName);
4248   return Standard_True;
4249 }
4250
4251 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4252 {
4253   if (theArgNum < 2)
4254   {
4255     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4256               << theArgs[0] <<"' for more information.\n";
4257     return 1;  //TCL_ERROR
4258   }
4259
4260   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4261   TCollection_AsciiString aParseKey;
4262   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4263   {
4264     TCollection_AsciiString anArg (theArgs [anArgIt]);
4265
4266     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4267     {
4268       aParseKey = anArg;
4269       aParseKey.Remove (1);
4270       aParseKey.LowerCase();
4271       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4272       continue;
4273     }
4274
4275     if (aParseKey.IsEmpty())
4276     {
4277       continue;
4278     }
4279
4280     aMapOfArgs(aParseKey)->Append (anArg);
4281   }
4282
4283   // Check parameters
4284   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4285        aMapIt.More(); aMapIt.Next())
4286   {
4287     const TCollection_AsciiString& aKey = aMapIt.Key();
4288     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4289
4290     // Bool key, without arguments
4291     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4292         && anArgs->IsEmpty())
4293     {
4294       continue;
4295     }
4296
4297     // One argument
4298     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4299           && anArgs->Length() == 1)
4300     {
4301       continue;
4302     }
4303
4304     // On/off arguments
4305     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4306         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4307         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4308         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4309         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4310     {
4311       continue;
4312     }
4313
4314     // One string argument
4315     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4316           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4317           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4318     {
4319       continue;
4320     }
4321
4322     // One integer argument
4323     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4324           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4325           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4326           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4327          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4328     {
4329       continue;
4330     }
4331
4332     // One real argument
4333     if ( aKey.IsEqual ("arrowlength")
4334          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4335     {
4336       continue;
4337     }
4338
4339     // Two string arguments
4340     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4341          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4342     {
4343       continue;
4344     }
4345
4346     TCollection_AsciiString aLowerKey;
4347     aLowerKey  = "-";
4348     aLowerKey += aKey;
4349     aLowerKey.LowerCase();
4350     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4351     std::cout << "Type help for more information.\n";
4352     return 1;
4353   }
4354
4355   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4356   if (anAISContext.IsNull())
4357   {
4358     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4359     return 1;
4360   }
4361
4362   Standard_Boolean toDisplay = Standard_True;
4363   Quantity_Color aColor;
4364   Graphic3d_GraduatedTrihedron aTrihedronData;
4365   // Process parameters
4366   Handle(TColStd_HSequenceOfAsciiString) aValues;
4367   if (aMapOfArgs.Find ("off", aValues))
4368   {
4369     toDisplay = Standard_False;
4370   }
4371
4372   // AXES NAMES
4373   if (aMapOfArgs.Find ("xname", aValues))
4374   {
4375     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4376   }
4377   if (aMapOfArgs.Find ("yname", aValues))
4378   {
4379     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4380   }
4381   if (aMapOfArgs.Find ("zname", aValues))
4382   {
4383     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4384   }
4385   if (aMapOfArgs.Find ("xdrawname", aValues))
4386   {
4387     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4388   }
4389   if (aMapOfArgs.Find ("ydrawname", aValues))
4390   {
4391     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4392   }
4393   if (aMapOfArgs.Find ("zdrawname", aValues))
4394   {
4395     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4396   }
4397   if (aMapOfArgs.Find ("xnameoffset", aValues))
4398   {
4399     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4400   }
4401   if (aMapOfArgs.Find ("ynameoffset", aValues))
4402   {
4403     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4404   }
4405   if (aMapOfArgs.Find ("znameoffset", aValues))
4406   {
4407     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4408   }
4409
4410   // COLORS
4411   if (aMapOfArgs.Find ("xnamecolor", aValues))
4412   {
4413     if (!GetColor (aValues->Value(1), aColor))
4414     {
4415       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4416       return 1;
4417     }
4418     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4419   }
4420   if (aMapOfArgs.Find ("ynamecolor", aValues))
4421   {
4422     if (!GetColor (aValues->Value(1), aColor))
4423     {
4424       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4425       return 1;
4426     }
4427     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4428   }
4429   if (aMapOfArgs.Find ("znamecolor", aValues))
4430   {
4431     if (!GetColor (aValues->Value(1), aColor))
4432     {
4433       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4434       return 1;
4435     }
4436     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4437   }
4438   if (aMapOfArgs.Find ("xcolor", aValues))
4439   {
4440     if (!GetColor (aValues->Value(1), aColor))
4441     {
4442       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4443       return 1;
4444     }
4445     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4446   }
4447   if (aMapOfArgs.Find ("ycolor", aValues))
4448   {
4449     if (!GetColor (aValues->Value(1), aColor))
4450     {
4451       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4452       return 1;
4453     }
4454     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4455   }
4456   if (aMapOfArgs.Find ("zcolor", aValues))
4457   {
4458     if (!GetColor (aValues->Value(1), aColor))
4459     {
4460       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4461       return 1;
4462     }
4463     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4464   }
4465
4466   // TICKMARKS
4467   if (aMapOfArgs.Find ("xticks", aValues))
4468   {
4469     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4470   }
4471   if (aMapOfArgs.Find ("yticks", aValues))
4472   {
4473     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4474   }
4475   if (aMapOfArgs.Find ("zticks", aValues))
4476   {
4477     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4478   }
4479   if (aMapOfArgs.Find ("xticklength", aValues))
4480   {
4481     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4482   }
4483   if (aMapOfArgs.Find ("yticklength", aValues))
4484   {
4485     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4486   }
4487   if (aMapOfArgs.Find ("zticklength", aValues))
4488   {
4489     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4490   }
4491   if (aMapOfArgs.Find ("xdrawticks", aValues))
4492   {
4493     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4494   }
4495   if (aMapOfArgs.Find ("ydrawticks", aValues))
4496   {
4497     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4498   }
4499   if (aMapOfArgs.Find ("zdrawticks", aValues))
4500   {
4501     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4502   }
4503
4504   // VALUES
4505   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4506   {
4507     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4508   }
4509   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4510   {
4511     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4512   }
4513   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4514   {
4515     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4516   }
4517   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4518   {
4519     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4520   }
4521   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4522   {
4523     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4524   }
4525   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4526   {
4527     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4528   }
4529
4530   // ARROWS
4531   if (aMapOfArgs.Find ("arrowlength", aValues))
4532   {
4533     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4534   }
4535
4536   // FONTS
4537   if (aMapOfArgs.Find ("namefont", aValues))
4538   {
4539     aTrihedronData.SetNamesFont (aValues->Value(1));
4540   }
4541   if (aMapOfArgs.Find ("valuesfont", aValues))
4542   {
4543     aTrihedronData.SetValuesFont (aValues->Value(1));
4544   }
4545
4546   if (aMapOfArgs.Find ("drawgrid", aValues))
4547   {
4548     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4549   }
4550   if (aMapOfArgs.Find ("drawaxes", aValues))
4551   {
4552     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4553   }
4554
4555   // The final step: display of erase trihedron
4556   if (toDisplay)
4557   {
4558     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4559   }
4560   else
4561   {
4562     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4563   }
4564
4565   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4566   ViewerTest::CurrentView()->Redraw();
4567
4568   return 0;
4569 }
4570
4571 //==============================================================================
4572 //function : VTile
4573 //purpose  :
4574 //==============================================================================
4575 static int VTile (Draw_Interpretor& theDI,
4576                   Standard_Integer  theArgNb,
4577                   const char**      theArgVec)
4578 {
4579   Handle(V3d_View) aView = ViewerTest::CurrentView();
4580   if (aView.IsNull())
4581   {
4582     std::cerr << "Error: no active viewer.\n";
4583     return 1;
4584   }
4585
4586   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4587   if (theArgNb < 2)
4588   {
4589     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4590           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4591           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4592     return 0;
4593   }
4594
4595   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4596   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4597   {
4598     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4599     anArg.LowerCase();
4600     if (anArg == "-lowerleft"
4601      || anArg == "-upperleft")
4602     {
4603       if (anArgIter + 3 < theArgNb)
4604       {
4605         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4606         return 1;
4607       }
4608       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4609       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4610       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4611     }
4612     else if (anArg == "-total"
4613           || anArg == "-totalsize"
4614           || anArg == "-viewsize")
4615     {
4616       if (anArgIter + 3 < theArgNb)
4617       {
4618         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4619         return 1;
4620       }
4621       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4622       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4623       if (aTile.TotalSize.x() < 1
4624        || aTile.TotalSize.y() < 1)
4625       {
4626         std::cerr << "Error: total size is incorrect.\n";
4627         return 1;
4628       }
4629     }
4630     else if (anArg == "-tilesize")
4631     {
4632       if (anArgIter + 3 < theArgNb)
4633       {
4634         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4635         return 1;
4636       }
4637
4638       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4639       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4640       if (aTile.TileSize.x() < 1
4641        || aTile.TileSize.y() < 1)
4642       {
4643         std::cerr << "Error: tile size is incorrect.\n";
4644         return 1;
4645       }
4646     }
4647     else if (anArg == "-unset")
4648     {
4649       aView->Camera()->SetTile (Graphic3d_CameraTile());
4650       aView->Redraw();
4651       return 0;
4652     }
4653   }
4654
4655   if (aTile.TileSize.x() < 1
4656    || aTile.TileSize.y() < 1)
4657   {
4658     std::cerr << "Error: tile size is undefined.\n";
4659     return 1;
4660   }
4661   else if (aTile.TotalSize.x() < 1
4662         || aTile.TotalSize.y() < 1)
4663   {
4664     std::cerr << "Error: total size is undefined.\n";
4665     return 1;
4666   }
4667
4668   aView->Camera()->SetTile (aTile);
4669   aView->Redraw();
4670   return 0;
4671 }
4672
4673 //! Format ZLayer ID.
4674 inline const char* formZLayerId (const Standard_Integer theLayerId)
4675 {
4676   switch (theLayerId)
4677   {
4678     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4679     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4680     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4681     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4682     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4683     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4684   }
4685   return "";
4686 }
4687
4688 //! Print the ZLayer information.
4689 inline void printZLayerInfo (Draw_Interpretor& theDI,
4690                              const Graphic3d_ZLayerSettings& theLayer)
4691 {
4692   if (!theLayer.Name().IsEmpty())
4693   {
4694     theDI << "  Name: " << theLayer.Name() << "\n";
4695   }
4696   if (theLayer.IsImmediate())
4697   {
4698     theDI << "  Immediate: TRUE\n";
4699   }
4700   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4701   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
4702   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
4703   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4704   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4705   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4706   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4707   {
4708     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4709   }
4710 }
4711
4712 //==============================================================================
4713 //function : VZLayer
4714 //purpose  : Test z layer operations for v3d viewer
4715 //==============================================================================
4716 static int VZLayer (Draw_Interpretor& theDI,
4717                     Standard_Integer  theArgNb,
4718                     const char**      theArgVec)
4719 {
4720   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4721   if (aContextAIS.IsNull())
4722   {
4723     std::cout << "No active viewer!\n";
4724     return 1;
4725   }
4726
4727   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4728   if (theArgNb < 2)
4729   {
4730     TColStd_SequenceOfInteger aLayers;
4731     aViewer->GetAllZLayers (aLayers);
4732     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4733     {
4734       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4735       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4736       printZLayerInfo (theDI, aSettings);
4737     }
4738     return 1;
4739   }
4740
4741   Standard_Integer anArgIter = 1;
4742   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4743   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4744   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4745   {
4746     ++anArgIter;
4747   }
4748
4749   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4750   if (aFirstArg.IsIntegerValue())
4751   {
4752     ++anArgIter;
4753     aLayerId = aFirstArg.IntegerValue();
4754   }
4755   else
4756   {
4757     aFirstArg.LowerCase();
4758     if (aFirstArg == "default"
4759      || aFirstArg == "def")
4760     {
4761       aLayerId = Graphic3d_ZLayerId_Default;
4762       ++anArgIter;
4763     }
4764     else if (aFirstArg == "top")
4765     {
4766       aLayerId = Graphic3d_ZLayerId_Top;
4767       ++anArgIter;
4768     }
4769     else if (aFirstArg == "topmost")
4770     {
4771       aLayerId = Graphic3d_ZLayerId_Topmost;
4772       ++anArgIter;
4773     }
4774     else if (aFirstArg == "overlay"
4775           || aFirstArg == "toposd")
4776     {
4777       aLayerId = Graphic3d_ZLayerId_TopOSD;
4778       ++anArgIter;
4779     }
4780     else if (aFirstArg == "underlay"
4781           || aFirstArg == "botosd")
4782     {
4783       aLayerId = Graphic3d_ZLayerId_BotOSD;
4784       ++anArgIter;
4785     }
4786     else
4787     {
4788       TColStd_SequenceOfInteger aLayers;
4789       aViewer->GetAllZLayers (aLayers);
4790       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4791       {
4792         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4793         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4794         {
4795           aLayerId = aLayeriter.Value();
4796           ++anArgIter;
4797           break;
4798         }
4799       }
4800     }
4801   }
4802
4803   for (; anArgIter < theArgNb; ++anArgIter)
4804   {
4805     // perform operation
4806     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4807     anArg.LowerCase();
4808     if (anUpdateTool.parseRedrawMode (anArg))
4809     {
4810       //
4811     }
4812     else if (anArg == "-add"
4813           || anArg == "add")
4814     {
4815       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4816       if (!aViewer->AddZLayer (aLayerId))
4817       {
4818         std::cout << "Error: can not add a new z layer!\n";
4819         return 0;
4820       }
4821
4822       theDI << aLayerId;
4823     }
4824     else if (anArg == "-del"
4825           || anArg == "-delete"
4826           || anArg == "del")
4827     {
4828       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4829       {
4830         if (++anArgIter >= theArgNb)
4831         {
4832           std::cout << "Syntax error: id of z layer to remove is missing\n";
4833           return 1;
4834         }
4835
4836         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4837       }
4838
4839       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4840        || aLayerId == Graphic3d_ZLayerId_Default
4841        || aLayerId == Graphic3d_ZLayerId_Top
4842        || aLayerId == Graphic3d_ZLayerId_Topmost
4843        || aLayerId == Graphic3d_ZLayerId_TopOSD
4844        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4845       {
4846         std::cout << "Syntax error: standard Z layer can not be removed\n";
4847         return 1;
4848       }
4849
4850       // move all object displayed in removing layer to default layer
4851       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4852            anObjIter.More(); anObjIter.Next())
4853       {
4854         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
4855         if (aPrs.IsNull()
4856          || aPrs->ZLayer() != aLayerId)
4857         {
4858           continue;
4859         }
4860         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4861       }
4862
4863       if (!aViewer->RemoveZLayer (aLayerId))
4864       {
4865         std::cout << "Z layer can not be removed!\n";
4866       }
4867       else
4868       {
4869         theDI << aLayerId << " ";
4870       }
4871     }
4872     else if (anArg == "-get"
4873           || anArg == "get")
4874     {
4875       TColStd_SequenceOfInteger aLayers;
4876       aViewer->GetAllZLayers (aLayers);
4877       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4878       {
4879         theDI << aLayeriter.Value() << " ";
4880       }
4881
4882       theDI << "\n";
4883     }
4884     else if (anArg == "-name")
4885     {
4886       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4887       {
4888         std::cout << "Syntax error: id of Z layer is missing\n";
4889         return 1;
4890       }
4891
4892       if (++anArgIter >= theArgNb)
4893       {
4894         std::cout << "Syntax error: name is missing\n";
4895         return 1;
4896       }
4897
4898       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4899       aSettings.SetName (theArgVec[anArgIter]);
4900       aViewer->SetZLayerSettings (aLayerId, aSettings);
4901     }
4902     else if (anArg == "-origin")
4903     {
4904       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4905       {
4906         std::cout << "Syntax error: id of Z layer is missing\n";
4907         return 1;
4908       }
4909
4910       if (anArgIter + 2 >= theArgNb)
4911       {
4912         std::cout << "Syntax error: origin coordinates are missing\n";
4913         return 1;
4914       }
4915
4916       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4917       gp_XYZ anOrigin;
4918       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4919       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4920       anOrigin.SetZ (0.0);
4921       if (anArgIter + 3 < theArgNb)
4922       {
4923         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4924         anArgIter += 3;
4925       }
4926       else
4927       {
4928         anArgIter += 2;
4929       }
4930       aSettings.SetOrigin (anOrigin);
4931       aViewer->SetZLayerSettings (aLayerId, aSettings);
4932     }
4933     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4934           && anArgIter + 1 < theArgNb
4935           && (anArg == "-cullingdistance"
4936            || anArg == "-cullingdist"
4937            || anArg == "-culldistance"
4938            || anArg == "-culldist"
4939            || anArg == "-distcull"
4940            || anArg == "-distculling"
4941            || anArg == "-distanceculling"))
4942     {
4943       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4944       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
4945       aSettings.SetCullingDistance (aDist);
4946       aViewer->SetZLayerSettings (aLayerId, aSettings);
4947     }
4948     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4949           && anArgIter + 1 < theArgNb
4950           && (anArg == "-cullingsize"
4951            || anArg == "-cullsize"
4952            || anArg == "-sizecull"
4953            || anArg == "-sizeculling"))
4954     {
4955       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4956       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
4957       aSettings.SetCullingSize (aSize);
4958       aViewer->SetZLayerSettings (aLayerId, aSettings);
4959     }
4960     else if (anArg == "-settings"
4961           || anArg == "settings")
4962     {
4963       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4964       {
4965         if (++anArgIter >= theArgNb)
4966         {
4967           std::cout << "Syntax error: id of Z layer is missing\n";
4968           return 1;
4969         }
4970
4971         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4972       }
4973
4974       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4975       printZLayerInfo (theDI, aSettings);
4976     }
4977     else if (anArg == "-enable"
4978           || anArg == "enable"
4979           || anArg == "-disable"
4980           || anArg == "disable")
4981     {
4982       const Standard_Boolean toEnable = anArg == "-enable"
4983                                      || anArg == "enable";
4984       if (++anArgIter >= theArgNb)
4985       {
4986         std::cout << "Syntax error: option name is missing\n";
4987         return 1;
4988       }
4989
4990       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4991       aSubOp.LowerCase();
4992       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4993       {
4994         if (++anArgIter >= theArgNb)
4995         {
4996           std::cout << "Syntax error: id of Z layer is missing\n";
4997           return 1;
4998         }
4999
5000         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5001       }
5002
5003       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5004       if (aSubOp == "depthtest"
5005        || aSubOp == "test")
5006       {
5007         aSettings.SetEnableDepthTest (toEnable);
5008       }
5009       else if (aSubOp == "depthwrite"
5010             || aSubOp == "write")
5011       {
5012         aSettings.SetEnableDepthWrite (toEnable);
5013       }
5014       else if (aSubOp == "depthclear"
5015             || aSubOp == "clear")
5016       {
5017         aSettings.SetClearDepth (toEnable);
5018       }
5019       else if (aSubOp == "depthoffset"
5020             || aSubOp == "offset")
5021       {
5022         Graphic3d_PolygonOffset aParams;
5023         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5024         if (toEnable)
5025         {
5026           if (anArgIter + 2 >= theArgNb)
5027           {
5028             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5029             return 1;
5030           }
5031
5032           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5033           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5034         }
5035         aSettings.SetPolygonOffset (aParams);
5036       }
5037       else if (aSubOp == "positiveoffset"
5038             || aSubOp == "poffset")
5039       {
5040         if (toEnable)
5041         {
5042           aSettings.SetDepthOffsetPositive();
5043         }
5044         else
5045         {
5046           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5047         }
5048       }
5049       else if (aSubOp == "negativeoffset"
5050             || aSubOp == "noffset")
5051       {
5052         if (toEnable)
5053         {
5054           aSettings.SetDepthOffsetNegative();
5055         }
5056         else
5057         {
5058           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5059         }
5060       }
5061       else if (aSubOp == "textureenv")
5062       {
5063         aSettings.SetEnvironmentTexture (toEnable);
5064       }
5065
5066       aViewer->SetZLayerSettings (aLayerId, aSettings);
5067     }
5068     else
5069     {
5070       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5071       return 1;
5072     }
5073   }
5074
5075   return 0;
5076 }
5077
5078 // The interactive presentation of 2d layer item
5079 // for "vlayerline" command it provides a presentation of
5080 // line with user-defined linewidth, linetype and transparency.
5081 class V3d_LineItem : public AIS_InteractiveObject
5082 {
5083 public:
5084   // CASCADE RTTI
5085   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5086
5087   // constructor
5088   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5089                                Standard_Real X2, Standard_Real Y2,
5090                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5091                                Standard_Real theWidth    = 0.5,
5092                                Standard_Real theTransp   = 1.0);
5093
5094   private:
5095
5096   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5097                 const Handle(Prs3d_Presentation)& thePresentation,
5098                 const Standard_Integer theMode) Standard_OVERRIDE;
5099
5100   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5101                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5102   {}
5103
5104 private:
5105
5106   Standard_Real       myX1, myY1, myX2, myY2;
5107   Aspect_TypeOfLine   myType;
5108   Standard_Real       myWidth;
5109 };
5110
5111 // default constructor for line item
5112 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5113                            Standard_Real X2, Standard_Real Y2,
5114                            Aspect_TypeOfLine theType,
5115                            Standard_Real theWidth,
5116                            Standard_Real theTransp) :
5117   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5118   myType(theType), myWidth(theWidth)
5119 {
5120   SetTransparency (1-theTransp);
5121 }
5122
5123 // render line
5124 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5125                             const Handle(Prs3d_Presentation)& thePresentation,
5126                             const Standard_Integer /*theMode*/)
5127 {
5128   thePresentation->Clear();
5129   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5130   Standard_Integer aWidth, aHeight;
5131   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5132   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5133   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5134   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5135   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5136   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5137   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5138   aGroup->AddPrimitiveArray (aPrim);
5139 }
5140
5141 //=============================================================================
5142 //function : VLayerLine
5143 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5144 //         : linewidth, transparency coefficient
5145 //============================================================================
5146 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5147 {
5148   // get the active view
5149   Handle(V3d_View) aView = ViewerTest::CurrentView();
5150   if (aView.IsNull())
5151   {
5152     di << "Call vinit before!\n";
5153     return 1;
5154   }
5155   else if (argc < 5)
5156   {
5157     di << "Use: " << argv[0];
5158     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5159     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5160     di << "              0 - solid  \n";
5161     di << "              1 - dashed \n";
5162     di << "              2 - dot    \n";
5163     di << "              3 - dashdot\n";
5164     di << " transparency : { 0.0 - 1.0 } \n";
5165     di << "                  0.0 - transparent\n";
5166     di << "                  1.0 - visible    \n";
5167     return 1;
5168   }
5169
5170   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5171   // get the input params
5172   Standard_Real X1 = Draw::Atof(argv[1]);
5173   Standard_Real Y1 = Draw::Atof(argv[2]);
5174   Standard_Real X2 = Draw::Atof(argv[3]);
5175   Standard_Real Y2 = Draw::Atof(argv[4]);
5176
5177   Standard_Real aWidth = 0.5;
5178   Standard_Real aTransparency = 1.0;
5179
5180   // has width
5181   if (argc > 5)
5182     aWidth = Draw::Atof(argv[5]);
5183
5184   // select appropriate line type
5185   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5186   if (argc > 6
5187   && !ViewerTest::ParseLineType (argv[6], aLineType))
5188   {
5189     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5190     return 1;
5191   }
5192
5193   // has transparency
5194   if (argc > 7)
5195   {
5196     aTransparency = Draw::Atof(argv[7]);
5197     if (aTransparency < 0 || aTransparency > 1.0)
5198       aTransparency = 1.0;
5199   }
5200
5201   static Handle (V3d_LineItem) aLine;
5202   if (!aLine.IsNull())
5203   {
5204     aContext->Erase (aLine, Standard_False);
5205   }
5206   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5207                             aLineType, aWidth,
5208                             aTransparency);
5209
5210   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5211   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5212   aLine->SetToUpdate();
5213   aContext->Display (aLine, Standard_True);
5214
5215   return 0;
5216 }
5217
5218
5219 //==============================================================================
5220 //function : VGrid
5221 //purpose  :
5222 //==============================================================================
5223
5224 static int VGrid (Draw_Interpretor& /*theDI*/,
5225                   Standard_Integer  theArgNb,
5226                   const char**      theArgVec)
5227 {
5228   // get the active view
5229   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5230   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5231   if (aView.IsNull() || aViewer.IsNull())
5232   {
5233     std::cerr << "No active view. Please call vinit.\n";
5234     return 1;
5235   }
5236
5237   Aspect_GridType     aType = aViewer->GridType();
5238   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5239   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5240   Standard_Integer anIter = 1;
5241   for (; anIter < theArgNb; ++anIter)
5242   {
5243     const char* aValue = theArgVec[anIter];
5244     if (anUpdateTool.parseRedrawMode (aValue))
5245     {
5246       continue;
5247     }
5248     else if (*aValue == 'r')
5249     {
5250       aType = Aspect_GT_Rectangular;
5251     }
5252     else if (*aValue == 'c')
5253     {
5254       aType = Aspect_GT_Circular;
5255     }
5256     else if (*aValue == 'l')
5257     {
5258       aMode = Aspect_GDM_Lines;
5259     }
5260     else if (*aValue == 'p')
5261     {
5262       aMode = Aspect_GDM_Points;
5263     }
5264     else if (strcmp (aValue, "off" ) == 0)
5265     {
5266       aViewer->DeactivateGrid();
5267       return 0;
5268     }
5269     else
5270     {
5271       break;
5272     }
5273   }
5274
5275   Standard_Integer aTail = (theArgNb - anIter);
5276   if (aTail == 0)
5277   {
5278     aViewer->ActivateGrid (aType, aMode);
5279     return 0;
5280   }
5281   else if (aTail != 2 && aTail != 5)
5282   {
5283     std::cerr << "Incorrect arguments number! Usage:\n"
5284               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5285     return 1;
5286   }
5287
5288   Standard_Real anOriginX, anOriginY, aRotAngle;
5289   if (aType == Aspect_GT_Rectangular)
5290   {
5291     Standard_Real aRStepX, aRStepY;
5292     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5293
5294     anOriginX = Draw::Atof (theArgVec[anIter++]);
5295     anOriginY = Draw::Atof (theArgVec[anIter++]);
5296     if (aTail == 5)
5297     {
5298       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5299       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5300       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5301     }
5302     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5303     aViewer->ActivateGrid (aType, aMode);
5304   }
5305   else if (aType == Aspect_GT_Circular)
5306   {
5307     Standard_Real aRadiusStep;
5308     Standard_Integer aDivisionNumber;
5309     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5310
5311     anOriginX = Draw::Atof (theArgVec[anIter++]);
5312     anOriginY = Draw::Atof (theArgVec[anIter++]);
5313     if (aTail == 5)
5314     {
5315       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5316       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5317       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5318     }
5319
5320     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5321     aViewer->ActivateGrid (aType, aMode);
5322   }
5323
5324   return 0;
5325 }
5326
5327 //==============================================================================
5328 //function : VPriviledgedPlane
5329 //purpose  :
5330 //==============================================================================
5331
5332 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5333                               Standard_Integer  theArgNb,
5334                               const char**      theArgVec)
5335 {
5336   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5337   {
5338     std::cerr << "Error: wrong number of arguments! See usage:\n";
5339     theDI.PrintHelp (theArgVec[0]);
5340     return 1;
5341   }
5342
5343   // get the active viewer
5344   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5345   if (aViewer.IsNull())
5346   {
5347     std::cerr << "Error: no active viewer. Please call vinit.\n";
5348     return 1;
5349   }
5350
5351   if (theArgNb == 1)
5352   {
5353     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5354     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5355     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5356     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5357     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5358           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5359           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5360     return 0;
5361   }
5362
5363   Standard_Integer anArgIdx = 1;
5364   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5365   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5366   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5367   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5368   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5369   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5370
5371   gp_Ax3 aPriviledgedPlane;
5372   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5373   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5374   if (theArgNb > 7)
5375   {
5376     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5377     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5378     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5379     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5380     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5381   }
5382   else
5383   {
5384     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5385   }
5386
5387   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5388
5389   return 0;
5390 }
5391
5392 //==============================================================================
5393 //function : VConvert
5394 //purpose  :
5395 //==============================================================================
5396
5397 static int VConvert (Draw_Interpretor& theDI,
5398                      Standard_Integer  theArgNb,
5399                      const char**      theArgVec)
5400 {
5401   // get the active view
5402   Handle(V3d_View) aView = ViewerTest::CurrentView();
5403   if (aView.IsNull())
5404   {
5405     std::cerr << "Error: no active view. Please call vinit.\n";
5406     return 1;
5407   }
5408
5409   enum { Model, Ray, View, Window, Grid } aMode = Model;
5410
5411   // access coordinate arguments
5412   TColStd_SequenceOfReal aCoord;
5413   Standard_Integer anArgIdx = 1;
5414   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5415   {
5416     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5417     if (!anArg.IsRealValue())
5418     {
5419       break;
5420     }
5421     aCoord.Append (anArg.RealValue());
5422   }
5423
5424   // non-numeric argument too early
5425   if (aCoord.IsEmpty())
5426   {
5427     std::cerr << "Error: wrong number of arguments! See usage:\n";
5428     theDI.PrintHelp (theArgVec[0]);
5429     return 1;
5430   }
5431
5432   // collect all other arguments and options
5433   for (; anArgIdx < theArgNb; ++anArgIdx)
5434   {
5435     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5436     anArg.LowerCase();
5437     if      (anArg == "window") aMode = Window;
5438     else if (anArg == "view")   aMode = View;
5439     else if (anArg == "grid")   aMode = Grid;
5440     else if (anArg == "ray")    aMode = Ray;
5441     else
5442     {
5443       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5444       theDI.PrintHelp (theArgVec[0]);
5445       return 1;
5446     }
5447   }
5448
5449   // complete input checks
5450   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5451       (aCoord.Length() == 2 && theArgNb > 4) ||
5452       (aCoord.Length() == 3 && theArgNb > 5))
5453   {
5454     std::cerr << "Error: wrong number of arguments! See usage:\n";
5455     theDI.PrintHelp (theArgVec[0]);
5456     return 1;
5457   }
5458
5459   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5460   Standard_Integer aXYp[2] = {0, 0};
5461
5462   // convert one-dimensional coordinate
5463   if (aCoord.Length() == 1)
5464   {
5465     switch (aMode)
5466     {
5467       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5468       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5469       default:
5470         std::cerr << "Error: wrong arguments! See usage:\n";
5471         theDI.PrintHelp (theArgVec[0]);
5472         return 1;
5473     }
5474   }
5475
5476   // convert 2D coordinates from projection or view reference space
5477   if (aCoord.Length() == 2)
5478   {
5479     switch (aMode)
5480     {
5481       case Model :
5482         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5483         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5484         return 0;
5485
5486       case View :
5487         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5488         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5489         return 0;
5490
5491       case Window :
5492         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5493         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5494         return 0;
5495
5496       case Grid :
5497         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5498         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5499         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5500         return 0;
5501
5502       case Ray :
5503         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5504                                 (Standard_Integer) aCoord (2),
5505                                 aXYZ[0], aXYZ[1], aXYZ[2],
5506                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5507         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5508         return 0;
5509
5510       default:
5511         std::cerr << "Error: wrong arguments! See usage:\n";
5512         theDI.PrintHelp (theArgVec[0]);
5513         return 1;
5514     }
5515   }
5516
5517   // convert 3D coordinates from view reference space
5518   else if (aCoord.Length() == 3)
5519   {
5520     switch (aMode)
5521     {
5522       case Window :
5523         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5524         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5525         return 0;
5526
5527       case Grid :
5528         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5529         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5530         return 0;
5531
5532       default:
5533         std::cerr << "Error: wrong arguments! See usage:\n";
5534         theDI.PrintHelp (theArgVec[0]);
5535         return 1;
5536     }
5537   }
5538
5539   return 0;
5540 }
5541
5542 //==============================================================================
5543 //function : VFps
5544 //purpose  :
5545 //==============================================================================
5546
5547 static int VFps (Draw_Interpretor& theDI,
5548                  Standard_Integer  theArgNb,
5549                  const char**      theArgVec)
5550 {
5551   // get the active view
5552   Handle(V3d_View) aView = ViewerTest::CurrentView();
5553   if (aView.IsNull())
5554   {
5555     std::cerr << "No active view. Please call vinit.\n";
5556     return 1;
5557   }
5558
5559   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5560   if (aFramesNb <= 0)
5561   {
5562     std::cerr << "Incorrect arguments!\n";
5563     return 1;
5564   }
5565
5566   // the time is meaningless for first call
5567   // due to async OpenGl rendering
5568   aView->Redraw();
5569
5570   // redraw view in loop to estimate average values
5571   OSD_Timer aTimer;
5572   aTimer.Start();
5573   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5574   {
5575     aView->Redraw();
5576   }
5577   aTimer.Stop();
5578   Standard_Real aCpu;
5579   const Standard_Real aTime = aTimer.ElapsedTime();
5580   aTimer.OSD_Chronometer::Show (aCpu);
5581
5582   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5583   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5584
5585   // return statistics
5586   theDI << "FPS: " << aFpsAver << "\n"
5587         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5588
5589   // compute additional statistics in ray-tracing mode
5590   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5591
5592   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5593   {
5594     Standard_Integer aSizeX;
5595     Standard_Integer aSizeY;
5596
5597     aView->Window()->Size (aSizeX, aSizeY);
5598
5599     // 1 shadow ray and 1 secondary ray pew each bounce
5600     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5601
5602     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5603   }
5604
5605   return 0;
5606 }
5607
5608 //! Auxiliary function for parsing glsl dump level argument.
5609 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
5610                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
5611 {
5612   TCollection_AsciiString aTypeStr (theArg);
5613   aTypeStr.LowerCase();
5614   if (aTypeStr == "off"
5615    || aTypeStr == "0")
5616   {
5617     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
5618   }
5619   else if (aTypeStr == "short")
5620   {
5621     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
5622   }
5623   else if (aTypeStr == "full"
5624         || aTypeStr == "1")
5625   {
5626     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
5627   }
5628   else
5629   {
5630     return Standard_False;
5631   }
5632   return Standard_True;
5633 }
5634
5635 //==============================================================================
5636 //function : VGlDebug
5637 //purpose  :
5638 //==============================================================================
5639
5640 static int VGlDebug (Draw_Interpretor& theDI,
5641                      Standard_Integer  theArgNb,
5642                      const char**      theArgVec)
5643 {
5644   Handle(OpenGl_GraphicDriver) aDriver;
5645   Handle(V3d_View) aView = ViewerTest::CurrentView();
5646   if (!aView.IsNull())
5647   {
5648     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5649   }
5650   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5651   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5652
5653   if (theArgNb < 2)
5654   {
5655     TCollection_AsciiString aDebActive, aSyncActive;
5656     if (aCaps == NULL)
5657     {
5658       aCaps = aDefCaps;
5659     }
5660     else
5661     {
5662       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5663                                                                   "GL_ARB_debug_output");
5664       aDebActive = isActive ? " (active)" : " (inactive)";
5665       if (isActive)
5666       {
5667         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5668         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5669       }
5670     }
5671
5672     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
5673       + "glslSourceCode: "
5674       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
5675          ? "Off"
5676          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
5677           ? "Short"
5678           : "Full")
5679       + "\n";
5680     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5681           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5682           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5683           << aGlslCodeDebugStatus
5684           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5685     return 0;
5686   }
5687
5688   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5689   {
5690     Standard_CString        anArg     = theArgVec[anArgIter];
5691     TCollection_AsciiString anArgCase (anArg);
5692     anArgCase.LowerCase();
5693     Standard_Boolean toEnableDebug = Standard_True;
5694     if (anArgCase == "-glsl"
5695      || anArgCase == "-glslwarn"
5696      || anArgCase == "-glslwarns"
5697      || anArgCase == "-glslwarnings")
5698     {
5699       Standard_Boolean toShowWarns = Standard_True;
5700       if (++anArgIter < theArgNb
5701       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5702       {
5703         --anArgIter;
5704       }
5705       aDefCaps->glslWarnings = toShowWarns;
5706       if (aCaps != NULL)
5707       {
5708         aCaps->glslWarnings = toShowWarns;
5709       }
5710     }
5711     else if (anArgCase == "-extra"
5712           || anArgCase == "-extramsg"
5713           || anArgCase == "-extramessages")
5714     {
5715       Standard_Boolean toShow = Standard_True;
5716       if (++anArgIter < theArgNb
5717       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5718       {
5719         --anArgIter;
5720       }
5721       aDefCaps->suppressExtraMsg = !toShow;
5722       if (aCaps != NULL)
5723       {
5724         aCaps->suppressExtraMsg = !toShow;
5725       }
5726     }
5727     else if (anArgCase == "-noextra"
5728           || anArgCase == "-noextramsg"
5729           || anArgCase == "-noextramessages")
5730     {
5731       Standard_Boolean toSuppress = Standard_True;
5732       if (++anArgIter < theArgNb
5733       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5734       {
5735         --anArgIter;
5736       }
5737       aDefCaps->suppressExtraMsg = toSuppress;
5738       if (aCaps != NULL)
5739       {
5740         aCaps->suppressExtraMsg = toSuppress;
5741       }
5742     }
5743     else if (anArgCase == "-sync")
5744     {
5745       Standard_Boolean toSync = Standard_True;
5746       if (++anArgIter < theArgNb
5747       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5748       {
5749         --anArgIter;
5750       }
5751       aDefCaps->contextSyncDebug = toSync;
5752       if (toSync)
5753       {
5754         aDefCaps->contextDebug = Standard_True;
5755       }
5756     }
5757     else if (anArgCase == "-glslsourcecode"
5758           || anArgCase == "-glslcode")
5759     {
5760       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
5761       if (++anArgIter < theArgNb
5762       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
5763       {
5764         --anArgIter;
5765       }
5766       aDefCaps->glslDumpLevel = aGslsDumpLevel;
5767       if (aCaps != NULL)
5768       {
5769         aCaps->glslDumpLevel = aGslsDumpLevel;
5770       }
5771     }
5772     else if (anArgCase == "-debug")
5773     {
5774       if (++anArgIter < theArgNb
5775       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5776       {
5777         --anArgIter;
5778       }
5779       aDefCaps->contextDebug = toEnableDebug;
5780     }
5781     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5782           && (anArgIter + 1 == theArgNb))
5783     {
5784       // simple alias to turn on almost everything
5785       aDefCaps->contextDebug     = toEnableDebug;
5786       aDefCaps->contextSyncDebug = toEnableDebug;
5787       aDefCaps->glslWarnings     = toEnableDebug;
5788       if (!toEnableDebug)
5789       {
5790         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
5791       }
5792       aDefCaps->suppressExtraMsg = !toEnableDebug;
5793       if (aCaps != NULL)
5794       {
5795         aCaps->contextDebug     = toEnableDebug;
5796         aCaps->contextSyncDebug = toEnableDebug;
5797         aCaps->glslWarnings     = toEnableDebug;
5798         if (!toEnableDebug)
5799         {
5800           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
5801         }
5802         aCaps->suppressExtraMsg = !toEnableDebug;
5803       }
5804     }
5805     else
5806     {
5807       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5808       return 1;
5809     }
5810   }
5811
5812   return 0;
5813 }
5814
5815 //==============================================================================
5816 //function : VVbo
5817 //purpose  :
5818 //==============================================================================
5819
5820 static int VVbo (Draw_Interpretor& theDI,
5821                  Standard_Integer  theArgNb,
5822                  const char**      theArgVec)
5823 {
5824   const Standard_Boolean toSet    = (theArgNb > 1);
5825   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5826   if (toSet)
5827   {
5828     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5829   }
5830
5831   // get the context
5832   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5833   if (aContextAIS.IsNull())
5834   {
5835     if (!toSet)
5836     {
5837       std::cerr << "No active view!\n";
5838     }
5839     return 1;
5840   }
5841   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5842   if (!aDriver.IsNull())
5843   {
5844     if (!toSet)
5845     {
5846       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5847     }
5848     else
5849     {
5850       aDriver->ChangeOptions().vboDisable = toUseVbo;
5851     }
5852   }
5853
5854   return 0;
5855 }
5856
5857 //==============================================================================
5858 //function : VCaps
5859 //purpose  :
5860 //==============================================================================
5861
5862 static int VCaps (Draw_Interpretor& theDI,
5863                   Standard_Integer  theArgNb,
5864                   const char**      theArgVec)
5865 {
5866   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5867   Handle(OpenGl_GraphicDriver)   aDriver;
5868   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5869   if (!aContext.IsNull())
5870   {
5871     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5872     aCaps   = &aDriver->ChangeOptions();
5873   }
5874
5875   if (theArgNb < 2)
5876   {
5877     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5878     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5879     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5880     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5881     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5882     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5883     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5884     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5885     return 0;
5886   }
5887
5888   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5889   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5890   {
5891     Standard_CString        anArg     = theArgVec[anArgIter];
5892     TCollection_AsciiString anArgCase (anArg);
5893     anArgCase.LowerCase();
5894     if (anUpdateTool.parseRedrawMode (anArg))
5895     {
5896       continue;
5897     }
5898     else if (anArgCase == "-vsync"
5899           || anArgCase == "-swapinterval")
5900     {
5901       Standard_Boolean toEnable = Standard_True;
5902       if (++anArgIter < theArgNb
5903       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5904       {
5905         --anArgIter;
5906       }
5907       aCaps->swapInterval = toEnable;
5908     }
5909     else if (anArgCase == "-ffp")
5910     {
5911       Standard_Boolean toEnable = Standard_True;
5912       if (++anArgIter < theArgNb
5913       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5914       {
5915         --anArgIter;
5916       }
5917       aCaps->ffpEnable = toEnable;
5918     }
5919     else if (anArgCase == "-vbo")
5920     {
5921       Standard_Boolean toEnable = Standard_True;
5922       if (++anArgIter < theArgNb
5923       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5924       {
5925         --anArgIter;
5926       }
5927       aCaps->vboDisable = !toEnable;
5928     }
5929     else if (anArgCase == "-sprite"
5930           || anArgCase == "-sprites")
5931     {
5932       Standard_Boolean toEnable = Standard_True;
5933       if (++anArgIter < theArgNb
5934       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5935       {
5936         --anArgIter;
5937       }
5938       aCaps->pntSpritesDisable = !toEnable;
5939     }
5940     else if (anArgCase == "-softmode")
5941     {
5942       Standard_Boolean toEnable = Standard_True;
5943       if (++anArgIter < theArgNb
5944       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5945       {
5946         --anArgIter;
5947       }
5948       aCaps->contextNoAccel = toEnable;
5949     }
5950     else if (anArgCase == "-winbuffer"
5951           || anArgCase == "-windowbuffer"
5952           || anArgCase == "-usewinbuffer"
5953           || anArgCase == "-usewindowbuffer"
5954           || anArgCase == "-usesystembuffer")
5955     {
5956       Standard_Boolean toEnable = Standard_True;
5957       if (++anArgIter < theArgNb
5958       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5959       {
5960         --anArgIter;
5961       }
5962       aCaps->useSystemBuffer = toEnable;
5963     }
5964     else if (anArgCase == "-accel"
5965           || anArgCase == "-acceleration")
5966     {
5967       Standard_Boolean toEnable = Standard_True;
5968       if (++anArgIter < theArgNb
5969       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5970       {
5971         --anArgIter;
5972       }
5973       aCaps->contextNoAccel = !toEnable;
5974     }
5975     else if (anArgCase == "-compat"
5976           || anArgCase == "-compatprofile"
5977           || anArgCase == "-compatible"
5978           || anArgCase == "-compatibleprofile")
5979     {
5980       Standard_Boolean toEnable = Standard_True;
5981       if (++anArgIter < theArgNb
5982       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5983       {
5984         --anArgIter;
5985       }
5986       aCaps->contextCompatible = toEnable;
5987       if (!aCaps->contextCompatible)
5988       {
5989         aCaps->ffpEnable = Standard_False;
5990       }
5991     }
5992     else if (anArgCase == "-core"
5993           || anArgCase == "-coreprofile")
5994     {
5995       Standard_Boolean toEnable = Standard_True;
5996       if (++anArgIter < theArgNb
5997       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5998       {
5999         --anArgIter;
6000       }
6001       aCaps->contextCompatible = !toEnable;
6002       if (!aCaps->contextCompatible)
6003       {
6004         aCaps->ffpEnable = Standard_False;
6005       }
6006     }
6007     else if (anArgCase == "-stereo"
6008           || anArgCase == "-quadbuffer")
6009     {
6010       Standard_Boolean toEnable = Standard_True;
6011       if (++anArgIter < theArgNb
6012       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6013       {
6014         --anArgIter;
6015       }
6016       aCaps->contextStereo = toEnable;
6017     }
6018     else
6019     {
6020       std::cout << "Error: unknown argument '" << anArg << "'\n";
6021       return 1;
6022     }
6023   }
6024   if (aCaps != &ViewerTest_myDefaultCaps)
6025   {
6026     ViewerTest_myDefaultCaps = *aCaps;
6027   }
6028   return 0;
6029 }
6030
6031 //==============================================================================
6032 //function : VMemGpu
6033 //purpose  :
6034 //==============================================================================
6035
6036 static int VMemGpu (Draw_Interpretor& theDI,
6037                     Standard_Integer  theArgNb,
6038                     const char**      theArgVec)
6039 {
6040   // get the context
6041   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6042   if (aContextAIS.IsNull())
6043   {
6044     std::cerr << "No active view. Please call vinit.\n";
6045     return 1;
6046   }
6047
6048   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
6049   if (aDriver.IsNull())
6050   {
6051     std::cerr << "Graphic driver not available.\n";
6052     return 1;
6053   }
6054
6055   Standard_Size aFreeBytes = 0;
6056   TCollection_AsciiString anInfo;
6057   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
6058   {
6059     std::cerr << "Information not available.\n";
6060     return 1;
6061   }
6062
6063   if (theArgNb > 1 && *theArgVec[1] == 'f')
6064   {
6065     theDI << Standard_Real (aFreeBytes);
6066   }
6067   else
6068   {
6069     theDI << anInfo;
6070   }
6071
6072   return 0;
6073 }
6074
6075 // ==============================================================================
6076 // function : VReadPixel
6077 // purpose  :
6078 // ==============================================================================
6079 static int VReadPixel (Draw_Interpretor& theDI,
6080                        Standard_Integer  theArgNb,
6081                        const char**      theArgVec)
6082 {
6083   // get the active view
6084   Handle(V3d_View) aView = ViewerTest::CurrentView();
6085   if (aView.IsNull())
6086   {
6087     std::cerr << "No active view. Please call vinit.\n";
6088     return 1;
6089   }
6090   else if (theArgNb < 3)
6091   {
6092     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
6093     return 1;
6094   }
6095
6096   Image_Format         aFormat     = Image_Format_RGBA;
6097   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
6098
6099   Standard_Integer aWidth, aHeight;
6100   aView->Window()->Size (aWidth, aHeight);
6101   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
6102   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
6103   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
6104   {
6105     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
6106     return 1;
6107   }
6108
6109   Standard_Boolean toShowName = Standard_False;
6110   Standard_Boolean toShowHls  = Standard_False;
6111   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6112   {
6113     TCollection_AsciiString aParam (theArgVec[anIter]);
6114     aParam.LowerCase();
6115     if (aParam == "rgb")
6116     {
6117       aFormat     = Image_Format_RGB;
6118       aBufferType = Graphic3d_BT_RGB;
6119     }
6120     else if (aParam == "hls")
6121     {
6122       aFormat     = Image_Format_RGB;
6123       aBufferType = Graphic3d_BT_RGB;
6124       toShowHls   = Standard_True;
6125     }
6126     else if (aParam == "rgbf")
6127     {
6128       aFormat     = Image_Format_RGBF;
6129       aBufferType = Graphic3d_BT_RGB;
6130     }
6131     else if (aParam == "rgba")
6132     {
6133       aFormat     = Image_Format_RGBA;
6134       aBufferType = Graphic3d_BT_RGBA;
6135     }
6136     else if (aParam == "rgbaf")
6137     {
6138       aFormat     = Image_Format_RGBAF;
6139       aBufferType = Graphic3d_BT_RGBA;
6140     }
6141     else if (aParam == "depth")
6142     {
6143       aFormat     = Image_Format_GrayF;
6144       aBufferType = Graphic3d_BT_Depth;
6145     }
6146     else if (aParam == "name")
6147     {
6148       toShowName = Standard_True;
6149     }
6150   }
6151
6152   Image_PixMap anImage;
6153   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6154   {
6155     std::cerr << "Image allocation failed\n";
6156     return 1;
6157   }
6158   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6159   {
6160     std::cerr << "Image dump failed\n";
6161     return 1;
6162   }
6163
6164   // redirect possible warning messages that could have been added by ToPixMap
6165   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6166   // contaminate result of the command
6167   Standard_CString aWarnLog = theDI.Result();
6168   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6169   {
6170     std::cout << aWarnLog << std::endl;
6171   }
6172   theDI.Reset();
6173
6174   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6175   if (toShowName)
6176   {
6177     if (aBufferType == Graphic3d_BT_RGBA)
6178     {
6179       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6180     }
6181     else
6182     {
6183       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6184     }
6185   }
6186   else
6187   {
6188     switch (aBufferType)
6189     {
6190       default:
6191       case Graphic3d_BT_RGB:
6192       {
6193         if (toShowHls)
6194         {
6195           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6196         }
6197         else
6198         {
6199           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6200         }
6201         break;
6202       }
6203       case Graphic3d_BT_RGBA:
6204       {
6205         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6206         break;
6207       }
6208       case Graphic3d_BT_Depth:
6209       {
6210         theDI << aColor.GetRGB().Red();
6211         break;
6212       }
6213     }
6214   }
6215
6216   return 0;
6217 }
6218
6219 //! Auxiliary presentation for an image plane.
6220 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6221 {
6222 public:
6223   //! Main constructor.
6224   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6225                        const Standard_Real theWidth,
6226                        const Standard_Real theHeight,
6227                        const TCollection_AsciiString& theLabel)
6228   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6229   {
6230     SetDisplayMode (0);
6231     SetHilightMode (1);
6232     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6233     {
6234       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6235       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6236       Graphic3d_MaterialAspect aMat;
6237       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6238       aMat.SetAmbient  (1.0);
6239       aMat.SetDiffuse  (1.0);
6240       aMat.SetSpecular (1.0);
6241       aMat.SetEmissive (1.0);
6242       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6243       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6244       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6245       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6246       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6247       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6248       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6249       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6250       aFillAspect->SetFrontMaterial (aMat);
6251       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6252       aFillAspect->SetTextureMapOn();
6253     }
6254     {
6255       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6256       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6257       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6258       myDrawer->SetTextAspect (aTextAspect);
6259     }
6260     {
6261       const gp_Dir aNorm (0.0, 0.0, 1.0);
6262       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6263       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6264       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6265       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6266       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6267       myTris->AddEdge (1);
6268       myTris->AddEdge (2);
6269       myTris->AddEdge (3);
6270       myTris->AddEdge (3);
6271       myTris->AddEdge (2);
6272       myTris->AddEdge (4);
6273
6274       myRect = new Graphic3d_ArrayOfPolylines (4);
6275       myRect->AddVertex (myTris->Vertice (1));
6276       myRect->AddVertex (myTris->Vertice (3));
6277       myRect->AddVertex (myTris->Vertice (4));
6278       myRect->AddVertex (myTris->Vertice (2));
6279     }
6280   }
6281
6282   //! Returns TRUE for accepted display modes.
6283   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6284
6285   //! Compute presentation.
6286   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6287   {
6288     switch (theMode)
6289     {
6290       case 0:
6291       {
6292         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6293         aGroup->AddPrimitiveArray (myTris);
6294         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6295         aGroup->AddPrimitiveArray (myRect);
6296         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6297         return;
6298       }
6299       case 1:
6300       {
6301         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6302         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6303         aGroup->AddPrimitiveArray (myRect);
6304         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6305         return;
6306       }
6307     }
6308   }
6309
6310   //! Compute selection.
6311   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6312   {
6313     if (theMode == 0)
6314     {
6315       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6316       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6317       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6318       theSel->Add (aSensitive);
6319     }
6320   }
6321
6322 private:
6323   Handle(Graphic3d_ArrayOfTriangles) myTris;
6324   Handle(Graphic3d_ArrayOfPolylines) myRect;
6325   TCollection_AsciiString myLabel;
6326   Standard_Real myWidth;
6327   Standard_Real myHeight;
6328 };
6329
6330 //==============================================================================
6331 //function : VDiffImage
6332 //purpose  : The draw-command compares two images.
6333 //==============================================================================
6334
6335 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6336 {
6337   if (theArgNb < 3)
6338   {
6339     std::cout << "Syntax error: not enough arguments.\n";
6340     return 1;
6341   }
6342
6343   Standard_Integer anArgIter = 1;
6344   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6345   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6346   TCollection_AsciiString aDiffImagePath;
6347   Standard_Real    aTolColor        = -1.0;
6348   Standard_Integer toBlackWhite     = -1;
6349   Standard_Integer isBorderFilterOn = -1;
6350   Standard_Boolean isOldSyntax = Standard_False;
6351   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6352   for (; anArgIter < theArgNb; ++anArgIter)
6353   {
6354     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6355     anArg.LowerCase();
6356     if (anArgIter + 1 < theArgNb
6357      && (anArg == "-toleranceofcolor"
6358       || anArg == "-tolerancecolor"
6359       || anArg == "-tolerance"
6360       || anArg == "-toler"))
6361     {
6362       aTolColor = Atof (theArgVec[++anArgIter]);
6363       if (aTolColor < 0.0 || aTolColor > 1.0)
6364       {
6365         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6366         return 1;
6367       }
6368     }
6369     else if (anArg == "-blackwhite")
6370     {
6371       Standard_Boolean toEnable = Standard_True;
6372       if (anArgIter + 1 < theArgNb
6373        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6374       {
6375         ++anArgIter;
6376       }
6377       toBlackWhite = toEnable ? 1 : 0;
6378     }
6379     else if (anArg == "-borderfilter")
6380     {
6381       Standard_Boolean toEnable = Standard_True;
6382       if (anArgIter + 1 < theArgNb
6383        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6384       {
6385         ++anArgIter;
6386       }
6387       isBorderFilterOn = toEnable ? 1 : 0;
6388     }
6389     else if (anArg == "-exitonclose")
6390     {
6391       Draw_ToExitOnCloseView = true;
6392       if (anArgIter + 1 < theArgNb
6393        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6394       {
6395         ++anArgIter;
6396       }
6397     }
6398     else if (anArg == "-closeonescape"
6399           || anArg == "-closeonesc")
6400     {
6401       Draw_ToCloseViewOnEsc = true;
6402       if (anArgIter + 1 < theArgNb
6403        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6404       {
6405         ++anArgIter;
6406       }
6407     }
6408     else if (anArgIter + 3 < theArgNb
6409           && anArg == "-display")
6410     {
6411       aViewName   = theArgVec[++anArgIter];
6412       aPrsNameRef = theArgVec[++anArgIter];
6413       aPrsNameNew = theArgVec[++anArgIter];
6414       if (anArgIter + 1 < theArgNb
6415       && *theArgVec[anArgIter + 1] != '-')
6416       {
6417         aPrsNameDiff = theArgVec[++anArgIter];
6418       }
6419     }
6420     else if (aTolColor < 0.0
6421           && anArg.IsRealValue())
6422     {
6423       isOldSyntax = Standard_True;
6424       aTolColor = anArg.RealValue();
6425       if (aTolColor < 0.0 || aTolColor > 1.0)
6426       {
6427         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6428         return 1;
6429       }
6430     }
6431     else if (isOldSyntax
6432           && toBlackWhite == -1
6433           && (anArg == "0" || anArg == "1"))
6434     {
6435       toBlackWhite = anArg == "1" ? 1 : 0;
6436     }
6437     else if (isOldSyntax
6438           && isBorderFilterOn == -1
6439           && (anArg == "0" || anArg == "1"))
6440     {
6441       isBorderFilterOn = anArg == "1" ? 1 : 0;
6442     }
6443     else if (aDiffImagePath.IsEmpty())
6444     {
6445       aDiffImagePath = theArgVec[anArgIter];
6446     }
6447     else
6448     {
6449       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6450       return 1;
6451     }
6452   }
6453
6454   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6455   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6456   if (!anImgRef->Load (anImgPathRef))
6457   {
6458     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6459     return 1;
6460   }
6461   if (!anImgNew->Load (anImgPathNew))
6462   {
6463     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6464     return 1;
6465   }
6466
6467   // compare the images
6468   Image_Diff aComparer;
6469   Standard_Integer aDiffColorsNb = -1;
6470   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6471   {
6472     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6473     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6474     aDiffColorsNb = aComparer.Compare();
6475     theDI << aDiffColorsNb << "\n";
6476   }
6477
6478   // save image of difference
6479   Handle(Image_AlienPixMap) aDiff;
6480   if (aDiffColorsNb > 0
6481   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6482   {
6483     aDiff = new Image_AlienPixMap();
6484     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6485     {
6486       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6487       return 1;
6488     }
6489     aComparer.SaveDiffImage (*aDiff);
6490     if (!aDiffImagePath.IsEmpty()
6491      && !aDiff->Save (aDiffImagePath))
6492     {
6493       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6494       return 1;
6495     }
6496   }
6497
6498   if (aViewName.IsEmpty())
6499   {
6500     return 0;
6501   }
6502
6503   ViewerTest_Names aViewNames (aViewName);
6504   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6505   {
6506     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6507     theDI.Eval (aCommand.ToCString());
6508   }
6509
6510   Standard_Integer aPxLeft = 0;
6511   Standard_Integer aPxTop  = 0;
6512   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6513   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6514                               ? int(anImgRef->SizeY() * 2)
6515                               : int(anImgRef->SizeY());
6516   TCollection_AsciiString aDisplayName;
6517   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
6518                                                             aViewName, aDisplayName);
6519
6520   Standard_Real aRatio = anImgRef->Ratio();
6521   Standard_Real aSizeX = 1.0;
6522   Standard_Real aSizeY = aSizeX / aRatio;
6523   {
6524     OSD_Path aPath (anImgPathRef);
6525     TCollection_AsciiString aLabelRef;
6526     if (!aPath.Name().IsEmpty())
6527     {
6528       aLabelRef = aPath.Name() + aPath.Extension();
6529     }
6530     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6531
6532     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6533     gp_Trsf aTrsfRef;
6534     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6535     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6536     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6537   }
6538   {
6539     OSD_Path aPath (anImgPathNew);
6540     TCollection_AsciiString aLabelNew;
6541     if (!aPath.Name().IsEmpty())
6542     {
6543       aLabelNew = aPath.Name() + aPath.Extension();
6544     }
6545     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6546
6547     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6548     gp_Trsf aTrsfRef;
6549     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6550     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6551     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6552   }
6553   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6554   if (!aDiff.IsNull())
6555   {
6556     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6557     gp_Trsf aTrsfDiff;
6558     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6559     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6560   }
6561   if (!aPrsNameDiff.IsEmpty())
6562   {
6563     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6564   }
6565   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6566   ViewerTest::CurrentView()->FitAll();
6567   return 0;
6568 }
6569
6570 //=======================================================================
6571 //function : VSelect
6572 //purpose  : Emulates different types of selection by mouse:
6573 //           1) single click selection
6574 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6575 //           3) selection with polygon having corners at
6576 //           pixel positions (x1,y1),...,(xn,yn)
6577 //           4) any of these selections with shift button pressed
6578 //=======================================================================
6579 static Standard_Integer VSelect (Draw_Interpretor& di,
6580                                  Standard_Integer argc,
6581                                  const char ** argv)
6582 {
6583   if(argc < 3)
6584   {
6585     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6586     return 1;
6587   }
6588
6589   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6590   if(myAIScontext.IsNull())
6591   {
6592     di << "use 'vinit' command before " << argv[0] << "\n";
6593     return 1;
6594   }
6595
6596   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6597   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6598   TCollection_AsciiString anArg;
6599   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6600   anArg.LowerCase();
6601   if (anArg == "-allowoverlap")
6602   {
6603     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6604       : argc == 7;
6605     if (!isValidated)
6606     {
6607       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6608       return 1;
6609     }
6610
6611     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6612     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6613     aCoordsNb -= 2;
6614   }
6615
6616   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6617   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6618   if(aCoordsNb == 2)
6619   {
6620     if(isShiftSelection)
6621       aCurrentEventManager->ShiftSelect();
6622     else
6623       aCurrentEventManager->Select();
6624   }
6625   else if(aCoordsNb == 4)
6626   {
6627     if(isShiftSelection)
6628       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6629     else
6630       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6631   }
6632   else
6633   {
6634     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6635
6636     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6637       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6638
6639     if(isShiftSelection)
6640       aCurrentEventManager->ShiftSelect(aPolyline);
6641     else
6642       aCurrentEventManager->Select(aPolyline);
6643   }
6644   return 0;
6645 }
6646
6647 //=======================================================================
6648 //function : VMoveTo
6649 //purpose  : Emulates cursor movement to defined pixel position
6650 //=======================================================================
6651 static Standard_Integer VMoveTo (Draw_Interpretor& ,
6652                                 Standard_Integer theNbArgs,
6653                                 const char**     theArgVec)
6654 {
6655   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
6656   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
6657   if (aContext.IsNull())
6658   {
6659     std::cout << "Error: no active View\n";
6660     return 1;
6661   }
6662
6663   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
6664   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
6665   {
6666     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
6667     anArgStr.LowerCase();
6668     if (anArgStr == "-reset"
6669      || anArgStr == "-clear")
6670     {
6671       if (anArgIter + 1 < theNbArgs)
6672       {
6673         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
6674         return 1;
6675       }
6676
6677       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
6678                                        && aContext->CurrentViewer()->GridEcho();
6679       if (toEchoGrid)
6680       {
6681         aContext->CurrentViewer()->HideGridEcho (aView);
6682       }
6683       if (aContext->ClearDetected() || toEchoGrid)
6684       {
6685         aContext->CurrentViewer()->RedrawImmediate();
6686       }
6687       return 0;
6688     }
6689     else if (aMousePos.x() == IntegerLast()
6690           && anArgStr.IsIntegerValue())
6691     {
6692       aMousePos.x() = anArgStr.IntegerValue();
6693     }
6694     else if (aMousePos.y() == IntegerLast()
6695           && anArgStr.IsIntegerValue())
6696     {
6697       aMousePos.y() = anArgStr.IntegerValue();
6698     }
6699     else
6700     {
6701       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6702       return 1;
6703     }
6704   }
6705
6706   if (aMousePos.x() == IntegerLast()
6707    || aMousePos.y() == IntegerLast())
6708   {
6709     std::cout << "Syntax error: wrong number of arguments\n";
6710     return 1;
6711   }
6712
6713   ViewerTest::CurrentEventManager()->MoveTo (aMousePos.x(), aMousePos.y());
6714   return 0;
6715 }
6716
6717 namespace
6718 {
6719   //! Global map storing all animations registered in ViewerTest.
6720   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6721
6722   //! The animation calling the Draw Harness command.
6723   class ViewerTest_AnimationProc : public AIS_Animation
6724   {
6725   public:
6726
6727     //! Main constructor.
6728     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6729                               Draw_Interpretor* theDI,
6730                               const TCollection_AsciiString& theCommand)
6731     : AIS_Animation (theAnimationName),
6732       myDrawInter(theDI),
6733       myCommand  (theCommand)
6734     {
6735       //
6736     }
6737
6738   protected:
6739
6740     //! Evaluate the command.
6741     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6742     {
6743       TCollection_AsciiString aCmd = myCommand;
6744       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6745       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6746       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6747       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6748       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6749       myDrawInter->Eval (aCmd.ToCString());
6750     }
6751
6752     //! Find the keyword in the command and replace it with value.
6753     //! @return the position of the keyword to pass value
6754     void replace (TCollection_AsciiString&       theCmd,
6755                   const TCollection_AsciiString& theKey,
6756                   const TCollection_AsciiString& theVal)
6757     {
6758       TCollection_AsciiString aCmd (theCmd);
6759       aCmd.LowerCase();
6760       const Standard_Integer aPos = aCmd.Search (theKey);
6761       if (aPos == -1)
6762       {
6763         return;
6764       }
6765
6766       TCollection_AsciiString aPart1, aPart2;
6767       Standard_Integer aPart1To = aPos - 1;
6768       if (aPart1To >= 1
6769        && aPart1To <= theCmd.Length())
6770       {
6771         aPart1 = theCmd.SubString (1, aPart1To);
6772       }
6773
6774       Standard_Integer aPart2From = aPos + theKey.Length();
6775       if (aPart2From >= 1
6776        && aPart2From <= theCmd.Length())
6777       {
6778         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6779       }
6780
6781       theCmd = aPart1 + theVal + aPart2;
6782     }
6783
6784   protected:
6785
6786     Draw_Interpretor*       myDrawInter;
6787     TCollection_AsciiString myCommand;
6788
6789   };
6790
6791   //! Replace the animation with the new one.
6792   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6793                                 Handle(AIS_Animation)&       theAnimation,
6794                                 const Handle(AIS_Animation)& theAnimationNew)
6795   {
6796     theAnimationNew->CopyFrom (theAnimation);
6797     if (!theParentAnimation.IsNull())
6798     {
6799       theParentAnimation->Replace (theAnimation, theAnimationNew);
6800     }
6801     else
6802     {
6803       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6804       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6805     }
6806     theAnimation = theAnimationNew;
6807   }
6808
6809   //! Parse the point.
6810   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6811   {
6812     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6813     if (!anXYZ[0].IsRealValue()
6814      || !anXYZ[1].IsRealValue()
6815      || !anXYZ[2].IsRealValue())
6816     {
6817       return Standard_False;
6818     }
6819
6820     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6821     return Standard_True;
6822   }
6823
6824   //! Parse the quaternion.
6825   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6826   {
6827     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6828     if (!anXYZW[0].IsRealValue()
6829      || !anXYZW[1].IsRealValue()
6830      || !anXYZW[2].IsRealValue()
6831      || !anXYZW[3].IsRealValue())
6832     {
6833       return Standard_False;
6834     }
6835
6836     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6837     return Standard_True;
6838   }
6839
6840   //! Auxiliary class for flipping image upside-down.
6841   class ImageFlipper
6842   {
6843   public:
6844
6845     //! Empty constructor.
6846     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6847
6848     //! Perform flipping.
6849     Standard_Boolean FlipY (Image_PixMap& theImage)
6850     {
6851       if (theImage.IsEmpty()
6852        || theImage.SizeX() == 0
6853        || theImage.SizeY() == 0)
6854       {
6855         return Standard_False;
6856       }
6857
6858       const Standard_Size aRowSize = theImage.SizeRowBytes();
6859       if (myTmp.Size() < aRowSize
6860       && !myTmp.Allocate (aRowSize))
6861       {
6862         return Standard_False;
6863       }
6864
6865       // for odd height middle row should be left as is
6866       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6867       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6868       {
6869         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6870         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6871         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
6872         memcpy (aTop,               aBot,         aRowSize);
6873         memcpy (aBot,               myTmp.Data(), aRowSize);
6874       }
6875       return Standard_True;
6876     }
6877
6878   private:
6879     NCollection_Buffer myTmp;
6880   };
6881
6882 }
6883
6884 //=================================================================================================
6885 //function : VViewParams
6886 //purpose  : Gets or sets AIS View characteristics
6887 //=================================================================================================
6888 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6889 {
6890   Handle(V3d_View) aView = ViewerTest::CurrentView();
6891   if (aView.IsNull())
6892   {
6893     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6894     return 1;
6895   }
6896
6897   Standard_Boolean toSetProj     = Standard_False;
6898   Standard_Boolean toSetUp       = Standard_False;
6899   Standard_Boolean toSetAt       = Standard_False;
6900   Standard_Boolean toSetEye      = Standard_False;
6901   Standard_Boolean toSetScale    = Standard_False;
6902   Standard_Boolean toSetSize     = Standard_False;
6903   Standard_Boolean toSetCenter2d = Standard_False;
6904   Standard_Real    aViewScale = aView->Scale();
6905   Standard_Real    aViewSize  = 1.0;
6906   Graphic3d_Vec2i  aCenter2d;
6907   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6908   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6909   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6910   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6911   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6912   if (theArgsNb == 1)
6913   {
6914     // print all of the available view parameters
6915     char aText[4096];
6916     Sprintf (aText,
6917              "Scale: %g\n"
6918              "Proj:  %12g %12g %12g\n"
6919              "Up:    %12g %12g %12g\n"
6920              "At:    %12g %12g %12g\n"
6921              "Eye:   %12g %12g %12g\n",
6922               aViewScale,
6923               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6924               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6925               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6926               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6927     theDi << aText;
6928     return 0;
6929   }
6930
6931   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6932   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6933   {
6934     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6935     anArg.LowerCase();
6936     if (anUpdateTool.parseRedrawMode (anArg))
6937     {
6938       continue;
6939     }
6940     else if (anArg == "-cmd"
6941           || anArg == "-command"
6942           || anArg == "-args")
6943     {
6944       char aText[4096];
6945       Sprintf (aText,
6946                "-scale %g "
6947                "-proj %g %g %g "
6948                "-up %g %g %g "
6949                "-at %g %g %g\n",
6950                 aViewScale,
6951                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6952                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6953                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6954       theDi << aText;
6955     }
6956     else if (anArg == "-scale"
6957           || anArg == "-size")
6958     {
6959       if (anArgIter + 1 < theArgsNb
6960        && *theArgVec[anArgIter + 1] != '-')
6961       {
6962         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6963         if (aValueArg.IsRealValue())
6964         {
6965           ++anArgIter;
6966           if (anArg == "-scale")
6967           {
6968             toSetScale = Standard_True;
6969             aViewScale = aValueArg.RealValue();
6970           }
6971           else if (anArg == "-size")
6972           {
6973             toSetSize = Standard_True;
6974             aViewSize = aValueArg.RealValue();
6975           }
6976           continue;
6977         }
6978       }
6979       if (anArg == "-scale")
6980       {
6981         theDi << "Scale: " << aView->Scale() << "\n";
6982       }
6983       else if (anArg == "-size")
6984       {
6985         Graphic3d_Vec2d aSizeXY;
6986         aView->Size (aSizeXY.x(), aSizeXY.y());
6987         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6988       }
6989     }
6990     else if (anArg == "-eye"
6991           || anArg == "-at"
6992           || anArg == "-up"
6993           || anArg == "-proj")
6994     {
6995       if (anArgIter + 3 < theArgsNb)
6996       {
6997         gp_XYZ anXYZ;
6998         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6999         {
7000           anArgIter += 3;
7001           if (anArg == "-eye")
7002           {
7003             toSetEye = Standard_True;
7004             aViewEye = anXYZ;
7005           }
7006           else if (anArg == "-at")
7007           {
7008             toSetAt = Standard_True;
7009             aViewAt = anXYZ;
7010           }
7011           else if (anArg == "-up")
7012           {
7013             toSetUp = Standard_True;
7014             aViewUp = anXYZ;
7015           }
7016           else if (anArg == "-proj")
7017           {
7018             toSetProj = Standard_True;
7019             aViewProj = anXYZ;
7020           }
7021           continue;
7022         }
7023       }
7024
7025       if (anArg == "-eye")
7026       {
7027         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
7028       }
7029       else if (anArg == "-at")
7030       {
7031         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
7032       }
7033       else if (anArg == "-up")
7034       {
7035         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
7036       }
7037       else if (anArg == "-proj")
7038       {
7039         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
7040       }
7041     }
7042     else if (anArg == "-center")
7043     {
7044       if (anArgIter + 2 < theArgsNb)
7045       {
7046         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
7047         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
7048         if (anX.IsIntegerValue()
7049          && anY.IsIntegerValue())
7050         {
7051           toSetCenter2d = Standard_True;
7052           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
7053         }
7054       }
7055     }
7056     else
7057     {
7058       std::cout << "Syntax error at '" << anArg << "'\n";
7059       return 1;
7060     }
7061   }
7062
7063   // change view parameters in proper order
7064   if (toSetScale)
7065   {
7066     aView->SetScale (aViewScale);
7067   }
7068   if (toSetSize)
7069   {
7070     aView->SetSize (aViewSize);
7071   }
7072   if (toSetEye)
7073   {
7074     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7075   }
7076   if (toSetAt)
7077   {
7078     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7079   }
7080   if (toSetProj)
7081   {
7082     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7083   }
7084   if (toSetUp)
7085   {
7086     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7087   }
7088   if (toSetCenter2d)
7089   {
7090     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
7091   }
7092
7093   return 0;
7094 }
7095
7096 //==============================================================================
7097 //function : V2DMode
7098 //purpose  :
7099 //==============================================================================
7100 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7101 {
7102   bool is2dMode = true;
7103   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7104   if (aV3dView.IsNull())
7105   {
7106     std::cout << "Error: no active view.\n";
7107     return 1;
7108   }
7109   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7110   {
7111     const TCollection_AsciiString anArg = theArgVec[anArgIt];
7112     TCollection_AsciiString anArgCase = anArg;
7113     anArgCase.LowerCase();
7114     if (anArgIt + 1 < theArgsNb
7115      && anArgCase == "-name")
7116     {
7117       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
7118       TCollection_AsciiString aViewName = aViewNames.GetViewName();
7119       if (!ViewerTest_myViews.IsBound1 (aViewName))
7120       {
7121         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
7122         return 1;
7123       }
7124       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7125     }
7126     else if (anArgCase == "-mode")
7127     {
7128       if (anArgIt + 1 < theArgsNb
7129        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
7130       {
7131         ++anArgIt;
7132       }
7133     }
7134     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
7135     {
7136       //
7137     }
7138     else
7139     {
7140       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
7141       return 1;
7142     }
7143   }
7144
7145   aV3dView->SetView2DMode (is2dMode);
7146   return 0;
7147 }
7148
7149 //==============================================================================
7150 //function : VAnimation
7151 //purpose  :
7152 //==============================================================================
7153 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7154                                     Standard_Integer  theArgNb,
7155                                     const char**      theArgVec)
7156 {
7157   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7158   if (theArgNb < 2)
7159   {
7160     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7161          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7162     {
7163       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
7164     }
7165     return 0;
7166   }
7167   if (aCtx.IsNull())
7168   {
7169     std::cout << "Error: no active view\n";
7170     return 1;
7171   }
7172
7173   Standard_Integer anArgIter = 1;
7174   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7175   if (aNameArg.IsEmpty())
7176   {
7177     std::cout << "Syntax error: animation name is not defined.\n";
7178     return 1;
7179   }
7180
7181   TCollection_AsciiString aNameArgLower = aNameArg;
7182   aNameArgLower.LowerCase();
7183   if (aNameArgLower == "-reset"
7184    || aNameArgLower == "-clear")
7185   {
7186     ViewerTest_AnimationTimelineMap.Clear();
7187     return 0;
7188   }
7189   else if (aNameArg.Value (1) == '-')
7190   {
7191     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
7192     return 1;
7193   }
7194
7195   const char* aNameSplitter = "/";
7196   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7197   if (aSplitPos == -1)
7198   {
7199     aNameSplitter = ".";
7200     aSplitPos = aNameArg.Search (aNameSplitter);
7201   }
7202
7203   // find existing or create a new animation by specified name within syntax "parent.child".
7204   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
7205   for (; !aNameArg.IsEmpty();)
7206   {
7207     TCollection_AsciiString aNameParent;
7208     if (aSplitPos != -1)
7209     {
7210       if (aSplitPos == aNameArg.Length())
7211       {
7212         std::cout << "Syntax error: animation name is not defined.\n";
7213         return 1;
7214       }
7215
7216       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7217       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7218
7219       aSplitPos = aNameArg.Search (aNameSplitter);
7220     }
7221     else
7222     {
7223       aNameParent = aNameArg;
7224       aNameArg.Clear();
7225     }
7226
7227     if (anAnimation.IsNull())
7228     {
7229       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7230       {
7231         anAnimation = new AIS_Animation (aNameParent);
7232         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7233       }
7234       aRootAnimation = anAnimation;
7235     }
7236     else
7237     {
7238       aParentAnimation = anAnimation;
7239       anAnimation = aParentAnimation->Find (aNameParent);
7240       if (anAnimation.IsNull())
7241       {
7242         anAnimation = new AIS_Animation (aNameParent);
7243         aParentAnimation->Add (anAnimation);
7244       }
7245     }
7246   }
7247
7248   if (anArgIter >= theArgNb)
7249   {
7250     // just print the list of children
7251     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7252     {
7253       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7254     }
7255     return 0;
7256   }
7257
7258   // animation parameters
7259   Standard_Boolean toPlay = Standard_False;
7260   Standard_Real aPlaySpeed     = 1.0;
7261   Standard_Real aPlayStartTime = anAnimation->StartPts();
7262   Standard_Real aPlayDuration  = anAnimation->Duration();
7263   Standard_Boolean isFreeCamera = Standard_False;
7264   Standard_Boolean isLockLoop   = Standard_False;
7265
7266   // video recording parameters
7267   TCollection_AsciiString aRecFile;
7268   Image_VideoParams aRecParams;
7269
7270   Handle(V3d_View) aView = ViewerTest::CurrentView();
7271   for (; anArgIter < theArgNb; ++anArgIter)
7272   {
7273     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7274     anArg.LowerCase();
7275     // general options
7276     if (anArg == "-reset"
7277      || anArg == "-clear")
7278     {
7279       anAnimation->Clear();
7280     }
7281     else if (anArg == "-remove"
7282           || anArg == "-del"
7283           || anArg == "-delete")
7284     {
7285       if (!aParentAnimation.IsNull())
7286       {
7287         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7288       }
7289       else
7290       {
7291         aParentAnimation->Remove (anAnimation);
7292       }
7293     }
7294     // playback options
7295     else if (anArg == "-play")
7296     {
7297       toPlay = Standard_True;
7298       if (++anArgIter < theArgNb)
7299       {
7300         if (*theArgVec[anArgIter] == '-')
7301         {
7302           --anArgIter;
7303           continue;
7304         }
7305         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7306
7307         if (++anArgIter < theArgNb)
7308         {
7309           if (*theArgVec[anArgIter] == '-')
7310           {
7311             --anArgIter;
7312             continue;
7313           }
7314           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7315         }
7316       }
7317     }
7318     else if (anArg == "-resume")
7319     {
7320       toPlay = Standard_True;
7321       aPlayStartTime = anAnimation->ElapsedTime();
7322       if (++anArgIter < theArgNb)
7323       {
7324         if (*theArgVec[anArgIter] == '-')
7325         {
7326           --anArgIter;
7327           continue;
7328         }
7329
7330         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7331       }
7332     }
7333     else if (anArg == "-playspeed"
7334           || anArg == "-speed")
7335     {
7336       if (++anArgIter >= theArgNb)
7337       {
7338         std::cout << "Syntax error at " << anArg << ".\n";
7339         return 1;
7340       }
7341       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7342     }
7343     else if (anArg == "-lock"
7344           || anArg == "-lockloop"
7345           || anArg == "-playlockloop")
7346     {
7347       isLockLoop = Standard_True;
7348     }
7349     else if (anArg == "-freecamera"
7350           || anArg == "-playfreecamera"
7351           || anArg == "-freelook")
7352     {
7353       isFreeCamera = Standard_True;
7354     }
7355     // video recodring options
7356     else if (anArg == "-rec"
7357           || anArg == "-record")
7358     {
7359       if (++anArgIter >= theArgNb)
7360       {
7361         std::cout << "Syntax error at " << anArg << ".\n";
7362         return 1;
7363       }
7364
7365       aRecFile = theArgVec[anArgIter];
7366       if (aRecParams.FpsNum <= 0)
7367       {
7368         aRecParams.FpsNum = 24;
7369       }
7370
7371       if (anArgIter + 2 < theArgNb
7372       && *theArgVec[anArgIter + 1] != '-'
7373       && *theArgVec[anArgIter + 2] != '-')
7374       {
7375         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7376         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7377         if (aWidthArg .IsIntegerValue()
7378          && aHeightArg.IsIntegerValue())
7379         {
7380           aRecParams.Width  = aWidthArg .IntegerValue();
7381           aRecParams.Height = aHeightArg.IntegerValue();
7382           anArgIter += 2;
7383         }
7384       }
7385     }
7386     else if (anArg == "-fps")
7387     {
7388       if (++anArgIter >= theArgNb)
7389       {
7390         std::cout << "Syntax error at " << anArg << ".\n";
7391         return 1;
7392       }
7393
7394       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7395       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7396       if (aSplitIndex == 0)
7397       {
7398         aRecParams.FpsNum = aFpsArg.IntegerValue();
7399       }
7400       else
7401       {
7402         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7403         aFpsArg.Split (aFpsArg.Length() - 1);
7404         const TCollection_AsciiString aNumStr = aFpsArg;
7405         aRecParams.FpsNum = aNumStr.IntegerValue();
7406         aRecParams.FpsDen = aDenStr.IntegerValue();
7407         if (aRecParams.FpsDen < 1)
7408         {
7409           std::cout << "Syntax error at " << anArg << ".\n";
7410           return 1;
7411         }
7412       }
7413     }
7414     else if (anArg == "-format")
7415     {
7416       if (++anArgIter >= theArgNb)
7417       {
7418         std::cout << "Syntax error at " << anArg << ".\n";
7419         return 1;
7420       }
7421       aRecParams.Format = theArgVec[anArgIter];
7422     }
7423     else if (anArg == "-pix_fmt"
7424           || anArg == "-pixfmt"
7425           || anArg == "-pixelformat")
7426     {
7427       if (++anArgIter >= theArgNb)
7428       {
7429         std::cout << "Syntax error at " << anArg << ".\n";
7430         return 1;
7431       }
7432       aRecParams.PixelFormat = theArgVec[anArgIter];
7433     }
7434     else if (anArg == "-codec"
7435           || anArg == "-vcodec"
7436           || anArg == "-videocodec")
7437     {
7438       if (++anArgIter >= theArgNb)
7439       {
7440         std::cout << "Syntax error at " << anArg << ".\n";
7441         return 1;
7442       }
7443       aRecParams.VideoCodec = theArgVec[anArgIter];
7444     }
7445     else if (anArg == "-crf"
7446           || anArg == "-preset"
7447           || anArg == "-qp")
7448     {
7449       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7450       if (++anArgIter >= theArgNb)
7451       {
7452         std::cout << "Syntax error at " << anArg << ".\n";
7453         return 1;
7454       }
7455
7456       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7457     }
7458     // animation definition options
7459     else if (anArg == "-start"
7460           || anArg == "-starttime"
7461           || anArg == "-startpts")
7462     {
7463       if (++anArgIter >= theArgNb)
7464       {
7465         std::cout << "Syntax error at " << anArg << ".\n";
7466         return 1;
7467       }
7468
7469       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7470       aRootAnimation->UpdateTotalDuration();
7471     }
7472     else if (anArg == "-end"
7473           || anArg == "-endtime"
7474           || anArg == "-endpts")
7475     {
7476       if (++anArgIter >= theArgNb)
7477       {
7478         std::cout << "Syntax error at " << anArg << ".\n";
7479         return 1;
7480       }
7481
7482       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7483       aRootAnimation->UpdateTotalDuration();
7484     }
7485     else if (anArg == "-dur"
7486           || anArg == "-duration")
7487     {
7488       if (++anArgIter >= theArgNb)
7489       {
7490         std::cout << "Syntax error at " << anArg << ".\n";
7491         return 1;
7492       }
7493
7494       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7495       aRootAnimation->UpdateTotalDuration();
7496     }
7497     else if (anArg == "-command"
7498           || anArg == "-cmd"
7499           || anArg == "-invoke"
7500           || anArg == "-eval"
7501           || anArg == "-proc")
7502     {
7503       if (++anArgIter >= theArgNb)
7504       {
7505         std::cout << "Syntax error at " << anArg << ".\n";
7506         return 1;
7507       }
7508
7509       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7510       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7511     }
7512     else if (anArg == "-objecttrsf"
7513           || anArg == "-objectransformation"
7514           || anArg == "-objtransformation"
7515           || anArg == "-objtrsf"
7516           || anArg == "-object"
7517           || anArg == "-obj")
7518     {
7519       if (++anArgIter >= theArgNb)
7520       {
7521         std::cout << "Syntax error at " << anArg << ".\n";
7522         return 1;
7523       }
7524
7525       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7526       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7527       Handle(AIS_InteractiveObject) anObject;
7528       if (!aMapOfAIS.Find2 (anObjName, anObject))
7529       {
7530         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7531         return 1;
7532       }
7533
7534       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7535       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7536       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7537       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7538       Standard_Boolean isTrsfSet = Standard_False;
7539       Standard_Integer aTrsfArgIter = anArgIter + 1;
7540       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7541       {
7542         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7543         aTrsfArg.LowerCase();
7544         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7545         if (aTrsfArg.StartsWith ("-rotation")
7546          || aTrsfArg.StartsWith ("-rot"))
7547         {
7548           isTrsfSet = Standard_True;
7549           if (aTrsfArgIter + 4 >= theArgNb
7550           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7551           {
7552             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7553             return 1;
7554           }
7555           aTrsfArgIter += 4;
7556         }
7557         else if (aTrsfArg.StartsWith ("-location")
7558               || aTrsfArg.StartsWith ("-loc"))
7559         {
7560           isTrsfSet = Standard_True;
7561           if (aTrsfArgIter + 3 >= theArgNb
7562           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7563           {
7564             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7565             return 1;
7566           }
7567           aTrsfArgIter += 3;
7568         }
7569         else if (aTrsfArg.StartsWith ("-scale"))
7570         {
7571           isTrsfSet = Standard_True;
7572           if (++aTrsfArgIter >= theArgNb)
7573           {
7574             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7575             return 1;
7576           }
7577
7578           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7579           if (!aScaleStr.IsRealValue())
7580           {
7581             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7582             return 1;
7583           }
7584           aScales[anIndex] = aScaleStr.RealValue();
7585         }
7586         else
7587         {
7588           anArgIter = aTrsfArgIter - 1;
7589           break;
7590         }
7591       }
7592       if (!isTrsfSet)
7593       {
7594         std::cout << "Syntax error at " << anArg << ".\n";
7595         return 1;
7596       }
7597       else if (aTrsfArgIter >= theArgNb)
7598       {
7599         anArgIter = theArgNb;
7600       }
7601
7602       aTrsfs[0].SetRotation        (aRotQuats[0]);
7603       aTrsfs[1].SetRotation        (aRotQuats[1]);
7604       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7605       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7606       aTrsfs[0].SetScaleFactor     (aScales[0]);
7607       aTrsfs[1].SetScaleFactor     (aScales[1]);
7608
7609       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7610       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7611     }
7612     else if (anArg == "-viewtrsf"
7613           || anArg == "-view")
7614     {
7615       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7616       if (aCamAnimation.IsNull())
7617       {
7618         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7619         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7620       }
7621
7622       Handle(Graphic3d_Camera) aCams[2] =
7623       {
7624         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7625         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7626       };
7627
7628       Standard_Boolean isTrsfSet = Standard_False;
7629       Standard_Integer aViewArgIter = anArgIter + 1;
7630       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7631       {
7632         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7633         aViewArg.LowerCase();
7634         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7635         if (aViewArg.StartsWith ("-scale"))
7636         {
7637           isTrsfSet = Standard_True;
7638           if (++aViewArgIter >= theArgNb)
7639           {
7640             std::cout << "Syntax error at " << anArg << ".\n";
7641             return 1;
7642           }
7643
7644           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7645           if (!aScaleStr.IsRealValue())
7646           {
7647             std::cout << "Syntax error at " << aViewArg << ".\n";
7648             return 1;
7649           }
7650           Standard_Real aScale = aScaleStr.RealValue();
7651           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7652           aCams[anIndex]->SetScale (aScale);
7653         }
7654         else if (aViewArg.StartsWith ("-eye")
7655               || aViewArg.StartsWith ("-center")
7656               || aViewArg.StartsWith ("-at")
7657               || aViewArg.StartsWith ("-up"))
7658         {
7659           isTrsfSet = Standard_True;
7660           gp_XYZ anXYZ;
7661           if (aViewArgIter + 3 >= theArgNb
7662           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7663           {
7664             std::cout << "Syntax error at " << aViewArg << ".\n";
7665             return 1;
7666           }
7667           aViewArgIter += 3;
7668
7669           if (aViewArg.StartsWith ("-eye"))
7670           {
7671             aCams[anIndex]->SetEye (anXYZ);
7672           }
7673           else if (aViewArg.StartsWith ("-center")
7674                 || aViewArg.StartsWith ("-at"))
7675           {
7676             aCams[anIndex]->SetCenter (anXYZ);
7677           }
7678           else if (aViewArg.StartsWith ("-up"))
7679           {
7680             aCams[anIndex]->SetUp (anXYZ);
7681           }
7682         }
7683         else
7684         {
7685           anArgIter = aViewArgIter - 1;
7686           break;
7687         }
7688       }
7689       if (!isTrsfSet)
7690       {
7691         std::cout << "Syntax error at " << anArg << ".\n";
7692         return 1;
7693       }
7694       else if (aViewArgIter >= theArgNb)
7695       {
7696         anArgIter = theArgNb;
7697       }
7698
7699       aCamAnimation->SetCameraStart(aCams[0]);
7700       aCamAnimation->SetCameraEnd  (aCams[1]);
7701     }
7702     else
7703     {
7704       std::cout << "Syntax error at " << anArg << ".\n";
7705       return 1;
7706     }
7707   }
7708
7709   if (!toPlay && aRecFile.IsEmpty())
7710   {
7711     return 0;
7712   }
7713
7714   // Start animation timeline and process frame updating.
7715   TheIsAnimating = Standard_True;
7716   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7717   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7718   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7719   if (isFreeCamera)
7720   {
7721     aView->Camera()->Copy (aCameraBack);
7722   }
7723
7724   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7725   if (aRecParams.FpsNum <= 0)
7726   {
7727     while (!anAnimation->IsStopped())
7728     {
7729       aCameraBack->Copy (aView->Camera());
7730       const Standard_Real aPts = anAnimation->UpdateTimer();
7731       if (isFreeCamera)
7732       {
7733         aView->Camera()->Copy (aCameraBack);
7734       }
7735
7736       if (aPts >= anUpperPts)
7737       {
7738         anAnimation->Pause();
7739         break;
7740       }
7741
7742       if (aView->IsInvalidated())
7743       {
7744         aView->Redraw();
7745       }
7746       else
7747       {
7748         aView->RedrawImmediate();
7749       }
7750
7751       if (!isLockLoop)
7752       {
7753         // handle user events
7754         theDI.Eval ("after 1 set waiter 1");
7755         theDI.Eval ("vwait waiter");
7756       }
7757       if (!TheIsAnimating)
7758       {
7759         anAnimation->Pause();
7760         theDI << aPts;
7761         break;
7762       }
7763     }
7764
7765     if (aView->IsInvalidated())
7766     {
7767       aView->Redraw();
7768     }
7769     else
7770     {
7771       aView->RedrawImmediate();
7772     }
7773   }
7774   else
7775   {
7776     OSD_Timer aPerfTimer;
7777     aPerfTimer.Start();
7778
7779     Handle(Image_VideoRecorder) aRecorder;
7780     ImageFlipper aFlipper;
7781     Handle(Draw_ProgressIndicator) aProgress;
7782     if (!aRecFile.IsEmpty())
7783     {
7784       if (aRecParams.Width  <= 0
7785        || aRecParams.Height <= 0)
7786       {
7787         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7788       }
7789
7790       aRecorder = new Image_VideoRecorder();
7791       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7792       {
7793         std::cout << "Error: failed to open video file for recording\n";
7794         return 0;
7795       }
7796
7797       aProgress = new Draw_ProgressIndicator (theDI, 1);
7798     }
7799
7800     // Manage frame-rated animation here
7801     Standard_Real aPts = aPlayStartTime;
7802     int64_t aNbFrames = 0;
7803     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7804     Standard_Integer aSecondsProgress = 0;
7805     for (; aPts <= anUpperPts && aPSentry.More();)
7806     {
7807       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
7808       aPts = aPlayStartTime + aRecPts;
7809       ++aNbFrames;
7810       if (!anAnimation->Update (aPts))
7811       {
7812         break;
7813       }
7814
7815       if (!aRecorder.IsNull())
7816       {
7817         V3d_ImageDumpOptions aDumpParams;
7818         aDumpParams.Width          = aRecParams.Width;
7819         aDumpParams.Height         = aRecParams.Height;
7820         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
7821         aDumpParams.StereoOptions  = V3d_SDO_MONO;
7822         aDumpParams.ToAdjustAspect = Standard_True;
7823         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
7824         {
7825           std::cout << "Error: view dump is failed!\n";
7826           return 0;
7827         }
7828         aFlipper.FlipY (aRecorder->ChangeFrame());
7829         if (!aRecorder->PushFrame())
7830         {
7831           return 0;
7832         }
7833       }
7834       else
7835       {
7836         aView->Redraw();
7837       }
7838
7839       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7840       {
7841         aPSentry.Next();
7842         ++aSecondsProgress;
7843       }
7844     }
7845
7846     aPerfTimer.Stop();
7847     anAnimation->Stop();
7848     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7849     theDI << "Average FPS: " << aRecFps << "\n"
7850           << "Nb. Frames: "  << Standard_Real(aNbFrames);
7851
7852     aView->Redraw();
7853   }
7854
7855   aView->SetImmediateUpdate (wasImmediateUpdate);
7856   TheIsAnimating = Standard_False;
7857   return 0;
7858 }
7859
7860
7861 //=======================================================================
7862 //function : VChangeSelected
7863 //purpose  : Adds the shape to selection or remove one from it
7864 //=======================================================================
7865 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7866                                 Standard_Integer argc,
7867                                 const char ** argv)
7868 {
7869   if(argc != 2)
7870   {
7871     di<<"Usage : " << argv[0] << " shape \n";
7872     return 1;
7873   }
7874   //get AIS_Shape:
7875   TCollection_AsciiString aName(argv[1]);
7876   Handle(AIS_InteractiveObject) anAISObject;
7877   if (!GetMapOfAIS().Find2 (aName, anAISObject)
7878     || anAISObject.IsNull())
7879   {
7880     di<<"Use 'vdisplay' before";
7881     return 1;
7882   }
7883
7884   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
7885   return 0;
7886 }
7887
7888 //=======================================================================
7889 //function : VNbSelected
7890 //purpose  : Returns number of selected objects
7891 //=======================================================================
7892 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7893                                 Standard_Integer argc,
7894                                 const char ** argv)
7895 {
7896   if(argc != 1)
7897   {
7898     di << "Usage : " << argv[0] << "\n";
7899     return 1;
7900   }
7901   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7902   if(aContext.IsNull())
7903   {
7904     di << "use 'vinit' command before " << argv[0] << "\n";
7905     return 1;
7906   }
7907   di << aContext->NbSelected() << "\n";
7908   return 0;
7909 }
7910
7911 //=======================================================================
7912 //function : VPurgeDisplay
7913 //purpose  : Switches altialiasing on or off
7914 //=======================================================================
7915 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7916                                 Standard_Integer argc,
7917                                 const char ** argv)
7918 {
7919   if (argc > 1)
7920   {
7921     di << "Usage : " << argv[0] << "\n";
7922     return 1;
7923   }
7924   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7925   if (aContext.IsNull())
7926   {
7927     di << "use 'vinit' command before " << argv[0] << "\n";
7928     return 1;
7929   }
7930
7931   di << aContext->PurgeDisplay() << "\n";
7932   return 0;
7933 }
7934
7935 //=======================================================================
7936 //function : VSetViewSize
7937 //purpose  :
7938 //=======================================================================
7939 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7940                                 Standard_Integer argc,
7941                                 const char ** argv)
7942 {
7943   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7944   if(aContext.IsNull())
7945   {
7946     di << "use 'vinit' command before " << argv[0] << "\n";
7947     return 1;
7948   }
7949   if(argc != 2)
7950   {
7951     di<<"Usage : " << argv[0] << " Size\n";
7952     return 1;
7953   }
7954   Standard_Real aSize = Draw::Atof (argv[1]);
7955   if (aSize <= 0.)
7956   {
7957     di<<"Bad Size value  : " << aSize << "\n";
7958     return 1;
7959   }
7960
7961   Handle(V3d_View) aView = ViewerTest::CurrentView();
7962   aView->SetSize(aSize);
7963   return 0;
7964 }
7965
7966 //=======================================================================
7967 //function : VMoveView
7968 //purpose  :
7969 //=======================================================================
7970 static Standard_Integer VMoveView (Draw_Interpretor& di,
7971                                 Standard_Integer argc,
7972                                 const char ** argv)
7973 {
7974   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7975   if(aContext.IsNull())
7976   {
7977     di << "use 'vinit' command before " << argv[0] << "\n";
7978     return 1;
7979   }
7980   if(argc < 4 || argc > 5)
7981   {
7982     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7983     return 1;
7984   }
7985   Standard_Real Dx = Draw::Atof (argv[1]);
7986   Standard_Real Dy = Draw::Atof (argv[2]);
7987   Standard_Real Dz = Draw::Atof (argv[3]);
7988   Standard_Boolean aStart = Standard_True;
7989   if (argc == 5)
7990   {
7991       aStart = (Draw::Atoi (argv[4]) > 0);
7992   }
7993
7994   Handle(V3d_View) aView = ViewerTest::CurrentView();
7995   aView->Move(Dx,Dy,Dz,aStart);
7996   return 0;
7997 }
7998
7999 //=======================================================================
8000 //function : VTranslateView
8001 //purpose  :
8002 //=======================================================================
8003 static Standard_Integer VTranslateView (Draw_Interpretor& di,
8004                                 Standard_Integer argc,
8005                                 const char ** argv)
8006 {
8007   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8008   if(aContext.IsNull())
8009   {
8010     di << "use 'vinit' command before " << argv[0] << "\n";
8011     return 1;
8012   }
8013   if(argc < 4 || argc > 5)
8014   {
8015     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8016     return 1;
8017   }
8018   Standard_Real Dx = Draw::Atof (argv[1]);
8019   Standard_Real Dy = Draw::Atof (argv[2]);
8020   Standard_Real Dz = Draw::Atof (argv[3]);
8021   Standard_Boolean aStart = Standard_True;
8022   if (argc == 5)
8023   {
8024       aStart = (Draw::Atoi (argv[4]) > 0);
8025   }
8026
8027   Handle(V3d_View) aView = ViewerTest::CurrentView();
8028   aView->Translate(Dx,Dy,Dz,aStart);
8029   return 0;
8030 }
8031
8032 //=======================================================================
8033 //function : VTurnView
8034 //purpose  :
8035 //=======================================================================
8036 static Standard_Integer VTurnView (Draw_Interpretor& di,
8037                                 Standard_Integer argc,
8038                                 const char ** argv)
8039 {
8040   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8041   if(aContext.IsNull()) {
8042     di << "use 'vinit' command before " << argv[0] << "\n";
8043     return 1;
8044   }
8045   if(argc < 4 || argc > 5){
8046     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
8047     return 1;
8048   }
8049   Standard_Real Ax = Draw::Atof (argv[1]);
8050   Standard_Real Ay = Draw::Atof (argv[2]);
8051   Standard_Real Az = Draw::Atof (argv[3]);
8052   Standard_Boolean aStart = Standard_True;
8053   if (argc == 5)
8054   {
8055       aStart = (Draw::Atoi (argv[4]) > 0);
8056   }
8057
8058   Handle(V3d_View) aView = ViewerTest::CurrentView();
8059   aView->Turn(Ax,Ay,Az,aStart);
8060   return 0;
8061 }
8062
8063 //==============================================================================
8064 //function : VTextureEnv
8065 //purpose  : ENables or disables environment mapping
8066 //==============================================================================
8067 class OCC_TextureEnv : public Graphic3d_TextureEnv
8068 {
8069 public:
8070   OCC_TextureEnv(const Standard_CString FileName);
8071   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8072   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8073                             const Standard_Boolean theModulateFlag,
8074                             const Graphic3d_TypeOfTextureFilter theFilter,
8075                             const Standard_ShortReal theXScale,
8076                             const Standard_ShortReal theYScale,
8077                             const Standard_ShortReal theXShift,
8078                             const Standard_ShortReal theYShift,
8079                             const Standard_ShortReal theAngle);
8080   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
8081 };
8082 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
8083
8084 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8085   : Graphic3d_TextureEnv(theFileName)
8086 {
8087 }
8088
8089 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8090   : Graphic3d_TextureEnv(theTexId)
8091 {
8092 }
8093
8094 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8095                                           const Standard_Boolean theModulateFlag,
8096                                           const Graphic3d_TypeOfTextureFilter theFilter,
8097                                           const Standard_ShortReal theXScale,
8098                                           const Standard_ShortReal theYScale,
8099                                           const Standard_ShortReal theXShift,
8100                                           const Standard_ShortReal theYShift,
8101                                           const Standard_ShortReal theAngle)
8102 {
8103   myParams->SetRepeat     (theRepeatFlag);
8104   myParams->SetModulate   (theModulateFlag);
8105   myParams->SetFilter     (theFilter);
8106   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
8107   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8108   myParams->SetRotation   (theAngle);
8109 }
8110
8111 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
8112 {
8113   // get the active view
8114   Handle(V3d_View) aView = ViewerTest::CurrentView();
8115   if (aView.IsNull())
8116   {
8117     std::cerr << "No active view. Please call vinit.\n";
8118     return 1;
8119   }
8120
8121   // Checking the input arguments
8122   Standard_Boolean anEnableFlag = Standard_False;
8123   Standard_Boolean isOk         = theArgNb >= 2;
8124   if (isOk)
8125   {
8126     TCollection_AsciiString anEnableOpt(theArgVec[1]);
8127     anEnableFlag = anEnableOpt.IsEqual("on");
8128     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
8129   }
8130   if (anEnableFlag)
8131   {
8132     isOk = (theArgNb == 3 || theArgNb == 11);
8133     if (isOk)
8134     {
8135       TCollection_AsciiString aTextureOpt(theArgVec[2]);
8136       isOk = (!aTextureOpt.IsIntegerValue() ||
8137              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8138
8139       if (isOk && theArgNb == 11)
8140       {
8141         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
8142                                 aModulateOpt(theArgVec[4]),
8143                                 aFilterOpt  (theArgVec[5]),
8144                                 aSScaleOpt  (theArgVec[6]),
8145                                 aTScaleOpt  (theArgVec[7]),
8146                                 aSTransOpt  (theArgVec[8]),
8147                                 aTTransOpt  (theArgVec[9]),
8148                                 anAngleOpt  (theArgVec[10]);
8149         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
8150                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8151                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
8152                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
8153                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
8154                 anAngleOpt.IsRealValue());
8155       }
8156     }
8157   }
8158
8159   if (!isOk)
8160   {
8161     std::cerr << "Usage :" << std::endl;
8162     std::cerr << theArgVec[0] << " off" << std::endl;
8163     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;
8164     return 1;
8165   }
8166
8167   if (anEnableFlag)
8168   {
8169     TCollection_AsciiString aTextureOpt(theArgVec[2]);
8170     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8171                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8172                                      new OCC_TextureEnv(theArgVec[2]);
8173
8174     if (theArgNb == 11)
8175     {
8176       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8177       aTexEnv->SetTextureParameters(
8178         aRepeatOpt.  IsEqual("repeat"),
8179         aModulateOpt.IsEqual("modulate"),
8180         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8181                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8182                                                                            Graphic3d_TOTF_TRILINEAR,
8183         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8184         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8185         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8186         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8187         (Standard_ShortReal)Draw::Atof(theArgVec[10])
8188         );
8189     }
8190     aView->SetTextureEnv(aTexEnv);
8191   }
8192   else // Disabling environment mapping
8193   {
8194     Handle(Graphic3d_TextureEnv) aTexture;
8195     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8196   }
8197
8198   aView->Redraw();
8199   return 0;
8200 }
8201
8202 namespace
8203 {
8204   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8205
8206   //! Remove registered clipping plane from all views and objects.
8207   static void removePlane (MapOfPlanes& theRegPlanes,
8208                            const TCollection_AsciiString& theName)
8209   {
8210     Handle(Graphic3d_ClipPlane) aClipPlane;
8211     if (!theRegPlanes.Find (theName, aClipPlane))
8212     {
8213       std::cout << "Warning: no such plane.\n";
8214       return;
8215     }
8216
8217     theRegPlanes.UnBind (theName);
8218     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8219          anIObjIt.More(); anIObjIt.Next())
8220     {
8221       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
8222       aPrs->RemoveClipPlane (aClipPlane);
8223     }
8224
8225     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8226          aViewIt.More(); aViewIt.Next())
8227     {
8228       const Handle(V3d_View)& aView = aViewIt.Key2();
8229       aView->RemoveClipPlane(aClipPlane);
8230     }
8231
8232     ViewerTest::RedrawAllViews();
8233   }
8234 }
8235
8236 //===============================================================================================
8237 //function : VClipPlane
8238 //purpose  :
8239 //===============================================================================================
8240 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8241 {
8242   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8243   static MapOfPlanes aRegPlanes;
8244
8245   if (theArgsNb < 2)
8246   {
8247     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8248     {
8249       theDi << aPlaneIter.Key() << " ";
8250     }
8251     return 0;
8252   }
8253
8254   TCollection_AsciiString aCommand (theArgVec[1]);
8255   aCommand.LowerCase();
8256   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8257   if (anActiveView.IsNull())
8258   {
8259     std::cout << "Error: no active view.\n";
8260     return 1;
8261   }
8262
8263   // print maximum number of planes for current viewer
8264   if (aCommand == "-maxplanes"
8265    || aCommand == "maxplanes")
8266   {
8267     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8268           << " plane slots provided by driver.\n";
8269     return 0;
8270   }
8271
8272   // create / delete plane instance
8273   if (aCommand == "-create"
8274    || aCommand == "create"
8275    || aCommand == "-delete"
8276    || aCommand == "delete"
8277    || aCommand == "-clone"
8278    || aCommand == "clone")
8279   {
8280     if (theArgsNb < 3)
8281     {
8282       std::cout << "Syntax error: plane name is required.\n";
8283       return 1;
8284     }
8285
8286     Standard_Boolean toCreate = aCommand == "-create"
8287                              || aCommand == "create";
8288     Standard_Boolean toClone  = aCommand == "-clone"
8289                              || aCommand == "clone";
8290     Standard_Boolean toDelete = aCommand == "-delete"
8291                              || aCommand == "delete";
8292     TCollection_AsciiString aPlane (theArgVec[2]);
8293
8294     if (toCreate)
8295     {
8296       if (aRegPlanes.IsBound (aPlane))
8297       {
8298         std::cout << "Warning: existing plane has been overridden.\n";
8299         toDelete = true;
8300       }
8301       else
8302       {
8303         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8304         return 0;
8305       }
8306     }
8307     else if (toClone) // toClone
8308     {
8309       if (!aRegPlanes.IsBound (aPlane))
8310       {
8311         std::cout << "Error: no such plane.\n";
8312         return 1;
8313       }
8314       else if (theArgsNb < 4)
8315       {
8316         std::cout << "Syntax error: enter name for new plane.\n";
8317         return 1;
8318       }
8319
8320       TCollection_AsciiString aClone (theArgVec[3]);
8321       if (aRegPlanes.IsBound (aClone))
8322       {
8323         std::cout << "Error: plane name is in use.\n";
8324         return 1;
8325       }
8326
8327       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8328
8329       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8330       return 0;
8331     }
8332
8333     if (toDelete)
8334     {
8335       if (aPlane == "ALL"
8336        || aPlane == "all"
8337        || aPlane == "*")
8338       {
8339         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8340         {
8341           aPlane = aPlaneIter.Key();
8342           removePlane (aRegPlanes, aPlane);
8343           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8344         }
8345       }
8346       else
8347       {
8348         removePlane (aRegPlanes, aPlane);
8349       }
8350     }
8351
8352     if (toCreate)
8353     {
8354       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8355     }
8356     return 0;
8357   }
8358
8359   // set / unset plane command
8360   if (aCommand == "set"
8361    || aCommand == "unset")
8362   {
8363     if (theArgsNb < 5)
8364     {
8365       std::cout << "Syntax error: need more arguments.\n";
8366       return 1;
8367     }
8368
8369     // redirect to new syntax
8370     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8371     anArgVec.SetValue (1, theArgVec[0]);
8372     anArgVec.SetValue (2, theArgVec[2]);
8373     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8374     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8375     {
8376       anArgVec.SetValue (anIt, theArgVec[anIt]);
8377     }
8378
8379     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8380   }
8381
8382   // change plane command
8383   TCollection_AsciiString aPlaneName;
8384   Handle(Graphic3d_ClipPlane) aClipPlane;
8385   Standard_Integer anArgIter = 0;
8386   if (aCommand == "-change"
8387    || aCommand == "change")
8388   {
8389     // old syntax support
8390     if (theArgsNb < 3)
8391     {
8392       std::cout << "Syntax error: need more arguments.\n";
8393       return 1;
8394     }
8395
8396     anArgIter  = 3;
8397     aPlaneName = theArgVec[2];
8398     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8399     {
8400       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8401       return 1;
8402     }
8403   }
8404   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8405   {
8406     anArgIter  = 2;
8407     aPlaneName = theArgVec[1];
8408   }
8409   else
8410   {
8411     anArgIter  = 2;
8412     aPlaneName = theArgVec[1];
8413     aClipPlane = new Graphic3d_ClipPlane();
8414     aRegPlanes.Bind (aPlaneName, aClipPlane);
8415     theDi << "Created new plane " << aPlaneName << ".\n";
8416   }
8417
8418   if (theArgsNb - anArgIter < 1)
8419   {
8420     std::cout << "Syntax error: need more arguments.\n";
8421     return 1;
8422   }
8423
8424   for (; anArgIter < theArgsNb; ++anArgIter)
8425   {
8426     const char**     aChangeArgs   = theArgVec + anArgIter;
8427     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8428     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8429     aChangeArg.LowerCase();
8430
8431     Standard_Boolean toEnable = Standard_True;
8432     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8433     {
8434       aClipPlane->SetOn (toEnable);
8435     }
8436     else if (aChangeArg.StartsWith ("-equation")
8437           || aChangeArg.StartsWith ("equation"))
8438     {
8439       if (aNbChangeArgs < 5)
8440       {
8441         std::cout << "Syntax error: need more arguments.\n";
8442         return 1;
8443       }
8444
8445       Standard_Integer aSubIndex = 1;
8446       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
8447       if (aPrefixLen < aChangeArg.Length())
8448       {
8449         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
8450         if (!aSubStr.IsIntegerValue()
8451           || aSubStr.IntegerValue() <= 0)
8452         {
8453           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8454           return 1;
8455         }
8456         aSubIndex = aSubStr.IntegerValue();
8457       }
8458
8459       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
8460       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
8461       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
8462       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
8463       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8464       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
8465       {
8466         if (aSubPln->ChainNextPlane().IsNull())
8467         {
8468           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8469         }
8470         aSubPln = aSubPln->ChainNextPlane();
8471       }
8472       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8473       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8474       anArgIter += 4;
8475     }
8476     else if ((aChangeArg == "-boxinterior"
8477            || aChangeArg == "-boxint"
8478            || aChangeArg == "-box")
8479             && aNbChangeArgs >= 7)
8480     {
8481       Graphic3d_BndBox3d aBndBox;
8482       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
8483       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
8484       anArgIter += 6;
8485
8486       Standard_Integer aNbSubPlanes = 6;
8487       const Graphic3d_Vec3d aDirArray[6] =
8488       {
8489         Graphic3d_Vec3d (-1, 0, 0),
8490         Graphic3d_Vec3d ( 1, 0, 0),
8491         Graphic3d_Vec3d ( 0,-1, 0),
8492         Graphic3d_Vec3d ( 0, 1, 0),
8493         Graphic3d_Vec3d ( 0, 0,-1),
8494         Graphic3d_Vec3d ( 0, 0, 1),
8495       };
8496       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8497       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
8498       {
8499         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
8500         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
8501         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
8502         if (aSubPlaneIter + 1 == aNbSubPlanes)
8503         {
8504           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8505         }
8506         else
8507         {
8508           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8509         }
8510         aSubPln = aSubPln->ChainNextPlane();
8511       }
8512     }
8513     else if (aChangeArg == "-capping"
8514           || aChangeArg == "capping")
8515     {
8516       if (aNbChangeArgs < 2)
8517       {
8518         std::cout << "Syntax error: need more arguments.\n";
8519         return 1;
8520       }
8521
8522       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8523       {
8524         aClipPlane->SetCapping (toEnable);
8525         anArgIter += 1;
8526       }
8527       else
8528       {
8529         // just skip otherwise (old syntax)
8530       }
8531     }
8532     else if (aChangeArg == "-useobjectmaterial"
8533           || aChangeArg == "-useobjectmat"
8534           || aChangeArg == "-useobjmat"
8535           || aChangeArg == "-useobjmaterial")
8536     {
8537       if (aNbChangeArgs < 2)
8538       {
8539         std::cout << "Syntax error: need more arguments.\n";
8540         return 1;
8541       }
8542
8543       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8544       {
8545         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8546         anArgIter += 1;
8547       }
8548     }
8549     else if (aChangeArg == "-useobjecttexture"
8550           || aChangeArg == "-useobjecttex"
8551           || aChangeArg == "-useobjtexture"
8552           || aChangeArg == "-useobjtex")
8553     {
8554       if (aNbChangeArgs < 2)
8555       {
8556         std::cout << "Syntax error: need more arguments.\n";
8557         return 1;
8558       }
8559
8560       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8561       {
8562         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8563         anArgIter += 1;
8564       }
8565     }
8566     else if (aChangeArg == "-useobjectshader"
8567           || aChangeArg == "-useobjshader")
8568     {
8569       if (aNbChangeArgs < 2)
8570       {
8571         std::cout << "Syntax error: need more arguments.\n";
8572         return 1;
8573       }
8574
8575       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8576       {
8577         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8578         anArgIter += 1;
8579       }
8580     }
8581     else if (aChangeArg == "-color"
8582           || aChangeArg == "color")
8583     {
8584       Quantity_Color aColor;
8585       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8586                                                            aChangeArgs + 1,
8587                                                            aColor);
8588       if (aNbParsed == 0)
8589       {
8590         std::cout << "Syntax error: need more arguments.\n";
8591         return 1;
8592       }
8593
8594       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8595       aMat.SetAmbientColor (aColor);
8596       aMat.SetDiffuseColor (aColor);
8597       aClipPlane->SetCappingMaterial (aMat);
8598       anArgIter += aNbParsed;
8599     }
8600     else if ((aChangeArg == "-transparency"
8601            || aChangeArg == "-transp")
8602           && aNbChangeArgs >= 2)
8603     {
8604       TCollection_AsciiString aValStr (aChangeArgs[1]);
8605       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
8606       if (aValStr.IsRealValue())
8607       {
8608         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8609         aMat.SetTransparency ((float )aValStr.RealValue());
8610         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
8611         aClipPlane->SetCappingMaterial (aMat);
8612       }
8613       else
8614       {
8615         aValStr.LowerCase();
8616         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
8617         if (aValStr == "opaque")
8618         {
8619           aMode = Graphic3d_AlphaMode_Opaque;
8620         }
8621         else if (aValStr == "mask")
8622         {
8623           aMode = Graphic3d_AlphaMode_Mask;
8624         }
8625         else if (aValStr == "blend")
8626         {
8627           aMode = Graphic3d_AlphaMode_Blend;
8628         }
8629         else if (aValStr == "blendauto")
8630         {
8631           aMode = Graphic3d_AlphaMode_BlendAuto;
8632         }
8633         else
8634         {
8635           std::cout << "Syntax error at '" << aValStr << "'\n";
8636           return 1;
8637         }
8638         anAspect->SetAlphaMode (aMode);
8639         aClipPlane->SetCappingAspect (anAspect);
8640       }
8641       anArgIter += 1;
8642     }
8643     else if (aChangeArg == "-texname"
8644           || aChangeArg == "texname")
8645     {
8646       if (aNbChangeArgs < 2)
8647       {
8648         std::cout << "Syntax error: need more arguments.\n";
8649         return 1;
8650       }
8651
8652       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8653       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8654       if (!aTexture->IsDone())
8655       {
8656         aClipPlane->SetCappingTexture (NULL);
8657       }
8658       else
8659       {
8660         aTexture->EnableModulate();
8661         aTexture->EnableRepeat();
8662         aClipPlane->SetCappingTexture (aTexture);
8663       }
8664       anArgIter += 1;
8665     }
8666     else if (aChangeArg == "-texscale"
8667           || aChangeArg == "texscale")
8668     {
8669       if (aClipPlane->CappingTexture().IsNull())
8670       {
8671         std::cout << "Error: no texture is set.\n";
8672         return 1;
8673       }
8674
8675       if (aNbChangeArgs < 3)
8676       {
8677         std::cout << "Syntax error: need more arguments.\n";
8678         return 1;
8679       }
8680
8681       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8682       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8683       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8684       anArgIter += 2;
8685     }
8686     else if (aChangeArg == "-texorigin"
8687           || aChangeArg == "texorigin") // texture origin
8688     {
8689       if (aClipPlane->CappingTexture().IsNull())
8690       {
8691         std::cout << "Error: no texture is set.\n";
8692         return 1;
8693       }
8694
8695       if (aNbChangeArgs < 3)
8696       {
8697         std::cout << "Syntax error: need more arguments.\n";
8698         return 1;
8699       }
8700
8701       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8702       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8703
8704       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8705       anArgIter += 2;
8706     }
8707     else if (aChangeArg == "-texrotate"
8708           || aChangeArg == "texrotate") // texture rotation
8709     {
8710       if (aClipPlane->CappingTexture().IsNull())
8711       {
8712         std::cout << "Error: no texture is set.\n";
8713         return 1;
8714       }
8715
8716       if (aNbChangeArgs < 2)
8717       {
8718         std::cout << "Syntax error: need more arguments.\n";
8719         return 1;
8720       }
8721
8722       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8723       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8724       anArgIter += 1;
8725     }
8726     else if (aChangeArg == "-hatch"
8727           || aChangeArg == "hatch")
8728     {
8729       if (aNbChangeArgs < 2)
8730       {
8731         std::cout << "Syntax error: need more arguments.\n";
8732         return 1;
8733       }
8734
8735       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8736       aHatchStr.LowerCase();
8737       if (aHatchStr == "on")
8738       {
8739         aClipPlane->SetCappingHatchOn();
8740       }
8741       else if (aHatchStr == "off")
8742       {
8743         aClipPlane->SetCappingHatchOff();
8744       }
8745       else
8746       {
8747         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8748       }
8749       anArgIter += 1;
8750     }
8751     else if (aChangeArg == "-delete"
8752           || aChangeArg == "delete")
8753     {
8754       removePlane (aRegPlanes, aPlaneName);
8755       return 0;
8756     }
8757     else if (aChangeArg == "-set"
8758           || aChangeArg == "-unset"
8759           || aChangeArg == "-setoverrideglobal")
8760     {
8761       // set / unset plane command
8762       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
8763       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
8764       Standard_Integer anIt = 1;
8765       for (; anIt < aNbChangeArgs; ++anIt)
8766       {
8767         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8768         if (anEntityName.IsEmpty()
8769          || anEntityName.Value (1) == '-')
8770         {
8771           break;
8772         }
8773         else if (!toOverrideGlobal
8774                && ViewerTest_myViews.IsBound1 (anEntityName))
8775         {
8776           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8777           if (toSet)
8778           {
8779             aView->AddClipPlane (aClipPlane);
8780           }
8781           else
8782           {
8783             aView->RemoveClipPlane (aClipPlane);
8784           }
8785           continue;
8786         }
8787         else if (GetMapOfAIS().IsBound2 (anEntityName))
8788         {
8789           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
8790           if (toSet)
8791           {
8792             aIObj->AddClipPlane (aClipPlane);
8793           }
8794           else
8795           {
8796             aIObj->RemoveClipPlane (aClipPlane);
8797           }
8798           if (!aIObj->ClipPlanes().IsNull())
8799           {
8800             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
8801           }
8802         }
8803         else
8804         {
8805           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
8806           return 1;
8807         }
8808       }
8809
8810       if (anIt == 1)
8811       {
8812         // apply to active view
8813         if (toSet)
8814         {
8815           anActiveView->AddClipPlane (aClipPlane);
8816         }
8817         else
8818         {
8819           anActiveView->RemoveClipPlane (aClipPlane);
8820         }
8821       }
8822       else
8823       {
8824         anArgIter = anArgIter + anIt - 1;
8825       }
8826     }
8827     else
8828     {
8829       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8830       return 1;
8831     }
8832   }
8833
8834   ViewerTest::RedrawAllViews();
8835   return 0;
8836 }
8837
8838 //===============================================================================================
8839 //function : VZRange
8840 //purpose  :
8841 //===============================================================================================
8842 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8843 {
8844   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8845
8846   if (aCurrentView.IsNull())
8847   {
8848     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8849     return 1;
8850   }
8851
8852   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
8853
8854   if (theArgsNb < 2)
8855   {
8856     theDi << "ZNear: " << aCamera->ZNear() << "\n";
8857     theDi << "ZFar: " << aCamera->ZFar() << "\n";
8858     return 0;
8859   }
8860
8861   if (theArgsNb == 3)
8862   {
8863     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8864     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
8865
8866     if (aNewZNear >= aNewZFar)
8867     {
8868       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
8869       return 1;
8870     }
8871
8872     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8873     {
8874       std::cout << theArgVec[0] << ": invalid arguments: ";
8875       std::cout << "znear, zfar should be positive for perspective camera.\n";
8876       return 1;
8877     }
8878
8879     aCamera->SetZRange (aNewZNear, aNewZFar);
8880   }
8881   else
8882   {
8883     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8884     return 1;
8885   }
8886
8887   aCurrentView->Redraw();
8888
8889   return 0;
8890 }
8891
8892 //===============================================================================================
8893 //function : VAutoZFit
8894 //purpose  :
8895 //===============================================================================================
8896 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8897 {
8898   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8899
8900   if (aCurrentView.IsNull())
8901   {
8902     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8903     return 1;
8904   }
8905
8906   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
8907
8908   if (theArgsNb > 3)
8909   {
8910     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8911     return 1;
8912   }
8913
8914   if (theArgsNb < 2)
8915   {
8916     theDi << "Auto z-fit mode: \n"
8917           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
8918           << "Scale: " << aScale << "\n";
8919     return 0;
8920   }
8921
8922   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
8923
8924   if (theArgsNb >= 3)
8925   {
8926     aScale = Draw::Atoi (theArgVec[2]);
8927   }
8928
8929   aCurrentView->SetAutoZFitMode (isOn, aScale);
8930   aCurrentView->AutoZFit();
8931   aCurrentView->Redraw();
8932
8933   return 0;
8934 }
8935
8936 //! Auxiliary function to print projection type
8937 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
8938 {
8939   switch (theProjType)
8940   {
8941     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
8942     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
8943     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
8944     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
8945     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
8946   }
8947   return "UNKNOWN";
8948 }
8949
8950 //===============================================================================================
8951 //function : VCamera
8952 //purpose  :
8953 //===============================================================================================
8954 static int VCamera (Draw_Interpretor& theDI,
8955                     Standard_Integer  theArgsNb,
8956                     const char**      theArgVec)
8957 {
8958   Handle(V3d_View) aView = ViewerTest::CurrentView();
8959   if (aView.IsNull())
8960   {
8961     std::cout << "Error: no active view.\n";
8962     return 1;
8963   }
8964
8965   Handle(Graphic3d_Camera) aCamera = aView->Camera();
8966   if (theArgsNb < 2)
8967   {
8968     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
8969     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
8970     theDI << "Distance:   " << aCamera->Distance() << "\n";
8971     theDI << "IOD:        " << aCamera->IOD() << "\n";
8972     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
8973     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
8974     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
8975     return 0;
8976   }
8977
8978   TCollection_AsciiString aPrsName;
8979   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8980   {
8981     Standard_CString        anArg = theArgVec[anArgIter];
8982     TCollection_AsciiString anArgCase (anArg);
8983     anArgCase.LowerCase();
8984     if (anArgCase == "-proj"
8985      || anArgCase == "-projection"
8986      || anArgCase == "-projtype"
8987      || anArgCase == "-projectiontype")
8988     {
8989       theDI << projTypeName (aCamera->ProjectionType()) << " ";
8990     }
8991     else if (anArgCase == "-ortho"
8992           || anArgCase == "-orthographic")
8993     {
8994       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8995     }
8996     else if (anArgCase == "-persp"
8997           || anArgCase == "-perspective"
8998           || anArgCase == "-perspmono"
8999           || anArgCase == "-perspectivemono"
9000           || anArgCase == "-mono")
9001     {
9002       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9003     }
9004     else if (anArgCase == "-stereo"
9005           || anArgCase == "-stereoscopic"
9006           || anArgCase == "-perspstereo"
9007           || anArgCase == "-perspectivestereo")
9008     {
9009       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9010     }
9011     else if (anArgCase == "-left"
9012           || anArgCase == "-lefteye"
9013           || anArgCase == "-monoleft"
9014           || anArgCase == "-monolefteye"
9015           || anArgCase == "-perpsleft"
9016           || anArgCase == "-perpslefteye")
9017     {
9018       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
9019     }
9020     else if (anArgCase == "-right"
9021           || anArgCase == "-righteye"
9022           || anArgCase == "-monoright"
9023           || anArgCase == "-monorighteye"
9024           || anArgCase == "-perpsright")
9025     {
9026       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
9027     }
9028     else if (anArgCase == "-dist"
9029           || anArgCase == "-distance")
9030     {
9031       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9032       if (anArgValue != NULL
9033       && *anArgValue != '-')
9034       {
9035         ++anArgIter;
9036         aCamera->SetDistance (Draw::Atof (anArgValue));
9037         continue;
9038       }
9039       theDI << aCamera->Distance() << " ";
9040     }
9041     else if (anArgCase == "-iod")
9042     {
9043       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9044       if (anArgValue != NULL
9045       && *anArgValue != '-')
9046       {
9047         ++anArgIter;
9048         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
9049         continue;
9050       }
9051       theDI << aCamera->IOD() << " ";
9052     }
9053     else if (anArgCase == "-iodtype")
9054     {
9055       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9056       TCollection_AsciiString anValueCase (anArgValue);
9057       anValueCase.LowerCase();
9058       if (anValueCase == "abs"
9059        || anValueCase == "absolute")
9060       {
9061         ++anArgIter;
9062         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
9063         continue;
9064       }
9065       else if (anValueCase == "rel"
9066             || anValueCase == "relative")
9067       {
9068         ++anArgIter;
9069         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
9070         continue;
9071       }
9072       else if (*anArgValue != '-')
9073       {
9074         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
9075         return 1;
9076       }
9077       switch (aCamera->GetIODType())
9078       {
9079         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
9080         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
9081       }
9082     }
9083     else if (anArgCase == "-zfocus")
9084     {
9085       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9086       if (anArgValue != NULL
9087       && *anArgValue != '-')
9088       {
9089         ++anArgIter;
9090         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
9091         continue;
9092       }
9093       theDI << aCamera->ZFocus() << " ";
9094     }
9095     else if (anArgCase == "-zfocustype")
9096     {
9097       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9098       TCollection_AsciiString anValueCase (anArgValue);
9099       anValueCase.LowerCase();
9100       if (anValueCase == "abs"
9101        || anValueCase == "absolute")
9102       {
9103         ++anArgIter;
9104         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
9105         continue;
9106       }
9107       else if (anValueCase == "rel"
9108             || anValueCase == "relative")
9109       {
9110         ++anArgIter;
9111         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
9112         continue;
9113       }
9114       else if (*anArgValue != '-')
9115       {
9116         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
9117         return 1;
9118       }
9119       switch (aCamera->ZFocusType())
9120       {
9121         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
9122         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
9123       }
9124     }
9125     else if (anArgCase == "-fov"
9126           || anArgCase == "-fovy")
9127     {
9128       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9129       if (anArgValue != NULL
9130       && *anArgValue != '-')
9131       {
9132         ++anArgIter;
9133         aCamera->SetFOVy (Draw::Atof (anArgValue));
9134         continue;
9135       }
9136       theDI << aCamera->FOVy() << " ";
9137     }
9138     else if (aPrsName.IsEmpty()
9139          && !anArgCase.StartsWith ("-"))
9140     {
9141       aPrsName = anArg;
9142     }
9143     else
9144     {
9145       std::cout << "Error: unknown argument '" << anArg << "'\n";
9146       return 1;
9147     }
9148   }
9149
9150   if (aPrsName.IsEmpty()
9151    || theArgsNb > 2)
9152   {
9153     aView->AutoZFit();
9154     aView->Redraw();
9155   }
9156
9157   if (!aPrsName.IsEmpty())
9158   {
9159     Handle(AIS_CameraFrustum) aCameraFrustum;
9160     if (GetMapOfAIS().IsBound2 (aPrsName))
9161     {
9162       // find existing object
9163       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
9164       if (aCameraFrustum.IsNull())
9165       {
9166         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
9167         return 1;
9168       }
9169     }
9170
9171     if (aCameraFrustum.IsNull())
9172     {
9173       aCameraFrustum = new AIS_CameraFrustum();
9174     }
9175     else
9176     {
9177       // not include displayed object of old camera frustum in the new one.
9178       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
9179       aView->ZFitAll();
9180     }
9181     aCameraFrustum->SetCameraFrustum (aView->Camera());
9182
9183     ViewerTest::Display (aPrsName, aCameraFrustum);
9184   }
9185
9186   return 0;
9187 }
9188
9189 //! Parse stereo output mode
9190 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
9191                                          Graphic3d_StereoMode& theMode)
9192 {
9193   TCollection_AsciiString aFlag (theArg);
9194   aFlag.LowerCase();
9195   if (aFlag == "quadbuffer")
9196   {
9197     theMode = Graphic3d_StereoMode_QuadBuffer;
9198   }
9199   else if (aFlag == "anaglyph")
9200   {
9201     theMode = Graphic3d_StereoMode_Anaglyph;
9202   }
9203   else if (aFlag == "row"
9204         || aFlag == "rowinterlaced")
9205   {
9206     theMode = Graphic3d_StereoMode_RowInterlaced;
9207   }
9208   else if (aFlag == "col"
9209         || aFlag == "colinterlaced"
9210         || aFlag == "columninterlaced")
9211   {
9212     theMode = Graphic3d_StereoMode_ColumnInterlaced;
9213   }
9214   else if (aFlag == "chess"
9215         || aFlag == "chessboard")
9216   {
9217     theMode = Graphic3d_StereoMode_ChessBoard;
9218   }
9219   else if (aFlag == "sbs"
9220         || aFlag == "sidebyside")
9221   {
9222     theMode = Graphic3d_StereoMode_SideBySide;
9223   }
9224   else if (aFlag == "ou"
9225         || aFlag == "overunder")
9226   {
9227     theMode = Graphic3d_StereoMode_OverUnder;
9228   }
9229   else if (aFlag == "pageflip"
9230         || aFlag == "softpageflip")
9231   {
9232     theMode = Graphic3d_StereoMode_SoftPageFlip;
9233   }
9234   else
9235   {
9236     return Standard_False;
9237   }
9238   return Standard_True;
9239 }
9240
9241 //! Parse anaglyph filter
9242 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
9243                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
9244 {
9245   TCollection_AsciiString aFlag (theArg);
9246   aFlag.LowerCase();
9247   if (aFlag == "redcyansimple")
9248   {
9249     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9250   }
9251   else if (aFlag == "redcyan"
9252         || aFlag == "redcyanoptimized")
9253   {
9254     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
9255   }
9256   else if (aFlag == "yellowbluesimple")
9257   {
9258     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
9259   }
9260   else if (aFlag == "yellowblue"
9261         || aFlag == "yellowblueoptimized")
9262   {
9263     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
9264   }
9265   else if (aFlag == "greenmagenta"
9266         || aFlag == "greenmagentasimple")
9267   {
9268     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
9269   }
9270   else
9271   {
9272     return Standard_False;
9273   }
9274   return Standard_True;
9275 }
9276
9277 //==============================================================================
9278 //function : VStereo
9279 //purpose  :
9280 //==============================================================================
9281
9282 static int VStereo (Draw_Interpretor& theDI,
9283                     Standard_Integer  theArgNb,
9284                     const char**      theArgVec)
9285 {
9286   Handle(V3d_View) aView = ViewerTest::CurrentView();
9287   if (theArgNb < 2)
9288   {
9289     if (aView.IsNull())
9290     {
9291       std::cout << "Error: no active viewer!\n";
9292       return 0;
9293     }
9294
9295     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
9296     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
9297     if (isActive)
9298     {
9299       TCollection_AsciiString aMode;
9300       switch (aView->RenderingParams().StereoMode)
9301       {
9302         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
9303         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
9304         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
9305         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
9306         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
9307         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
9308         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
9309         case Graphic3d_StereoMode_Anaglyph  :
9310           aMode = "anaglyph";
9311           switch (aView->RenderingParams().AnaglyphFilter)
9312           {
9313             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
9314             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
9315             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
9316             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
9317             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
9318             default: break;
9319           }
9320         default: break;
9321       }
9322       theDI << "Mode " << aMode << "\n";
9323     }
9324     return 0;
9325   }
9326
9327   Handle(Graphic3d_Camera) aCamera;
9328   Graphic3d_RenderingParams*   aParams   = NULL;
9329   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
9330   if (!aView.IsNull())
9331   {
9332     aParams   = &aView->ChangeRenderingParams();
9333     aMode     = aParams->StereoMode;
9334     aCamera   = aView->Camera();
9335   }
9336
9337   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9338   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9339   {
9340     Standard_CString        anArg = theArgVec[anArgIter];
9341     TCollection_AsciiString aFlag (anArg);
9342     aFlag.LowerCase();
9343     if (anUpdateTool.parseRedrawMode (aFlag))
9344     {
9345       continue;
9346     }
9347     else if (aFlag == "0"
9348           || aFlag == "off")
9349     {
9350       if (++anArgIter < theArgNb)
9351       {
9352         std::cout << "Error: wrong number of arguments!\n";
9353         return 1;
9354       }
9355
9356       if (!aCamera.IsNull()
9357        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
9358       {
9359         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9360       }
9361       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
9362       return 0;
9363     }
9364     else if (aFlag == "1"
9365           || aFlag == "on")
9366     {
9367       if (++anArgIter < theArgNb)
9368       {
9369         std::cout << "Error: wrong number of arguments!\n";
9370         return 1;
9371       }
9372
9373       if (!aCamera.IsNull())
9374       {
9375         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9376       }
9377       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9378       return 0;
9379     }
9380     else if (aFlag == "-reverse"
9381           || aFlag == "-reversed"
9382           || aFlag == "-swap")
9383     {
9384       Standard_Boolean toEnable = Standard_True;
9385       if (++anArgIter < theArgNb
9386       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9387       {
9388         --anArgIter;
9389       }
9390       aParams->ToReverseStereo = toEnable;
9391     }
9392     else if (aFlag == "-noreverse"
9393           || aFlag == "-noswap")
9394     {
9395       Standard_Boolean toDisable = Standard_True;
9396       if (++anArgIter < theArgNb
9397       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9398       {
9399         --anArgIter;
9400       }
9401       aParams->ToReverseStereo = !toDisable;
9402     }
9403     else if (aFlag == "-mode"
9404           || aFlag == "-stereomode")
9405     {
9406       if (++anArgIter >= theArgNb
9407       || !parseStereoMode (theArgVec[anArgIter], aMode))
9408       {
9409         std::cout << "Error: syntax error at '" << anArg << "'\n";
9410         return 1;
9411       }
9412
9413       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9414       {
9415         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9416       }
9417     }
9418     else if (aFlag == "-anaglyph"
9419           || aFlag == "-anaglyphfilter")
9420     {
9421       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9422       if (++anArgIter >= theArgNb
9423       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9424       {
9425         std::cout << "Error: syntax error at '" << anArg << "'\n";
9426         return 1;
9427       }
9428
9429       aMode = Graphic3d_StereoMode_Anaglyph;
9430       aParams->AnaglyphFilter = aFilter;
9431     }
9432     else if (parseStereoMode (anArg, aMode)) // short syntax
9433     {
9434       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9435       {
9436         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9437       }
9438     }
9439     else
9440     {
9441       std::cout << "Error: syntax error at '" << anArg << "'\n";
9442       return 1;
9443     }
9444   }
9445
9446   if (!aView.IsNull())
9447   {
9448     aParams->StereoMode = aMode;
9449     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9450   }
9451   return 0;
9452 }
9453
9454 //===============================================================================================
9455 //function : VDefaults
9456 //purpose  :
9457 //===============================================================================================
9458 static int VDefaults (Draw_Interpretor& theDi,
9459                       Standard_Integer  theArgsNb,
9460                       const char**      theArgVec)
9461 {
9462   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9463   if (aCtx.IsNull())
9464   {
9465     std::cerr << "No active viewer!\n";
9466     return 1;
9467   }
9468
9469   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9470   if (theArgsNb < 2)
9471   {
9472     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9473     {
9474       theDi << "DeflType:           relative\n"
9475             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9476     }
9477     else
9478     {
9479       theDi << "DeflType:           absolute\n"
9480             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9481     }
9482     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9483     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9484     return 0;
9485   }
9486
9487   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9488   {
9489     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9490     anArg.UpperCase();
9491     if (anArg == "-ABSDEFL"
9492      || anArg == "-ABSOLUTEDEFLECTION"
9493      || anArg == "-DEFL"
9494      || anArg == "-DEFLECTION")
9495     {
9496       if (++anArgIter >= theArgsNb)
9497       {
9498         std::cout << "Error: wrong syntax at " << anArg << "\n";
9499         return 1;
9500       }
9501       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9502       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9503     }
9504     else if (anArg == "-RELDEFL"
9505           || anArg == "-RELATIVEDEFLECTION"
9506           || anArg == "-DEVCOEFF"
9507           || anArg == "-DEVIATIONCOEFF"
9508           || anArg == "-DEVIATIONCOEFFICIENT")
9509     {
9510       if (++anArgIter >= theArgsNb)
9511       {
9512         std::cout << "Error: wrong syntax at " << anArg << "\n";
9513         return 1;
9514       }
9515       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9516       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9517     }
9518     else if (anArg == "-ANGDEFL"
9519           || anArg == "-ANGULARDEFL"
9520           || anArg == "-ANGULARDEFLECTION")
9521     {
9522       if (++anArgIter >= theArgsNb)
9523       {
9524         std::cout << "Error: wrong syntax at " << anArg << "\n";
9525         return 1;
9526       }
9527       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9528       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9529     }
9530     else if (anArg == "-AUTOTR"
9531           || anArg == "-AUTOTRIANG"
9532           || anArg == "-AUTOTRIANGULATION")
9533     {
9534       if (++anArgIter >= theArgsNb)
9535       {
9536         std::cout << "Error: wrong syntax at " << anArg << "\n";
9537         return 1;
9538       }
9539       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9540       aValue.LowerCase();
9541       if (aValue == "on"
9542        || aValue == "1")
9543       {
9544         aDefParams->SetAutoTriangulation (Standard_True);
9545       }
9546       else if (aValue == "off"
9547             || aValue == "0")
9548       {
9549         aDefParams->SetAutoTriangulation (Standard_False);
9550       }
9551     }
9552     else
9553     {
9554       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9555     }
9556   }
9557
9558   return 0;
9559 }
9560
9561 //! Auxiliary method
9562 inline void addLight (const Handle(V3d_Light)& theLightNew,
9563                       const Graphic3d_ZLayerId theLayer,
9564                       const Standard_Boolean   theIsGlobal)
9565 {
9566   if (theLightNew.IsNull())
9567   {
9568     return;
9569   }
9570
9571   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9572   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
9573   {
9574     aViewer->AddLight (theLightNew);
9575     if (theIsGlobal)
9576     {
9577       aViewer->SetLightOn (theLightNew);
9578     }
9579     else
9580     {
9581       ViewerTest::CurrentView()->SetLightOn (theLightNew);
9582     }
9583   }
9584   else
9585   {
9586     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
9587     if (aSettings.Lights().IsNull())
9588     {
9589       aSettings.SetLights (new Graphic3d_LightSet());
9590     }
9591     aSettings.Lights()->Add (theLightNew);
9592     aViewer->SetZLayerSettings (theLayer, aSettings);
9593   }
9594 }
9595
9596 //! Auxiliary method
9597 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9598 {
9599   TCollection_AsciiString anArgNextCase (theArgNext);
9600   anArgNextCase.UpperCase();
9601   if (anArgNextCase.Length() > 5
9602    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9603   {
9604     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9605   }
9606   else
9607   {
9608     return theArgNext.IntegerValue();
9609   }
9610 }
9611
9612 //===============================================================================================
9613 //function : VLight
9614 //purpose  :
9615 //===============================================================================================
9616 static int VLight (Draw_Interpretor& theDi,
9617                    Standard_Integer  theArgsNb,
9618                    const char**      theArgVec)
9619 {
9620   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9621   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9622   if (aView.IsNull()
9623    || aViewer.IsNull())
9624   {
9625     std::cerr << "No active viewer!\n";
9626     return 1;
9627   }
9628
9629   Standard_Real anXYZ[3]   = {};
9630   Standard_Real anAtten[2] = {};
9631   if (theArgsNb < 2)
9632   {
9633     // print lights info
9634     Standard_Integer aLightId = 0;
9635     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9636     {
9637       Handle(V3d_Light) aLight = aLightIter.Value();
9638       const Quantity_Color aColor = aLight->Color();
9639       theDi << "Light #" << aLightId
9640             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
9641             << " [" << aLight->GetId() << "]" << "\n";
9642       switch (aLight->Type())
9643       {
9644         case V3d_AMBIENT:
9645         {
9646           theDi << "  Type:       Ambient\n";
9647           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9648           break;
9649         }
9650         case V3d_DIRECTIONAL:
9651         {
9652           theDi << "  Type:       Directional\n";
9653           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9654           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9655           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9656           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9657           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9658           break;
9659         }
9660         case V3d_POSITIONAL:
9661         {
9662           theDi << "  Type:       Positional\n";
9663           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9664           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9665           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9666           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9667           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9668           aLight->Attenuation (anAtten[0], anAtten[1]);
9669           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9670           break;
9671         }
9672         case V3d_SPOT:
9673         {
9674           theDi << "  Type:       Spot\n";
9675           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9676           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9677           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9678           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9679           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9680           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9681           aLight->Attenuation (anAtten[0], anAtten[1]);
9682           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9683           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
9684           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
9685           break;
9686         }
9687         default:
9688         {
9689           theDi << "  Type:       UNKNOWN\n";
9690           break;
9691         }
9692       }
9693       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
9694     }
9695   }
9696
9697   Handle(V3d_Light) aLightNew;
9698   Handle(V3d_Light) aLightOld;
9699   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
9700   Standard_Boolean  isGlobal = Standard_True;
9701   Standard_Boolean  toCreate = Standard_False;
9702   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9703   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9704   {
9705     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9706
9707     TCollection_AsciiString aName, aValue;
9708     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9709     TCollection_AsciiString anArgCase (anArg);
9710     anArgCase.UpperCase();
9711     if (anUpdateTool.parseRedrawMode (anArg))
9712     {
9713       continue;
9714     }
9715
9716     if (anArgCase.IsEqual ("NEW")
9717      || anArgCase.IsEqual ("ADD")
9718      || anArgCase.IsEqual ("CREATE")
9719      || anArgCase.IsEqual ("-NEW")
9720      || anArgCase.IsEqual ("-ADD")
9721      || anArgCase.IsEqual ("-CREATE"))
9722     {
9723       toCreate = Standard_True;
9724     }
9725     else if (anArgCase.IsEqual ("-LAYER")
9726           || anArgCase.IsEqual ("-ZLAYER"))
9727     {
9728       if (++anArgIt >= theArgsNb)
9729       {
9730         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9731         return 1;
9732       }
9733
9734       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
9735       aValStr.LowerCase();
9736       if (aValStr == "default"
9737        || aValStr == "def")
9738       {
9739         aLayer = Graphic3d_ZLayerId_Default;
9740       }
9741       else if (aValStr == "top")
9742       {
9743         aLayer = Graphic3d_ZLayerId_Top;
9744       }
9745       else if (aValStr == "topmost")
9746       {
9747         aLayer = Graphic3d_ZLayerId_Topmost;
9748       }
9749       else if (aValStr == "toposd"
9750             || aValStr == "osd")
9751       {
9752         aLayer = Graphic3d_ZLayerId_TopOSD;
9753       }
9754       else if (aValStr == "botosd"
9755             || aValStr == "bottom")
9756       {
9757         aLayer = Graphic3d_ZLayerId_BotOSD;
9758       }
9759       else if (aValStr.IsIntegerValue())
9760       {
9761         aLayer = Draw::Atoi (theArgVec[anArgIt]);
9762       }
9763       else
9764       {
9765         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
9766         return 1;
9767       }
9768     }
9769     else if (anArgCase.IsEqual ("GLOB")
9770           || anArgCase.IsEqual ("GLOBAL")
9771           || anArgCase.IsEqual ("-GLOB")
9772           || anArgCase.IsEqual ("-GLOBAL"))
9773     {
9774       isGlobal = Standard_True;
9775     }
9776     else if (anArgCase.IsEqual ("LOC")
9777           || anArgCase.IsEqual ("LOCAL")
9778           || anArgCase.IsEqual ("-LOC")
9779           || anArgCase.IsEqual ("-LOCAL"))
9780     {
9781       isGlobal = Standard_False;
9782     }
9783     else if (anArgCase.IsEqual ("DEF")
9784           || anArgCase.IsEqual ("DEFAULTS")
9785           || anArgCase.IsEqual ("-DEF")
9786           || anArgCase.IsEqual ("-DEFAULTS"))
9787     {
9788       toCreate = Standard_False;
9789       aViewer->SetDefaultLights();
9790     }
9791     else if (anArgCase.IsEqual ("CLR")
9792           || anArgCase.IsEqual ("CLEAR")
9793           || anArgCase.IsEqual ("-CLR")
9794           || anArgCase.IsEqual ("-CLEAR"))
9795     {
9796       toCreate = Standard_False;
9797
9798       TColStd_SequenceOfInteger aLayers;
9799       aViewer->GetAllZLayers (aLayers);
9800       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9801       {
9802         if (aLayeriter.Value() == aLayer
9803          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9804         {
9805           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9806           aSettings.SetLights (Handle(Graphic3d_LightSet)());
9807           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9808           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9809           {
9810             break;
9811           }
9812         }
9813       }
9814
9815       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9816       {
9817         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
9818         {
9819           Handle(V3d_Light) aLight = aLightIter.Value();
9820           aViewer->DelLight (aLight);
9821           aLightIter = aView->ActiveLightIterator();
9822         }
9823       }
9824     }
9825     else if (anArgCase.IsEqual ("AMB")
9826           || anArgCase.IsEqual ("AMBIENT")
9827           || anArgCase.IsEqual ("AMBLIGHT"))
9828     {
9829       if (!toCreate)
9830       {
9831         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9832         return 1;
9833       }
9834
9835       addLight (aLightNew, aLayer, isGlobal);
9836       toCreate  = Standard_False;
9837       aLightNew = new V3d_AmbientLight();
9838     }
9839     else if (anArgCase.IsEqual ("DIRECTIONAL")
9840           || anArgCase.IsEqual ("DIRLIGHT"))
9841     {
9842       if (!toCreate)
9843       {
9844         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9845         return 1;
9846       }
9847
9848       addLight (aLightNew, aLayer, isGlobal);
9849       toCreate  = Standard_False;
9850       aLightNew = new V3d_DirectionalLight();
9851     }
9852     else if (anArgCase.IsEqual ("SPOT")
9853           || anArgCase.IsEqual ("SPOTLIGHT"))
9854     {
9855       if (!toCreate)
9856       {
9857         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9858         return 1;
9859       }
9860
9861       addLight (aLightNew, aLayer, isGlobal);
9862       toCreate  = Standard_False;
9863       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
9864     }
9865     else if (anArgCase.IsEqual ("POSLIGHT")
9866           || anArgCase.IsEqual ("POSITIONAL"))
9867     {
9868       if (!toCreate)
9869       {
9870         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9871         return 1;
9872       }
9873
9874       addLight (aLightNew, aLayer, isGlobal);
9875       toCreate  = Standard_False;
9876       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
9877     }
9878     else if (anArgCase.IsEqual ("CHANGE")
9879           || anArgCase.IsEqual ("-CHANGE"))
9880     {
9881       if (++anArgIt >= theArgsNb)
9882       {
9883         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9884         return 1;
9885       }
9886
9887       addLight (aLightNew, aLayer, isGlobal);
9888       aLightNew.Nullify();
9889       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
9890       Standard_Integer aLightIt = 0;
9891       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9892       {
9893         if (aLightIt == aLightId)
9894         {
9895           aLightOld = aLightIter.Value();
9896           break;
9897         }
9898       }
9899
9900       if (aLightOld.IsNull())
9901       {
9902         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
9903         return 1;
9904       }
9905     }
9906     else if (anArgCase.IsEqual ("DEL")
9907           || anArgCase.IsEqual ("DELETE")
9908           || anArgCase.IsEqual ("-DEL")
9909           || anArgCase.IsEqual ("-DELETE"))
9910     {
9911       Handle(V3d_Light) aLightDel;
9912       if (++anArgIt >= theArgsNb)
9913       {
9914         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9915         return 1;
9916       }
9917
9918       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9919       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
9920       Standard_Integer aLightIt = 0;
9921       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9922       {
9923         aLightDel = aLightIter.Value();
9924         if (aLightIt == aLightDelId)
9925         {
9926           break;
9927         }
9928       }
9929       if (aLightDel.IsNull())
9930       {
9931         continue;
9932       }
9933
9934       TColStd_SequenceOfInteger aLayers;
9935       aViewer->GetAllZLayers (aLayers);
9936       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9937       {
9938         if (aLayeriter.Value() == aLayer
9939          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9940         {
9941           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9942           if (!aSettings.Lights().IsNull())
9943           {
9944             aSettings.Lights()->Remove (aLightDel);
9945             if (aSettings.Lights()->IsEmpty())
9946             {
9947               aSettings.SetLights (Handle(Graphic3d_LightSet)());
9948             }
9949           }
9950           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9951           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9952           {
9953             break;
9954           }
9955         }
9956       }
9957
9958       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9959       {
9960         aViewer->DelLight (aLightDel);
9961       }
9962     }
9963     else if (anArgCase.IsEqual ("COLOR")
9964           || anArgCase.IsEqual ("COLOUR")
9965           || anArgCase.IsEqual ("-COLOR")
9966           || anArgCase.IsEqual ("-COLOUR"))
9967     {
9968       if (++anArgIt >= theArgsNb
9969        || aLightCurr.IsNull())
9970       {
9971         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9972         return 1;
9973       }
9974
9975       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9976       anArgNext.UpperCase();
9977       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
9978       aLightCurr->SetColor (aColor);
9979     }
9980     else if (anArgCase.IsEqual ("POS")
9981           || anArgCase.IsEqual ("POSITION")
9982           || anArgCase.IsEqual ("-POS")
9983           || anArgCase.IsEqual ("-POSITION"))
9984     {
9985       if ((anArgIt + 3) >= theArgsNb
9986        || aLightCurr.IsNull()
9987        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9988         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9989       {
9990         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9991         return 1;
9992       }
9993
9994       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9995       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9996       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9997       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9998     }
9999     else if (anArgCase.IsEqual ("DIR")
10000           || anArgCase.IsEqual ("DIRECTION")
10001           || anArgCase.IsEqual ("-DIR")
10002           || anArgCase.IsEqual ("-DIRECTION"))
10003     {
10004       if ((anArgIt + 3) >= theArgsNb
10005        || aLightCurr.IsNull()
10006        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
10007         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10008       {
10009         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10010         return 1;
10011       }
10012
10013       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10014       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10015       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10016       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
10017     }
10018     else if (anArgCase.IsEqual ("SM")
10019           || anArgCase.IsEqual ("SMOOTHNESS")
10020           || anArgCase.IsEqual ("-SM")
10021           || anArgCase.IsEqual ("-SMOOTHNESS"))
10022     {
10023       if (++anArgIt >= theArgsNb
10024        || aLightCurr.IsNull())
10025       {
10026         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10027         return 1;
10028       }
10029
10030       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10031       if (Abs (aSmoothness) <= ShortRealEpsilon())
10032       {
10033         aLightCurr->SetIntensity (1.f);
10034       }
10035       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
10036       {
10037         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
10038       }
10039       else
10040       {
10041         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
10042         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
10043       }
10044
10045       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
10046       {
10047         aLightCurr->SetSmoothRadius (aSmoothness);
10048       }
10049       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
10050       {
10051         aLightCurr->SetSmoothAngle (aSmoothness);
10052       }
10053     }
10054     else if (anArgCase.IsEqual ("INT")
10055           || anArgCase.IsEqual ("INTENSITY")
10056           || anArgCase.IsEqual ("-INT")
10057           || anArgCase.IsEqual ("-INTENSITY"))
10058     {
10059       if (++anArgIt >= theArgsNb
10060        || aLightCurr.IsNull())
10061       {
10062         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10063         return 1;
10064       }
10065
10066       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10067       aLightCurr->SetIntensity (aIntensity);
10068     }
10069     else if (anArgCase.IsEqual ("ANG")
10070           || anArgCase.IsEqual ("ANGLE")
10071           || anArgCase.IsEqual ("-ANG")
10072           || anArgCase.IsEqual ("-ANGLE"))
10073     {
10074       if (++anArgIt >= theArgsNb
10075        || aLightCurr.IsNull()
10076        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10077       {
10078         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10079         return 1;
10080       }
10081
10082       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10083       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
10084     }
10085     else if (anArgCase.IsEqual ("CONSTATTEN")
10086           || anArgCase.IsEqual ("CONSTATTENUATION")
10087           || anArgCase.IsEqual ("-CONSTATTEN")
10088           || anArgCase.IsEqual ("-CONSTATTENUATION"))
10089     {
10090       if (++anArgIt >= theArgsNb
10091        || aLightCurr.IsNull()
10092        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10093         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10094       {
10095         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10096         return 1;
10097       }
10098
10099       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10100       anAtten[0] = Atof (theArgVec[anArgIt]);
10101       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10102     }
10103     else if (anArgCase.IsEqual ("LINATTEN")
10104           || anArgCase.IsEqual ("LINEARATTEN")
10105           || anArgCase.IsEqual ("LINEARATTENUATION")
10106           || anArgCase.IsEqual ("-LINATTEN")
10107           || anArgCase.IsEqual ("-LINEARATTEN")
10108           || anArgCase.IsEqual ("-LINEARATTENUATION"))
10109     {
10110       if (++anArgIt >= theArgsNb
10111        || aLightCurr.IsNull()
10112        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10113         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10114       {
10115         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10116         return 1;
10117       }
10118
10119       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10120       anAtten[1] = Atof (theArgVec[anArgIt]);
10121       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10122     }
10123     else if (anArgCase.IsEqual ("EXP")
10124           || anArgCase.IsEqual ("EXPONENT")
10125           || anArgCase.IsEqual ("SPOTEXP")
10126           || anArgCase.IsEqual ("SPOTEXPONENT")
10127           || anArgCase.IsEqual ("-EXP")
10128           || anArgCase.IsEqual ("-EXPONENT")
10129           || anArgCase.IsEqual ("-SPOTEXP")
10130           || anArgCase.IsEqual ("-SPOTEXPONENT"))
10131     {
10132       if (++anArgIt >= theArgsNb
10133        || aLightCurr.IsNull()
10134        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10135       {
10136         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10137         return 1;
10138       }
10139
10140       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
10141     }
10142     else if (anArgCase.IsEqual ("HEAD")
10143           || anArgCase.IsEqual ("HEADLIGHT")
10144           || anArgCase.IsEqual ("-HEAD")
10145           || anArgCase.IsEqual ("-HEADLIGHT"))
10146     {
10147       if (aLightCurr.IsNull()
10148        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
10149       {
10150         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10151         return 1;
10152       }
10153
10154       Standard_Boolean isHeadLight = Standard_True;
10155       if (anArgIt + 1 < theArgsNb
10156        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
10157       {
10158         ++anArgIt;
10159       }
10160       aLightCurr->SetHeadlight (isHeadLight);
10161     }
10162     else
10163     {
10164       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
10165     }
10166   }
10167
10168   addLight (aLightNew, aLayer, isGlobal);
10169   return 0;
10170 }
10171
10172 //! Read Graphic3d_RenderingParams::PerfCounters flag.
10173 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10174                                             Standard_Boolean& theToReset,
10175                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10176                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10177 {
10178   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10179   TCollection_AsciiString aVal = theValue;
10180   Standard_Boolean toReverse = Standard_False;
10181   if (aVal == "none")
10182   {
10183     theToReset = Standard_True;
10184     return Standard_True;
10185   }
10186   else if (aVal.StartsWith ("-"))
10187   {
10188     toReverse = Standard_True;
10189     aVal = aVal.SubString (2, aVal.Length());
10190   }
10191   else if (aVal.StartsWith ("no"))
10192   {
10193     toReverse = Standard_True;
10194     aVal = aVal.SubString (3, aVal.Length());
10195   }
10196   else if (aVal.StartsWith ("+"))
10197   {
10198     aVal = aVal.SubString (2, aVal.Length());
10199   }
10200   else
10201   {
10202     theToReset = Standard_True;
10203   }
10204
10205   if (     aVal == "fps"
10206         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
10207   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
10208   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
10209   else if (aVal == "structs"
10210         || aVal == "structures"
10211         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
10212   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
10213   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
10214   else if (aVal == "tris"
10215         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
10216   else if (aVal == "pnts"
10217         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
10218   else if (aVal == "mem"
10219         || aVal == "gpumem"
10220         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
10221   else if (aVal == "skipimmediate"
10222         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
10223   else if (aVal == "frametime"
10224         || aVal == "frametimers"
10225         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
10226   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
10227   else if (aVal == "extended"
10228         || aVal == "verbose"
10229         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
10230   else if (aVal == "full"
10231         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
10232   else
10233   {
10234     return Standard_False;
10235   }
10236
10237   if (toReverse)
10238   {
10239     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
10240   }
10241   else
10242   {
10243     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
10244   }
10245   return Standard_True;
10246 }
10247
10248 //! Read Graphic3d_RenderingParams::PerfCounters flags.
10249 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
10250                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
10251 {
10252   TCollection_AsciiString aValue = theValue;
10253   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
10254   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
10255   Standard_Boolean toReset = Standard_False;
10256   for (;;)
10257   {
10258     Standard_Integer aSplitPos = aValue.Search ("|");
10259     if (aSplitPos <= 0)
10260     {
10261       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
10262       {
10263         return Standard_False;
10264       }
10265       if (toReset)
10266       {
10267         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
10268       }
10269       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
10270       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
10271       return Standard_True;
10272     }
10273
10274     if (aSplitPos > 1)
10275     {
10276       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
10277       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
10278       {
10279         return Standard_False;
10280       }
10281     }
10282     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
10283   }
10284 }
10285
10286 //=======================================================================
10287 //function : VRenderParams
10288 //purpose  : Enables/disables rendering features
10289 //=======================================================================
10290
10291 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
10292                                        Standard_Integer  theArgNb,
10293                                        const char**      theArgVec)
10294 {
10295   Handle(V3d_View) aView = ViewerTest::CurrentView();
10296   if (aView.IsNull())
10297   {
10298     std::cerr << "Error: no active viewer!\n";
10299     return 1;
10300   }
10301
10302   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
10303   TCollection_AsciiString aCmdName (theArgVec[0]);
10304   aCmdName.LowerCase();
10305   if (aCmdName == "vraytrace")
10306   {
10307     if (theArgNb == 1)
10308     {
10309       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
10310       return 0;
10311     }
10312     else if (theArgNb == 2)
10313     {
10314       TCollection_AsciiString aValue (theArgVec[1]);
10315       aValue.LowerCase();
10316       if (aValue == "on"
10317        || aValue == "1")
10318       {
10319         aParams.Method = Graphic3d_RM_RAYTRACING;
10320         aView->Redraw();
10321         return 0;
10322       }
10323       else if (aValue == "off"
10324             || aValue == "0")
10325       {
10326         aParams.Method = Graphic3d_RM_RASTERIZATION;
10327         aView->Redraw();
10328         return 0;
10329       }
10330       else
10331       {
10332         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
10333         return 1;
10334       }
10335     }
10336     else
10337     {
10338       std::cout << "Error: wrong number of arguments\n";
10339       return 1;
10340     }
10341   }
10342
10343   if (theArgNb < 2)
10344   {
10345     theDI << "renderMode:  ";
10346     switch (aParams.Method)
10347     {
10348       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10349       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
10350     }
10351     theDI << "\n";
10352     theDI << "transparency:  ";
10353     switch (aParams.TransparencyMethod)
10354     {
10355       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
10356       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
10357                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
10358     }
10359     theDI << "\n";
10360     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
10361     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
10362     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
10363     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
10364     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
10365     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
10366     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
10367     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
10368     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
10369     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
10370     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
10371     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
10372     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
10373     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
10374     theDI << "shadingModel: ";
10375     switch (aView->ShadingModel())
10376     {
10377       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
10378       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
10379       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
10380       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
10381       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
10382     }
10383     {
10384       theDI << "perfCounters:";
10385       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
10386       {
10387         theDI << " fps";
10388       }
10389       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
10390       {
10391         theDI << " cpu";
10392       }
10393       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
10394       {
10395         theDI << " structs";
10396       }
10397       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
10398       {
10399         theDI << " groups";
10400       }
10401       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
10402       {
10403         theDI << " arrays";
10404       }
10405       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
10406       {
10407         theDI << " tris";
10408       }
10409       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
10410       {
10411         theDI << " pnts";
10412       }
10413       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
10414       {
10415         theDI << " gpumem";
10416       }
10417       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
10418       {
10419         theDI << " frameTime";
10420       }
10421       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
10422       {
10423         theDI << " skipimmediate";
10424       }
10425       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
10426       {
10427         theDI << " none";
10428       }
10429       theDI << "\n";
10430     }
10431     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
10432     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
10433     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
10434                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
10435                                                                                                                     "noUpdate") << "\n";
10436     theDI << "\n";
10437     return 0;
10438   }
10439
10440   Standard_Boolean toPrint = Standard_False;
10441   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10442   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10443   {
10444     Standard_CString        anArg (theArgVec[anArgIter]);
10445     TCollection_AsciiString aFlag (anArg);
10446     aFlag.LowerCase();
10447     if (anUpdateTool.parseRedrawMode (aFlag))
10448     {
10449       continue;
10450     }
10451     else if (aFlag == "-echo"
10452           || aFlag == "-print")
10453     {
10454       toPrint = Standard_True;
10455       anUpdateTool.Invalidate();
10456     }
10457     else if (aFlag == "-mode"
10458           || aFlag == "-rendermode"
10459           || aFlag == "-render_mode")
10460     {
10461       if (toPrint)
10462       {
10463         switch (aParams.Method)
10464         {
10465           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10466           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
10467         }
10468         continue;
10469       }
10470       else
10471       {
10472         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10473         return 1;
10474       }
10475     }
10476     else if (aFlag == "-ray"
10477           || aFlag == "-raytrace")
10478     {
10479       if (toPrint)
10480       {
10481         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
10482         continue;
10483       }
10484
10485       aParams.Method = Graphic3d_RM_RAYTRACING;
10486     }
10487     else if (aFlag == "-rast"
10488           || aFlag == "-raster"
10489           || aFlag == "-rasterization")
10490     {
10491       if (toPrint)
10492       {
10493         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
10494         continue;
10495       }
10496
10497       aParams.Method = Graphic3d_RM_RASTERIZATION;
10498     }
10499     else if (aFlag == "-msaa")
10500     {
10501       if (toPrint)
10502       {
10503         theDI << aParams.NbMsaaSamples << " ";
10504         continue;
10505       }
10506       else if (++anArgIter >= theArgNb)
10507       {
10508         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10509         return 1;
10510       }
10511
10512       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
10513       if (aNbSamples < 0)
10514       {
10515         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
10516         return 1;
10517       }
10518       else
10519       {
10520         aParams.NbMsaaSamples = aNbSamples;
10521       }
10522     }
10523     else if (aFlag == "-oit")
10524     {
10525       if (toPrint)
10526       {
10527         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
10528         {
10529           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
10530         }
10531         else
10532         {
10533           theDI << "off" << " ";
10534         }
10535         continue;
10536       }
10537       else if (++anArgIter >= theArgNb)
10538       {
10539         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10540         return 1;
10541       }
10542
10543       TCollection_AsciiString aParam = theArgVec[anArgIter];
10544       aParam.LowerCase();
10545       if (aParam.IsRealValue())
10546       {
10547         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10548         if (aWeight < 0.f || aWeight > 1.f)
10549         {
10550           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
10551           return 1;
10552         }
10553
10554         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
10555         aParams.OitDepthFactor     = aWeight;
10556       }
10557       else if (aParam == "off")
10558       {
10559         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
10560       }
10561       else
10562       {
10563         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10564         return 1;
10565       }
10566     }
10567     else if (aFlag == "-depthprepass")
10568     {
10569       if (toPrint)
10570       {
10571         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
10572         continue;
10573       }
10574       aParams.ToEnableDepthPrepass = Standard_True;
10575       if (anArgIter + 1 < theArgNb
10576        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
10577       {
10578         ++anArgIter;
10579       }
10580     }
10581     else if (aFlag == "-samplealphatocoverage"
10582           || aFlag == "-alphatocoverage")
10583     {
10584       if (toPrint)
10585       {
10586         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
10587         continue;
10588       }
10589       aParams.ToEnableAlphaToCoverage = Standard_True;
10590       if (anArgIter + 1 < theArgNb
10591        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
10592       {
10593         ++anArgIter;
10594       }
10595     }
10596     else if (aFlag == "-rendscale"
10597           || aFlag == "-renderscale"
10598           || aFlag == "-renderresolutionscale")
10599     {
10600       if (toPrint)
10601       {
10602         theDI << aParams.RenderResolutionScale << " ";
10603         continue;
10604       }
10605       else if (++anArgIter >= theArgNb)
10606       {
10607         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10608         return 1;
10609       }
10610
10611       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
10612       if (aScale < 0.01)
10613       {
10614         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
10615         return 1;
10616       }
10617       else
10618       {
10619         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
10620       }
10621     }
10622     else if (aFlag == "-raydepth"
10623           || aFlag == "-ray_depth")
10624     {
10625       if (toPrint)
10626       {
10627         theDI << aParams.RaytracingDepth << " ";
10628         continue;
10629       }
10630       else if (++anArgIter >= theArgNb)
10631       {
10632         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10633         return 1;
10634       }
10635
10636       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
10637
10638       // We allow RaytracingDepth be more than 10 in case of GI enabled
10639       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
10640       {
10641         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
10642         return 1;
10643       }
10644       else
10645       {
10646         aParams.RaytracingDepth = aDepth;
10647       }
10648     }
10649     else if (aFlag == "-shad"
10650           || aFlag == "-shadows")
10651     {
10652       if (toPrint)
10653       {
10654         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
10655         continue;
10656       }
10657
10658       Standard_Boolean toEnable = Standard_True;
10659       if (++anArgIter < theArgNb
10660       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10661       {
10662         --anArgIter;
10663       }
10664       aParams.IsShadowEnabled = toEnable;
10665     }
10666     else if (aFlag == "-refl"
10667           || aFlag == "-reflections")
10668     {
10669       if (toPrint)
10670       {
10671         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10672         continue;
10673       }
10674
10675       Standard_Boolean toEnable = Standard_True;
10676       if (++anArgIter < theArgNb
10677       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10678       {
10679         --anArgIter;
10680       }
10681       aParams.IsReflectionEnabled = toEnable;
10682     }
10683     else if (aFlag == "-fsaa")
10684     {
10685       if (toPrint)
10686       {
10687         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10688         continue;
10689       }
10690
10691       Standard_Boolean toEnable = Standard_True;
10692       if (++anArgIter < theArgNb
10693       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10694       {
10695         --anArgIter;
10696       }
10697       aParams.IsAntialiasingEnabled = toEnable;
10698     }
10699     else if (aFlag == "-gleam")
10700     {
10701       if (toPrint)
10702       {
10703         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10704         continue;
10705       }
10706
10707       Standard_Boolean toEnable = Standard_True;
10708       if (++anArgIter < theArgNb
10709       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10710       {
10711         --anArgIter;
10712       }
10713       aParams.IsTransparentShadowEnabled = toEnable;
10714     }
10715     else if (aFlag == "-gi")
10716     {
10717       if (toPrint)
10718       {
10719         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10720         continue;
10721       }
10722
10723       Standard_Boolean toEnable = Standard_True;
10724       if (++anArgIter < theArgNb
10725       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10726       {
10727         --anArgIter;
10728       }
10729       aParams.IsGlobalIlluminationEnabled = toEnable;
10730       if (!toEnable)
10731       {
10732         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10733       }
10734     }
10735     else if (aFlag == "-blockedrng"
10736           || aFlag == "-brng")
10737     {
10738       if (toPrint)
10739       {
10740         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10741         continue;
10742       }
10743
10744       Standard_Boolean toEnable = Standard_True;
10745       if (++anArgIter < theArgNb
10746         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10747       {
10748         --anArgIter;
10749       }
10750       aParams.CoherentPathTracingMode = toEnable;
10751     }
10752     else if (aFlag == "-maxrad")
10753     {
10754       if (toPrint)
10755       {
10756         theDI << aParams.RadianceClampingValue << " ";
10757         continue;
10758       }
10759       else if (++anArgIter >= theArgNb)
10760       {
10761         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10762         return 1;
10763       }
10764
10765       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10766       if (!aMaxRadStr.IsRealValue())
10767       {
10768         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10769         return 1;
10770       }
10771
10772       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10773       if (aMaxRadiance <= 0.0)
10774       {
10775         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10776         return 1;
10777       }
10778       else
10779       {
10780         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
10781       }
10782     }
10783     else if (aFlag == "-iss")
10784     {
10785       if (toPrint)
10786       {
10787         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
10788         continue;
10789       }
10790
10791       Standard_Boolean toEnable = Standard_True;
10792       if (++anArgIter < theArgNb
10793         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10794       {
10795         --anArgIter;
10796       }
10797       aParams.AdaptiveScreenSampling = toEnable;
10798     }
10799     else if (aFlag == "-issd")
10800     {
10801       if (toPrint)
10802       {
10803         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
10804         continue;
10805       }
10806
10807       Standard_Boolean toEnable = Standard_True;
10808       if (++anArgIter < theArgNb
10809         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10810       {
10811         --anArgIter;
10812       }
10813       aParams.ShowSamplingTiles = toEnable;
10814     }
10815     else if (aFlag == "-nbtiles")
10816     {
10817       if (toPrint)
10818       {
10819         theDI << aParams.NbRayTracingTiles << " ";
10820         continue;
10821       }
10822       else if (++anArgIter >= theArgNb)
10823       {
10824         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10825         return 1;
10826       }
10827
10828       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
10829
10830       if (aNbTiles < 64)
10831       {
10832         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
10833         std::cerr << "Specify value in range [64, 1024].\n";
10834         return 1;
10835       }
10836       else
10837       {
10838         aParams.NbRayTracingTiles = aNbTiles;
10839       }
10840     }
10841     else if (aFlag == "-env")
10842     {
10843       if (toPrint)
10844       {
10845         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
10846         continue;
10847       }
10848
10849       Standard_Boolean toEnable = Standard_True;
10850       if (++anArgIter < theArgNb
10851         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10852       {
10853         --anArgIter;
10854       }
10855       aParams.UseEnvironmentMapBackground = toEnable;
10856     }
10857     else if (aFlag == "-twoside")
10858     {
10859       if (toPrint)
10860       {
10861         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
10862         continue;
10863       }
10864
10865       Standard_Boolean toEnable = Standard_True;
10866       if (++anArgIter < theArgNb
10867         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10868       {
10869         --anArgIter;
10870       }
10871       aParams.TwoSidedBsdfModels = toEnable;
10872     }
10873     else if (aFlag == "-shademodel"
10874           || aFlag == "-shadingmodel"
10875           || aFlag == "-shading")
10876     {
10877       if (toPrint)
10878       {
10879         switch (aView->ShadingModel())
10880         {
10881           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
10882           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
10883           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
10884           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
10885           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
10886         }
10887         continue;
10888       }
10889
10890       if (++anArgIter >= theArgNb)
10891       {
10892         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10893       }
10894
10895       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
10896       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
10897        && aModel != Graphic3d_TOSM_DEFAULT)
10898       {
10899         aView->SetShadingModel (aModel);
10900       }
10901       else
10902       {
10903         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
10904         return 1;
10905       }
10906     }
10907     else if (aFlag == "-resolution")
10908     {
10909       if (++anArgIter >= theArgNb)
10910       {
10911         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10912         return 1;
10913       }
10914
10915       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
10916       if (aResolution.IsIntegerValue())
10917       {
10918         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
10919       }
10920       else
10921       {
10922         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10923         return 1;
10924       }
10925     }
10926     else if (aFlag == "-rebuildglsl"
10927           || aFlag == "-rebuild")
10928     {
10929       if (toPrint)
10930       {
10931         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
10932         continue;
10933       }
10934
10935       Standard_Boolean toEnable = Standard_True;
10936       if (++anArgIter < theArgNb
10937           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10938       {
10939         --anArgIter;
10940       }
10941       aParams.RebuildRayTracingShaders = toEnable;
10942     }
10943     else if (aFlag == "-focal")
10944     {
10945       if (++anArgIter >= theArgNb)
10946       {
10947         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10948         return 1;
10949       }
10950
10951       TCollection_AsciiString aParam (theArgVec[anArgIter]);
10952       if (aParam.IsRealValue())
10953       {
10954         float aFocalDist = static_cast<float> (aParam.RealValue());
10955         if (aFocalDist < 0)
10956         {
10957           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10958           return 1;
10959         }
10960         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
10961       }
10962       else
10963       {
10964         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10965         return 1;
10966       }
10967     }
10968     else if (aFlag == "-aperture")
10969     {
10970       if (++anArgIter >= theArgNb)
10971       {
10972         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10973         return 1;
10974       }
10975
10976       TCollection_AsciiString aParam(theArgVec[anArgIter]);
10977       if (aParam.IsRealValue())
10978       {
10979         float aApertureSize = static_cast<float> (aParam.RealValue());
10980         if (aApertureSize < 0)
10981         {
10982           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10983           return 1;
10984         }
10985         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
10986       }
10987       else
10988       {
10989         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10990         return 1;
10991       }
10992     }
10993     else if (aFlag == "-exposure")
10994     {
10995       if (++anArgIter >= theArgNb)
10996       {
10997         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10998         return 1;
10999       }
11000
11001       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
11002       if (anExposure.IsRealValue())
11003       {
11004         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
11005       }
11006       else
11007       {
11008         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11009         return 1;
11010       }
11011     }
11012     else if (aFlag == "-whitepoint")
11013     {
11014       if (++anArgIter >= theArgNb)
11015       {
11016         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11017         return 1;
11018       }
11019
11020       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
11021       if (aWhitePoint.IsRealValue())
11022       {
11023         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
11024       }
11025       else
11026       {
11027         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11028         return 1;
11029       }
11030     }
11031     else if (aFlag == "-tonemapping")
11032     {
11033       if (++anArgIter >= theArgNb)
11034       {
11035         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11036         return 1;
11037       }
11038
11039       TCollection_AsciiString aMode (theArgVec[anArgIter]);
11040       aMode.LowerCase();
11041
11042       if (aMode == "disabled")
11043       {
11044         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
11045       }
11046       else if (aMode == "filmic")
11047       {
11048         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
11049       }
11050       else
11051       {
11052         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11053         return 1;
11054       }
11055     }
11056     else if (aFlag == "-performancestats"
11057           || aFlag == "-performancecounters"
11058           || aFlag == "-perfstats"
11059           || aFlag == "-perfcounters"
11060           || aFlag == "-stats")
11061     {
11062       if (++anArgIter >= theArgNb)
11063       {
11064         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11065         return 1;
11066       }
11067
11068       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
11069       aFlagsStr.LowerCase();
11070       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
11071       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
11072       {
11073         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11074         return 1;
11075       }
11076       aView->ChangeRenderingParams().CollectedStats = aFlags;
11077       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
11078     }
11079     else if (aFlag == "-perfupdateinterval"
11080           || aFlag == "-statsupdateinterval")
11081     {
11082       if (++anArgIter >= theArgNb)
11083       {
11084         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11085         return 1;
11086       }
11087       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11088     }
11089     else if (aFlag == "-perfchart"
11090           || aFlag == "-statschart")
11091     {
11092       if (++anArgIter >= theArgNb)
11093       {
11094         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11095         return 1;
11096       }
11097       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
11098     }
11099     else if (aFlag == "-perfchartmax"
11100           || aFlag == "-statschartmax")
11101     {
11102       if (++anArgIter >= theArgNb)
11103       {
11104         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11105         return 1;
11106       }
11107       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11108     }
11109     else if (aFlag == "-frustumculling"
11110           || aFlag == "-culling")
11111     {
11112       if (toPrint)
11113       {
11114         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
11115                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
11116                                                                                                    "noUpdate") << " ";
11117         continue;
11118       }
11119
11120       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
11121       if (++anArgIter < theArgNb)
11122       {
11123         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
11124         aStateStr.LowerCase();
11125         bool toEnable = true;
11126         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
11127         {
11128           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
11129         }
11130         else if (aStateStr == "noupdate"
11131               || aStateStr == "freeze")
11132         {
11133           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
11134         }
11135         else
11136         {
11137           --anArgIter;
11138         }
11139       }
11140       aParams.FrustumCullingState = aState;
11141     }
11142     else
11143     {
11144       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
11145       return 1;
11146     }
11147   }
11148
11149   return 0;
11150 }
11151
11152 //=======================================================================
11153 //function : searchInfo
11154 //purpose  :
11155 //=======================================================================
11156 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
11157                                            const TCollection_AsciiString&              theKey)
11158 {
11159   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
11160   {
11161     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
11162     {
11163       return anIter.Value();
11164     }
11165   }
11166   return TCollection_AsciiString();
11167 }
11168
11169 //=======================================================================
11170 //function : VStatProfiler
11171 //purpose  :
11172 //=======================================================================
11173 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
11174                                        Standard_Integer  theArgNb,
11175                                        const char**      theArgVec)
11176 {
11177   Handle(V3d_View) aView = ViewerTest::CurrentView();
11178   if (aView.IsNull())
11179   {
11180     std::cerr << "Error: no active viewer!\n";
11181     return 1;
11182   }
11183
11184   Standard_Boolean toRedraw = Standard_True;
11185   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
11186   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
11187   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
11188   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11189   {
11190     Standard_CString        anArg (theArgVec[anArgIter]);
11191     TCollection_AsciiString aFlag (anArg);
11192     aFlag.LowerCase();
11193     if (aFlag == "-noredraw")
11194     {
11195       toRedraw = Standard_False;
11196     }
11197     else
11198     {
11199       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
11200       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11201       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
11202       else if (aFlag == "alllayers"
11203             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
11204       else if (aFlag == "allstructs"
11205             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
11206       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
11207       else if (aFlag == "allarrays"
11208             || aFlag == "fillarrays"
11209             || aFlag == "linearrays"
11210             || aFlag == "pointarrays"
11211             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11212       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
11213       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
11214       else if (aFlag == "geommem"
11215             || aFlag == "texturemem"
11216             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11217       else if (aFlag == "elapsedframe"
11218             || aFlag == "cpuframeaverage"
11219             || aFlag == "cpupickingaverage"
11220             || aFlag == "cpucullingaverage"
11221             || aFlag == "cpudynaverage"
11222             || aFlag == "cpuframemax"
11223             || aFlag == "cpupickingmax"
11224             || aFlag == "cpucullingmax"
11225             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11226       else
11227       {
11228         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
11229         continue;
11230       }
11231
11232       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
11233     }
11234   }
11235
11236   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
11237   {
11238     aView->ChangeRenderingParams().CollectedStats =
11239       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
11240
11241     if (toRedraw)
11242     {
11243       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
11244       aView->Redraw();
11245       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
11246     }
11247
11248     TColStd_IndexedDataMapOfStringString aDict;
11249     aView->StatisticInformation (aDict);
11250
11251     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
11252
11253     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11254     {
11255       Standard_CString        anArg(theArgVec[anArgIter]);
11256       TCollection_AsciiString aFlag(anArg);
11257       aFlag.LowerCase();
11258       if (aFlag == "fps")
11259       {
11260         theDI << searchInfo (aDict, "FPS") << " ";
11261       }
11262       else if (aFlag == "cpu")
11263       {
11264         theDI << searchInfo (aDict, "CPU FPS") << " ";
11265       }
11266       else if (aFlag == "alllayers")
11267       {
11268         theDI << searchInfo (aDict, "Layers") << " ";
11269       }
11270       else if (aFlag == "layers")
11271       {
11272         theDI << searchInfo (aDict, "Rendered layers") << " ";
11273       }
11274       else if (aFlag == "allstructs")
11275       {
11276         theDI << searchInfo (aDict, "Structs") << " ";
11277       }
11278       else if (aFlag == "structs")
11279       {
11280         theDI << searchInfo (aDict, "Rendered structs") << " ";
11281       }
11282       else if (aFlag == "groups")
11283       {
11284         theDI << searchInfo (aDict, "Rendered groups") << " ";
11285       }
11286       else if (aFlag == "allarrays")
11287       {
11288         theDI << searchInfo (aDict, "Rendered arrays") << " ";
11289       }
11290       else if (aFlag == "fillarrays")
11291       {
11292         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
11293       }
11294       else if (aFlag == "linearrays")
11295       {
11296         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
11297       }
11298       else if (aFlag == "pointarrays")
11299       {
11300         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
11301       }
11302       else if (aFlag == "textarrays")
11303       {
11304         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
11305       }
11306       else if (aFlag == "triangles")
11307       {
11308         theDI << searchInfo (aDict, "Rendered triangles") << " ";
11309       }
11310       else if (aFlag == "points")
11311       {
11312         theDI << searchInfo (aDict, "Rendered points") << " ";
11313       }
11314       else if (aFlag == "geommem")
11315       {
11316         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
11317       }
11318       else if (aFlag == "texturemem")
11319       {
11320         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
11321       }
11322       else if (aFlag == "framemem")
11323       {
11324         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
11325       }
11326       else if (aFlag == "elapsedframe")
11327       {
11328         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
11329       }
11330       else if (aFlag == "cpuframe_average")
11331       {
11332         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
11333       }
11334       else if (aFlag == "cpupicking_average")
11335       {
11336         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
11337       }
11338       else if (aFlag == "cpuculling_average")
11339       {
11340         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
11341       }
11342       else if (aFlag == "cpudyn_average")
11343       {
11344         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
11345       }
11346       else if (aFlag == "cpuframe_max")
11347       {
11348         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
11349       }
11350       else if (aFlag == "cpupicking_max")
11351       {
11352         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
11353       }
11354       else if (aFlag == "cpuculling_max")
11355       {
11356         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
11357       }
11358       else if (aFlag == "cpudyn_max")
11359       {
11360         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
11361       }
11362     }
11363   }
11364   else
11365   {
11366     if (toRedraw)
11367     {
11368       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
11369       aView->Redraw();
11370       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
11371     }
11372     theDI << "Statistic info:\n" << aView->StatisticInformation();
11373   }
11374   return 0;
11375 }
11376
11377 //=======================================================================
11378 //function : VProgressiveMode
11379 //purpose  :
11380 //=======================================================================
11381 #if defined(_WIN32)
11382 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
11383                                           Standard_Integer  /*theNbArgs*/,
11384                                           const char**      /*theArgs*/)
11385 {
11386   Handle(V3d_View) aView = ViewerTest::CurrentView();
11387   if (aView.IsNull())
11388   {
11389     std::cerr << "Error: no active viewer!\n";
11390     return 1;
11391   }
11392
11393   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
11394
11395   for (;;)
11396   {
11397     aView->Redraw();
11398
11399     Standard_Boolean toExit = Standard_False;
11400
11401     MSG aMsg;
11402     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
11403     {
11404       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
11405       {
11406         toExit = Standard_True;
11407       }
11408
11409       TranslateMessage (&aMsg);
11410       DispatchMessageW (&aMsg);
11411     }
11412
11413     if (toExit)
11414     {
11415       break;
11416     }
11417   }
11418
11419   return 0;
11420 }
11421 #endif
11422
11423 //=======================================================================
11424 //function : VXRotate
11425 //purpose  :
11426 //=======================================================================
11427 static Standard_Integer VXRotate (Draw_Interpretor& di,
11428                                    Standard_Integer argc,
11429                                    const char ** argv)
11430 {
11431   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
11432   if (aContext.IsNull())
11433   {
11434     di << argv[0] << "ERROR : use 'vinit' command before \n";
11435     return 1;
11436   }
11437   
11438   if (argc != 3)
11439   {
11440     di << "ERROR : Usage : " << argv[0] << " name angle\n";
11441     return 1;
11442   }
11443
11444   TCollection_AsciiString aName (argv[1]);
11445   Standard_Real anAngle = Draw::Atof (argv[2]);
11446
11447   // find object
11448   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
11449   Handle(AIS_InteractiveObject) anIObj;
11450   if (!aMap.Find2 (aName, anIObj))
11451   {
11452     di << "Use 'vdisplay' before\n";
11453     return 1;
11454   }
11455
11456   gp_Trsf aTransform;
11457   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
11458   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
11459
11460   aContext->SetLocation (anIObj, aTransform);
11461   aContext->UpdateCurrentViewer();
11462   return 0;
11463 }
11464
11465 //===============================================================================================
11466 //class   : ViewerTest_AISManipulator
11467 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
11468 //===============================================================================================
11469 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11470
11471 class ViewerTest_AISManipulator : public AIS_Manipulator
11472 {
11473 public:
11474
11475   ViewerTest_AISManipulator() : AIS_Manipulator()
11476   {
11477     GetMapOfAISManipulators().Add (this);
11478   }
11479
11480   virtual ~ViewerTest_AISManipulator()
11481   {
11482     GetMapOfAISManipulators().Remove (this);
11483   }
11484
11485   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11486 };
11487
11488 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
11489 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
11490
11491 //===============================================================================================
11492 //function : VManipulator
11493 //purpose  :
11494 //===============================================================================================
11495 static int VManipulator (Draw_Interpretor& theDi,
11496                          Standard_Integer  theArgsNb,
11497                          const char**      theArgVec)
11498 {
11499   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
11500   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
11501   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
11502   if (aView.IsNull()
11503    || aViewer.IsNull())
11504   {
11505     std::cerr << "No active viewer!\n";
11506     return 1;
11507   }
11508
11509   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
11510   Standard_Integer anArgIter = 1;
11511   for (; anArgIter < theArgsNb; ++anArgIter)
11512   {
11513     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
11514   }
11515
11516   ViewerTest_CmdParser aCmd;
11517   aCmd.AddDescription ("Manages manipulator for interactive objects:");
11518   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
11519   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
11520   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
11521   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
11522   aCmd.AddOption ("detach",         "...       - detach manipulator");
11523
11524   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
11525   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
11526   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
11527
11528   aCmd.AddOption ("move",   "... x y z - move object");
11529   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
11530   aCmd.AddOption ("scale",  "... factor - scale object");
11531
11532   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
11533   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
11534   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
11535   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
11536   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
11537   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
11538   aCmd.AddOption ("size",              "... size - set size of manipulator");
11539   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
11540
11541   aCmd.Parse (theArgsNb, theArgVec);
11542
11543   if (aCmd.HasOption ("help"))
11544   {
11545     theDi.PrintHelp (theArgVec[0]);
11546     return 0;
11547   }
11548
11549   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
11550
11551   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
11552
11553   if (aName.IsEmpty())
11554   {
11555     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
11556     return 1;
11557   }
11558
11559   // ----------------------------------
11560   // detach existing manipulator object
11561   // ----------------------------------
11562
11563   if (aCmd.HasOption ("detach"))
11564   {
11565     if (!aMapAIS.IsBound2 (aName))
11566     {
11567       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
11568       return 1;
11569     }
11570
11571     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11572     if (aManipulator.IsNull())
11573     {
11574       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11575       return 1;
11576     }
11577
11578     aManipulator->Detach();
11579     aMapAIS.UnBind2 (aName);
11580     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
11581
11582     return 0;
11583   }
11584
11585   // -----------------------------------------------
11586   // find or create manipulator if it does not exist
11587   // -----------------------------------------------
11588
11589   Handle(AIS_Manipulator) aManipulator;
11590   if (!aMapAIS.IsBound2 (aName))
11591   {
11592     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
11593
11594     aManipulator = new ViewerTest_AISManipulator();
11595     aMapAIS.Bind (aManipulator, aName);
11596   }
11597   else
11598   {
11599     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11600     if (aManipulator.IsNull())
11601     {
11602       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11603       return 1;
11604     }
11605   }
11606
11607   // -----------------------------------------
11608   // change properties of manipulator instance
11609   // -----------------------------------------
11610
11611   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
11612   {
11613     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
11614   }
11615   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
11616   {
11617     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
11618   }
11619   if (aCmd.HasOption ("followRotation", 1, Standard_True))
11620   {
11621     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
11622   }
11623   if (aCmd.HasOption ("gap", 1, Standard_True))
11624   {
11625     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
11626   }
11627   if (aCmd.HasOption ("part", 3, Standard_True))
11628   {
11629     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
11630     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
11631     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
11632     if (aMode < 1 || aMode > 3)
11633     {
11634       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
11635       return 1;
11636     }
11637
11638     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
11639   }
11640   if (aCmd.HasOption ("pos", 3, Standard_True))
11641   {
11642     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
11643     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
11644     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
11645
11646     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
11647   }
11648   if (aCmd.HasOption ("size", 1, Standard_True))
11649   {
11650     aManipulator->SetSize (aCmd.ArgFloat ("size"));
11651   }
11652   if (aCmd.HasOption ("zoomable", 1, Standard_True))
11653   {
11654     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
11655
11656     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
11657     {
11658       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
11659       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
11660     }
11661   }
11662
11663   // ---------------------------------------------------
11664   // attach, detach or access manipulator from an object
11665   // ---------------------------------------------------
11666
11667   if (aCmd.HasOption ("attach"))
11668   {
11669     // Find an object and attach manipulator to it
11670     if (!aCmd.HasOption ("attach", 1, Standard_True))
11671     {
11672       return 1;
11673     }
11674
11675     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
11676     Handle(AIS_InteractiveObject) anObject;
11677     if (!aMapAIS.Find2 (anObjName, anObject))
11678     {
11679       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
11680       return 1;
11681     }
11682
11683     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
11684     {
11685       if (anIt.Value()->IsAttached()
11686        && anIt.Value()->Object() == anObject)
11687       {
11688         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
11689         return 1;
11690       }
11691     }
11692
11693     AIS_Manipulator::OptionsForAttach anOptions;
11694     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
11695     {
11696       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
11697     }
11698     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
11699     {
11700       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
11701     }
11702     if (aCmd.HasOption ("enableModes", 1, Standard_True))
11703     {
11704       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
11705     }
11706
11707     aManipulator->Attach (anObject, anOptions);
11708   }
11709
11710   // --------------------------------------
11711   // apply transformation using manipulator
11712   // --------------------------------------
11713
11714   if (aCmd.HasOption ("startTransform", 2, Standard_True))
11715   {
11716     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
11717   }
11718   if (aCmd.HasOption ("transform", 2, Standard_True))
11719   {
11720     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
11721   }
11722   if (aCmd.HasOption ("stopTransform"))
11723   {
11724     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
11725
11726     aManipulator->StopTransform (toApply);
11727   }
11728
11729   gp_Trsf aT;
11730   if (aCmd.HasOption ("move", 3, Standard_True))
11731   {
11732     aT.SetTranslationPart (aCmd.ArgVec ("move"));
11733   }
11734   if (aCmd.HasOption ("rotate", 7, Standard_True))
11735   {
11736     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
11737   }
11738   if (aCmd.HasOption ("scale", 1))
11739   {
11740     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
11741   }
11742
11743   if (aT.Form() != gp_Identity)
11744   {
11745     aManipulator->Transform (aT);
11746   }
11747
11748   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
11749
11750   return 0;
11751 }
11752
11753 //===============================================================================================
11754 //function : VSelectionProperties
11755 //purpose  :
11756 //===============================================================================================
11757 static int VSelectionProperties (Draw_Interpretor& theDi,
11758                                  Standard_Integer  theArgsNb,
11759                                  const char**      theArgVec)
11760 {
11761   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
11762   if (aCtx.IsNull())
11763   {
11764     std::cerr << "No active viewer!\n";
11765     return 1;
11766   }
11767
11768   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
11769   {
11770     // handle obsolete alias
11771     bool toEnable = true;
11772     if (theArgsNb < 2)
11773     {
11774       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
11775       return 0;
11776     }
11777     else if (theArgsNb != 2
11778          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
11779     {
11780       std::cout << "Syntax error: wrong number of parameters.";
11781       return 1;
11782     }
11783     if (toEnable != aCtx->ToHilightSelected())
11784     {
11785       aCtx->ClearDetected();
11786       aCtx->SetToHilightSelected (toEnable);
11787     }
11788     return 0;
11789   }
11790
11791   Standard_Boolean toPrint  = theArgsNb == 1;
11792   Standard_Boolean toRedraw = Standard_False;
11793   Standard_Integer anArgIter = 1;
11794   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
11795   if (anArgIter < theArgsNb)
11796   {
11797     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
11798     anArgFirst.LowerCase();
11799     ++anArgIter;
11800     if (anArgFirst == "dynhighlight"
11801      || anArgFirst == "dynhilight"
11802      || anArgFirst == "dynamichighlight"
11803      || anArgFirst == "dynamichilight")
11804     {
11805       aType = Prs3d_TypeOfHighlight_Dynamic;
11806     }
11807     else if (anArgFirst == "localdynhighlight"
11808           || anArgFirst == "localdynhilight"
11809           || anArgFirst == "localdynamichighlight"
11810           || anArgFirst == "localdynamichilight")
11811     {
11812       aType = Prs3d_TypeOfHighlight_LocalDynamic;
11813     }
11814     else if (anArgFirst == "selhighlight"
11815           || anArgFirst == "selhilight"
11816           || anArgFirst == "selectedhighlight"
11817           || anArgFirst == "selectedhilight")
11818     {
11819       aType = Prs3d_TypeOfHighlight_Selected;
11820     }
11821     else if (anArgFirst == "localselhighlight"
11822           || anArgFirst == "localselhilight"
11823           || anArgFirst == "localselectedhighlight"
11824           || anArgFirst == "localselectedhilight")
11825     {
11826       aType = Prs3d_TypeOfHighlight_LocalSelected;
11827     }
11828     else
11829     {
11830       --anArgIter;
11831     }
11832   }
11833   for (; anArgIter < theArgsNb; ++anArgIter)
11834   {
11835     TCollection_AsciiString anArg (theArgVec[anArgIter]);
11836     anArg.LowerCase();
11837     if (anArg == "-help")
11838     {
11839       theDi.PrintHelp (theArgVec[0]);
11840       return 0;
11841     }
11842     else if (anArg == "-print")
11843     {
11844       toPrint = Standard_True;
11845     }
11846     else if (anArg == "-autoactivate")
11847     {
11848       Standard_Boolean toEnable = Standard_True;
11849       if (anArgIter + 1 < theArgsNb
11850        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11851       {
11852         ++anArgIter;
11853       }
11854       aCtx->SetAutoActivateSelection (toEnable);
11855     }
11856     else if (anArg == "-automatichighlight"
11857           || anArg == "-automatichilight"
11858           || anArg == "-autohighlight"
11859           || anArg == "-autohilight")
11860     {
11861       Standard_Boolean toEnable = Standard_True;
11862       if (anArgIter + 1 < theArgsNb
11863        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11864       {
11865         ++anArgIter;
11866       }
11867       aCtx->ClearSelected (false);
11868       aCtx->ClearDetected();
11869       aCtx->SetAutomaticHilight (toEnable);
11870       toRedraw = true;
11871     }
11872     else if (anArg == "-highlightselected"
11873           || anArg == "-hilightselected")
11874     {
11875       Standard_Boolean toEnable = Standard_True;
11876       if (anArgIter + 1 < theArgsNb
11877        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11878       {
11879         ++anArgIter;
11880       }
11881       aCtx->ClearDetected();
11882       aCtx->SetToHilightSelected (toEnable);
11883       toRedraw = true;
11884     }
11885     else if (anArg == "-pickstrategy"
11886           || anArg == "-pickingstrategy")
11887     {
11888       if (++anArgIter >= theArgsNb)
11889       {
11890         std::cout << "Syntax error: type of highlighting is undefined\n";
11891         return 1;
11892       }
11893
11894       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11895       TCollection_AsciiString aVal (theArgVec[anArgIter]);
11896       aVal.LowerCase();
11897       if (aVal == "first"
11898        || aVal == "firstaccepted"
11899        || aVal == "firstacceptable")
11900       {
11901         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11902       }
11903       else if (aVal == "topmost"
11904             || aVal == "onlyTopmost")
11905       {
11906         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
11907       }
11908       else
11909       {
11910         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
11911         return 1;
11912       }
11913
11914       aCtx->SetPickingStrategy (aStrategy);
11915     }
11916     else if (anArg == "-pixtol"
11917           && anArgIter + 1 < theArgsNb)
11918     {
11919       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
11920     }
11921     else if ((anArg == "-mode"
11922            || anArg == "-dispmode")
11923           && anArgIter + 1 < theArgsNb)
11924     {
11925       if (aType == Prs3d_TypeOfHighlight_None)
11926       {
11927         std::cout << "Syntax error: type of highlighting is undefined\n";
11928         return 1;
11929       }
11930
11931       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
11932       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11933       aStyle->SetDisplayMode (aDispMode);
11934       toRedraw = Standard_True;
11935     }
11936     else if (anArg == "-layer"
11937           && anArgIter + 1 < theArgsNb)
11938     {
11939       if (aType == Prs3d_TypeOfHighlight_None)
11940       {
11941         std::cout << "Syntax error: type of highlighting is undefined\n";
11942         return 1;
11943       }
11944
11945       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
11946       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
11947       {
11948         TColStd_SequenceOfInteger aLayers;
11949         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
11950         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
11951         {
11952           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
11953           return 1;
11954         }
11955       }
11956
11957       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11958       aStyle->SetZLayer (aNewLayer);
11959       toRedraw = Standard_True;
11960     }
11961     else if (anArg == "-hicolor"
11962           || anArg == "-selcolor"
11963           || anArg == "-color")
11964     {
11965       if (anArg.StartsWith ("-hi"))
11966       {
11967         aType = Prs3d_TypeOfHighlight_Dynamic;
11968       }
11969       else if (anArg.StartsWith ("-sel"))
11970       {
11971         aType = Prs3d_TypeOfHighlight_Selected;
11972       }
11973       else if (aType == Prs3d_TypeOfHighlight_None)
11974       {
11975         std::cout << "Syntax error: type of highlighting is undefined\n";
11976         return 1;
11977       }
11978
11979       Quantity_Color aColor;
11980       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
11981                                                            theArgVec + anArgIter + 1,
11982                                                            aColor);
11983       if (aNbParsed == 0)
11984       {
11985         std::cout << "Syntax error: need more arguments.\n";
11986         return 1;
11987       }
11988       anArgIter += aNbParsed;
11989
11990       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11991       aStyle->SetColor (aColor);
11992       toRedraw = Standard_True;
11993     }
11994     else if ((anArg == "-transp"
11995            || anArg == "-transparency"
11996            || anArg == "-hitransp"
11997            || anArg == "-seltransp"
11998            || anArg == "-hitransplocal"
11999            || anArg == "-seltransplocal")
12000           && anArgIter + 1 < theArgsNb)
12001     {
12002       if (anArg.StartsWith ("-hi"))
12003       {
12004         aType = Prs3d_TypeOfHighlight_Dynamic;
12005       }
12006       else if (anArg.StartsWith ("-sel"))
12007       {
12008         aType = Prs3d_TypeOfHighlight_Selected;
12009       }
12010       else if (aType == Prs3d_TypeOfHighlight_None)
12011       {
12012         std::cout << "Syntax error: type of highlighting is undefined\n";
12013         return 1;
12014       }
12015
12016       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
12017       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12018       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
12019       toRedraw = Standard_True;
12020     }
12021     else if ((anArg == "-mat"
12022            || anArg == "-material")
12023           && anArgIter + 1 < theArgsNb)
12024     {
12025       if (aType == Prs3d_TypeOfHighlight_None)
12026       {
12027         std::cout << "Syntax error: type of highlighting is undefined\n";
12028         return 1;
12029       }
12030
12031       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12032       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
12033       if (aMatName != Graphic3d_NOM_DEFAULT)
12034       {
12035         ++anArgIter;
12036         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
12037         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
12038         Graphic3d_MaterialAspect aMat (aMatName);
12039         aMat.SetColor (aStyle->Color());
12040         aMat.SetTransparency (aStyle->Transparency());
12041         anAspect->SetFrontMaterial (aMat);
12042         anAspect->SetInteriorColor (aStyle->Color());
12043         aStyle->SetBasicFillAreaAspect (anAspect);
12044       }
12045       else
12046       {
12047         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
12048       }
12049       toRedraw = Standard_True;
12050     }
12051     else
12052     {
12053       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
12054     }
12055   }
12056
12057   if (toPrint)
12058   {
12059     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
12060     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
12061     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
12062     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
12063     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
12064     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
12065     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
12066     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
12067     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
12068     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
12069     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
12070     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
12071     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
12072     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
12073   }
12074
12075   if (aCtx->NbSelected() != 0 && toRedraw)
12076   {
12077     aCtx->HilightSelected (Standard_True);
12078   }
12079
12080   return 0;
12081 }
12082
12083 //===============================================================================================
12084 //function : VDumpSelectionImage
12085 //purpose  :
12086 //===============================================================================================
12087 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
12088                                 Standard_Integer  theArgsNb,
12089                                 const char**      theArgVec)
12090 {
12091   if (theArgsNb < 2)
12092   {
12093     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
12094     return 1;
12095   }
12096
12097   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
12098   if (aContext.IsNull())
12099   {
12100     std::cout << "Error: no active view.\n";
12101     return 1;
12102   }
12103
12104   TCollection_AsciiString aFile;
12105   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12106   Image_Format anImgFormat = Image_Format_BGR;
12107   Standard_Integer aPickedIndex = 1;
12108   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
12109   {
12110     TCollection_AsciiString aParam (theArgVec[anArgIter]);
12111     aParam.LowerCase();
12112     if (aParam == "-type")
12113     {
12114       if (++anArgIter >= theArgsNb)
12115       {
12116         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
12117         return 1;
12118       }
12119
12120       TCollection_AsciiString aValue (theArgVec[anArgIter]);
12121       aValue.LowerCase();
12122       if (aValue == "depth"
12123        || aValue == "normdepth"
12124        || aValue == "normalizeddepth")
12125       {
12126         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12127         anImgFormat = Image_Format_GrayF;
12128       }
12129       if (aValue == "depthinverted"
12130        || aValue == "normdepthinverted"
12131        || aValue == "normalizeddepthinverted"
12132        || aValue == "inverted")
12133       {
12134         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
12135         anImgFormat = Image_Format_GrayF;
12136       }
12137       else if (aValue == "unnormdepth"
12138             || aValue == "unnormalizeddepth")
12139       {
12140         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
12141         anImgFormat = Image_Format_GrayF;
12142       }
12143       else if (aValue == "objectcolor"
12144             || aValue == "object"
12145             || aValue == "color")
12146       {
12147         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
12148       }
12149       else if (aValue == "entitycolor"
12150             || aValue == "entity")
12151       {
12152         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
12153       }
12154       else if (aValue == "ownercolor"
12155             || aValue == "owner")
12156       {
12157         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
12158       }
12159       else if (aValue == "selectionmodecolor"
12160             || aValue == "selectionmode"
12161             || aValue == "selmodecolor"
12162             || aValue == "selmode")
12163       {
12164         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
12165       }
12166     }
12167     else if (aParam == "-picked"
12168           || aParam == "-pickeddepth"
12169           || aParam == "-pickedindex")
12170     {
12171       if (++anArgIter >= theArgsNb)
12172       {
12173         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
12174         return 1;
12175       }
12176
12177       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
12178     }
12179     else if (aFile.IsEmpty())
12180     {
12181       aFile = theArgVec[anArgIter];
12182     }
12183     else
12184     {
12185       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
12186       return 1;
12187     }
12188   }
12189   if (aFile.IsEmpty())
12190   {
12191     std::cout << "Syntax error: image file name is missing.\n";
12192     return 1;
12193   }
12194
12195   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
12196   Standard_Integer aWidth = 0, aHeight = 0;
12197   aView->Window()->Size (aWidth, aHeight);
12198
12199   Image_AlienPixMap aPixMap;
12200   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
12201   {
12202     std::cout << "Error: can't allocate image.\n";
12203     return 1;
12204   }
12205   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
12206   {
12207     std::cout << "Error: can't generate selection image.\n";
12208     return 1;
12209   }
12210   if (!aPixMap.Save (aFile))
12211   {
12212     std::cout << "Error: can't save selection image.\n";
12213     return 0;
12214   }
12215   return 0;
12216 }
12217
12218 //=======================================================================
12219 //function : ViewerCommands
12220 //purpose  :
12221 //=======================================================================
12222
12223 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
12224 {
12225
12226   const char *group = "ZeViewer";
12227   theCommands.Add("vinit",
12228           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
12229     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
12230   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
12231     "\n\t\t:     [-display displayName]"
12232   #endif
12233     "\n\t\t: Creates new View window with specified name viewName."
12234     "\n\t\t: By default the new view is created in the viewer and in"
12235     "\n\t\t: graphic driver shared with active view."
12236     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
12237     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
12238     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
12239 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
12240     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
12241     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
12242 #endif
12243     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
12244     "\n\t\t:  -width, -height width and heigth of window respectively."
12245     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
12246     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
12247     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
12248     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
12249     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
12250     __FILE__,VInit,group);
12251   theCommands.Add("vclose" ,
12252     "[view_id [keep_context=0|1]]\n"
12253     "or vclose ALL - to remove all created views\n"
12254     " - removes view(viewer window) defined by its view_id.\n"
12255     " - keep_context: by default 0; if 1 and the last view is deleted"
12256     " the current context is not removed.",
12257     __FILE__,VClose,group);
12258   theCommands.Add("vactivate" ,
12259     "view_id"
12260     " - activates view(viewer window) defined by its view_id",
12261     __FILE__,VActivate,group);
12262   theCommands.Add("vviewlist",
12263     "vviewlist [format={tree, long}]"
12264     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
12265     " - format: format of result output, if tree the output is a tree view;"
12266     "otherwise it's a list of full view names. By default format = tree",
12267     __FILE__,VViewList,group);
12268   theCommands.Add("vhelp" ,
12269     "vhelp            : display help on the viewer commands",
12270     __FILE__,VHelp,group);
12271   theCommands.Add("vtop" ,
12272     "vtop or <T>      : Top view. Orientation +X+Y" ,
12273     __FILE__,VTop,group);
12274   theCommands.Add("vbottom" ,
12275     "vbottom          : Bottom view. Orientation +X-Y" ,
12276     __FILE__,VBottom,group);
12277   theCommands.Add("vleft" ,
12278     "vleft            : Left view. Orientation -Y+Z" ,
12279     __FILE__,VLeft,group);
12280   theCommands.Add("vright" ,
12281     "vright           : Right view. Orientation +Y+Z" ,
12282     __FILE__,VRight,group);
12283   theCommands.Add("vaxo" ,
12284     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
12285     __FILE__,VAxo,group);
12286   theCommands.Add("vfront" ,
12287     "vfront           : Front view. Orientation +X+Z" ,
12288     __FILE__,VFront,group);
12289   theCommands.Add("vback" ,
12290     "vback            : Back view. Orientation -X+Z" ,
12291     __FILE__,VBack,group);
12292   theCommands.Add("vpick" ,
12293     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
12294     VPick,group);
12295   theCommands.Add("vfit",
12296     "vfit or <F> [-selected] [-noupdate]"
12297     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
12298     __FILE__,VFit,group);
12299   theCommands.Add ("vfitarea",
12300     "vfitarea x1 y1 x2 y2"
12301     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
12302     "\n\t\t: Fit view to show area located between two points"
12303     "\n\t\t: given in world 2D or 3D corrdinates.",
12304     __FILE__, VFitArea, group);
12305   theCommands.Add ("vzfit", "vzfit [scale]\n"
12306     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
12307     "   \"scale\" - specifies factor to scale computed z range.\n",
12308     __FILE__, VZFit, group);
12309   theCommands.Add("vrepaint",
12310             "vrepaint [-immediate]"
12311     "\n\t\t: force redraw",
12312     __FILE__,VRepaint,group);
12313   theCommands.Add("vclear",
12314     "vclear          : vclear"
12315     "\n\t\t: remove all the object from the viewer",
12316     __FILE__,VClear,group);
12317   theCommands.Add("vsetbg",
12318     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
12319     __FILE__,VSetBg,group);
12320   theCommands.Add("vsetbgmode",
12321     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
12322     __FILE__,VSetBgMode,group);
12323   theCommands.Add("vsetgradientbg",
12324     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
12325     __FILE__,VSetGradientBg,group);
12326   theCommands.Add("vsetgrbgmode",
12327     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
12328     __FILE__,VSetGradientBgMode,group);
12329   theCommands.Add("vsetcolorbg",
12330     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
12331     __FILE__,VSetColorBg,group);
12332   theCommands.Add("vsetdefaultbg",
12333     "vsetdefaultbg r g b\n"
12334     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
12335     "\n\t\t: Set default viewer background fill color (flat/gradient).",
12336     __FILE__,VSetDefaultBg,group);
12337   theCommands.Add("vscale",
12338     "vscale          : vscale X Y Z",
12339     __FILE__,VScale,group);
12340   theCommands.Add("vzbufftrihedron",
12341             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
12342     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
12343     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
12344     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
12345     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
12346     "\n\t\t: Displays a trihedron",
12347     __FILE__,VZBuffTrihedron,group);
12348   theCommands.Add("vrotate",
12349     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
12350     "\n                : Option -mouseStart starts rotation according to the mouse position"
12351     "\n                : Option -mouseMove continues rotation with angle computed"
12352     "\n                : from last and new mouse position."
12353     "\n                : vrotate AX AY AZ [X Y Z]",
12354     __FILE__,VRotate,group);
12355   theCommands.Add("vzoom",
12356     "vzoom           : vzoom coef",
12357     __FILE__,VZoom,group);
12358   theCommands.Add("vpan",
12359     "vpan            : vpan dx dy",
12360     __FILE__,VPan,group);
12361   theCommands.Add("vcolorscale",
12362     "vcolorscale name [-noupdate|-update] [-demo]"
12363     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
12364     "\n\t\t:       [-font HeightFont=20]"
12365     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
12366     "\n\t\t:       [-smoothTransition {on|off}=off]"
12367     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
12368     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
12369     "\n\t\t:       [-textpos {left|right|center|none}=right]"
12370     "\n\t\t:       [-labelAtBorder {on|off}=on]"
12371     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
12372     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
12373     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
12374     "\n\t\t:       [-xy Left=0 Bottom=0]"
12375     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
12376     "\n\t\t:  -colors   - set colors for all intervals"
12377     "\n\t\t:  -color    - set color for specific interval"
12378     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
12379     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
12380     "\n\t\t:              at border means the value inbetween neighbor intervals,"
12381     "\n\t\t:              at center means the center value within current interval"
12382     "\n\t\t:  -labels   - set labels for all intervals"
12383     "\n\t\t:  -freeLabels - same as -labels but does not require"
12384     "\n\t\t:              matching the number of intervals"
12385     "\n\t\t:  -label    - set label for specific interval"
12386     "\n\t\t:  -title    - set title"
12387     "\n\t\t:  -reversed - setup smooth color transition between intervals"
12388     "\n\t\t:  -smoothTransition - swap colorscale direction"
12389     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
12390     __FILE__, VColorScale, group);
12391   theCommands.Add("vgraduatedtrihedron",
12392     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
12393     "\t[-namefont Name] [-valuesfont Name]\n"
12394     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
12395     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
12396     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
12397     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
12398     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
12399     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
12400     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
12401     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
12402     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
12403     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
12404     " - Displays or erases graduated trihedron"
12405     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
12406     " - namefont - font of axes names. Default: Arial\n"
12407     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
12408     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
12409     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
12410     " - valuesfont - font of axes values. Default: Arial\n"
12411     " - xcolor, ycolor, zcolor - color of axis and values\n"
12412     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
12413     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
12414     __FILE__,VGraduatedTrihedron,group);
12415   theCommands.Add("vtile" ,
12416             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
12417     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
12418     "\n\t\t:  -totalSize the size of virtual bigger viewport"
12419     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
12420     "\n\t\t:  -lowerLeft tile offset as lower left corner"
12421     "\n\t\t:  -upperLeft tile offset as upper left corner",
12422     __FILE__, VTile, group);
12423   theCommands.Add("vzlayer",
12424               "vzlayer [layerId]"
12425       "\n\t\t:         [-add|-delete|-get|-settings]"
12426       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
12427       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
12428       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
12429       "\n\t\t: ZLayer list management:"
12430       "\n\t\t:   -add      add new z layer to viewer and print its id"
12431       "\n\t\t:   -delete   delete z layer"
12432       "\n\t\t:   -get      print sequence of z layers"
12433       "\n\t\t:   -settings print status of z layer settings"
12434       "\n\t\t:   -disable  disables given setting"
12435       "\n\t\t:   -enable   enables  given setting",
12436     __FILE__,VZLayer,group);
12437   theCommands.Add("vlayerline",
12438     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
12439     __FILE__,VLayerLine,group);
12440   theCommands.Add ("vgrid",
12441     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
12442     " : Mode - rectangular or circular"
12443     " : Type - lines or points",
12444     __FILE__, VGrid, group);
12445   theCommands.Add ("vpriviledgedplane",
12446     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
12447     "\n\t\t:   Ox, Oy, Oz - plane origin"
12448     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
12449     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
12450     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
12451     __FILE__, VPriviledgedPlane, group);
12452   theCommands.Add ("vconvert",
12453     "vconvert v [Mode={window|view}]"
12454     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
12455     "\n\t\t: vconvert x y z [Mode={window|grid}]"
12456     "\n\t\t:   window - convert to window coordinates, pixels"
12457     "\n\t\t:   view   - convert to view projection plane"
12458     "\n\t\t:   grid   - convert to model coordinates, given on grid"
12459     "\n\t\t:   ray    - convert projection ray to model coordiantes"
12460     "\n\t\t: - vconvert v window : convert view to window;"
12461     "\n\t\t: - vconvert v view   : convert window to view;"
12462     "\n\t\t: - vconvert x y window : convert view to window;"
12463     "\n\t\t: - vconvert x y view : convert window to view;"
12464     "\n\t\t: - vconvert x y : convert window to model;"
12465     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
12466     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
12467     "\n\t\t: - vconvert x y z window : convert model to window;"
12468     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
12469     "\n\t\t: Converts the given coordinates to window/view/model space.",
12470     __FILE__, VConvert, group);
12471   theCommands.Add ("vfps",
12472     "vfps [framesNb=100] : estimate average frame rate for active view",
12473     __FILE__, VFps, group);
12474   theCommands.Add ("vgldebug",
12475             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
12476     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
12477     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
12478     "\n\t\t: Debug context can be requested only on Windows"
12479     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
12480     "\n\t\t:  -sync     - request synchronized debug GL context"
12481     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
12482     "\n\t\t:              which are suppressed by default,"
12483     "\n\t\t:  -glslCode - log GLSL program source code,"
12484     "\n\t\t:              which are suppressed by default,"
12485     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
12486     "\n\t\t:              which are suppressed by default",
12487     __FILE__, VGlDebug, group);
12488   theCommands.Add ("vvbo",
12489     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
12490     __FILE__, VVbo, group);
12491   theCommands.Add ("vstereo",
12492             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
12493     "\n\t\t:         [-anaglyph Filter]"
12494     "\n\t\t: Control stereo output mode. Available modes for -mode:"
12495     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
12496     "\n\t\t:                     requires driver support."
12497     "\n\t\t:                     Should be called BEFORE vinit!"
12498     "\n\t\t:  anaglyph         - Anaglyph glasses"
12499     "\n\t\t:  rowInterlaced    - row-interlaced display"
12500     "\n\t\t:  columnInterlaced - column-interlaced display"
12501     "\n\t\t:  chessBoard       - chess-board output"
12502     "\n\t\t:  sideBySide       - horizontal pair"
12503     "\n\t\t:  overUnder        - vertical   pair"
12504     "\n\t\t: Available Anaglyph filters for -anaglyph:"
12505     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
12506     "\n\t\t:  greenMagentaSimple",
12507     __FILE__, VStereo, group);
12508   theCommands.Add ("vcaps",
12509             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
12510     "\n\t\t:       [-compatibleProfile {0|1}]"
12511     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
12512     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
12513     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
12514     "\n\t\t: Modify particular graphic driver options:"
12515     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
12516     "\n\t\t:             built-in GLSL programs"
12517     "\n\t\t:            (requires compatible profile)"
12518     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
12519     "\n\t\t:             arrays to GPU memory)"
12520     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
12521     "\n\t\t:  vsync    - switch VSync on or off"
12522     "\n\t\t:  winBuffer - allow using window buffer for rendering"
12523     "\n\t\t: Context creation options:"
12524     "\n\t\t:  softMode          - software OpenGL implementation"
12525     "\n\t\t:  compatibleProfile - backward-compatible profile"
12526     "\n\t\t:  quadbuffer        - QuadBuffer"
12527     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
12528     "\n\t\t: rendering paths producing the same visual result when"
12529     "\n\t\t: possible."
12530     "\n\t\t: Command is intended for testing old hardware compatibility.",
12531     __FILE__, VCaps, group);
12532   theCommands.Add ("vmemgpu",
12533     "vmemgpu [f]: print system-dependent GPU memory information if available;"
12534     " with f option returns free memory in bytes",
12535     __FILE__, VMemGpu, group);
12536   theCommands.Add ("vreadpixel",
12537     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
12538     " : Read pixel value for active view",
12539     __FILE__, VReadPixel, group);
12540   theCommands.Add("diffimage",
12541             "diffimage imageFile1 imageFile2 [diffImageFile]"
12542     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
12543     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
12544     "\n\t\t: Compare two images by content and generate difference image."
12545     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
12546     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
12547     __FILE__, VDiffImage, group);
12548   theCommands.Add ("vselect",
12549     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
12550     "- emulates different types of selection:\n"
12551     "- 1) single click selection\n"
12552     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
12553     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
12554     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
12555     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
12556     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
12557     " (partial inclusion - overlap - is not allowed by default)\n"
12558     "- 5) any of these selections with shift button pressed",
12559     __FILE__, VSelect, group);
12560   theCommands.Add ("vmoveto",
12561     "vmoveto [x y] [-reset]"
12562     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
12563     "\n\t\t:   -reset resets current highlighting",
12564     __FILE__, VMoveTo, group);
12565   theCommands.Add ("vviewparams",
12566               "vviewparams [-args] [-scale [s]]"
12567       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
12568       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
12569       "\n\t\t: Manage current view parameters or prints all"
12570       "\n\t\t: current values when called without argument."
12571       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
12572       "\n\t\t:   -eye  [x y z] prints or sets eye location"
12573       "\n\t\t:   -at   [x y z] prints or sets center of look"
12574       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
12575       "\n\t\t:   -proj [x y z] prints or sets direction of look"
12576       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
12577       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
12578       "\n\t\t:                 or changes the size of its maximum dimension"
12579       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
12580     __FILE__, VViewParams, group);
12581
12582   theCommands.Add("v2dmode",
12583     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
12584     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
12585     "\n\t\t:   mode   - switches On/Off rotation mode"
12586     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
12587     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
12588     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
12589     "\n\t\t: View camera position might be changed only by commands.",
12590     __FILE__, V2DMode, group);
12591
12592   theCommands.Add("vanimation", "Alias for vanim",
12593     __FILE__, VAnimation, group);
12594
12595   theCommands.Add("vanim",
12596             "List existing animations:"
12597     "\n\t\t:  vanim"
12598     "\n\t\t: Animation playback:"
12599     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
12600     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
12601     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
12602     "\n\t\t:   -freeLook skip camera animations"
12603     "\n\t\t:   -lockLoop disable any interactions"
12604     "\n\t\t:"
12605     "\n\t\t: Animation definition:"
12606     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
12607     "\n\t\t:        [start TimeSec] [duration TimeSec]"
12608     "\n\t\t:"
12609     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
12610     "\n\t\t: specifies nested animations."
12611     "\n\t\t: There is no syntax to explicitly add new animation,"
12612     "\n\t\t: and all non-existing animations within the name will be"
12613     "\n\t\t: implicitly created on first use (including parents)."
12614     "\n\t\t:"
12615     "\n\t\t: Each animation might define the SINGLE action (see below),"
12616     "\n\t\t: like camera transition, object transformation or custom callback."
12617     "\n\t\t: Child animations can be used for defining concurrent actions."
12618     "\n\t\t:"
12619     "\n\t\t: Camera animation:"
12620     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
12621     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
12622     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
12623     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
12624     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
12625     "\n\t\t:   -atX    camera Center positions pair"
12626     "\n\t\t:   -upX    camera Up directions pair"
12627     "\n\t\t:   -scaleX camera Scale factors pair"
12628     "\n\t\t: Object animation:"
12629     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
12630     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
12631     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
12632     "\n\t\t:   -locX   object Location points pair (translation)"
12633     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
12634     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
12635     "\n\t\t: Custom callback:"
12636     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
12637     "\n\t\t:   %Pts        overall animation presentation timestamp"
12638     "\n\t\t:   %LocalPts   local animation timestamp"
12639     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
12640     "\n\t\t:"
12641     "\n\t\t: Video recording:"
12642     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
12643     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
12644     "\n\t\t:             [-crf Value] [-preset Preset]"
12645     "\n\t\t:   -fps     video framerate"
12646     "\n\t\t:   -format  file format, container (matroska, etc.)"
12647     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
12648     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
12649     "\n\t\t:   -crf     constant rate factor (specific to codec)"
12650     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
12651     __FILE__, VAnimation, group);
12652
12653   theCommands.Add("vchangeselected",
12654     "vchangeselected shape"
12655     "- adds to shape to selection or remove one from it",
12656                 __FILE__, VChangeSelected, group);
12657   theCommands.Add ("vnbselected",
12658     "vnbselected"
12659     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
12660   theCommands.Add ("vcamera",
12661               "vcamera [PrsName] [-ortho] [-projtype]"
12662       "\n\t\t:         [-persp]"
12663       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
12664       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
12665       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
12666       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
12667       "\n\t\t: Manages camera parameters."
12668       "\n\t\t: Displays frustum when presntation name PrsName is specified."
12669       "\n\t\t: Prints current value when option called without argument."
12670       "\n\t\t: Orthographic camera:"
12671       "\n\t\t:   -ortho      activate orthographic projection"
12672       "\n\t\t: Perspective camera:"
12673       "\n\t\t:   -persp      activate perspective  projection (mono)"
12674       "\n\t\t:   -fovy       field of view in y axis, in degrees"
12675       "\n\t\t:   -distance   distance of eye from camera center"
12676       "\n\t\t: Stereoscopic camera:"
12677       "\n\t\t:   -stereo     perspective  projection (stereo)"
12678       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
12679       "\n\t\t:   -rightEye   perspective  projection (right eye)"
12680       "\n\t\t:   -iod        intraocular distance value"
12681       "\n\t\t:   -iodType    distance type, absolute or relative"
12682       "\n\t\t:   -zfocus     stereographic focus value"
12683       "\n\t\t:   -zfocusType focus type, absolute or relative",
12684     __FILE__, VCamera, group);
12685   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
12686     "- vautozfit [on={1|0}] [scale]\n"
12687     "    Prints or changes parameters of automatic z-fit mode:\n"
12688     "   \"on\" - turns automatic z-fit on or off\n"
12689     "   \"scale\" - specifies factor to scale computed z range.\n",
12690     __FILE__, VAutoZFit, group);
12691   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
12692     "   vzrange                - without parameters shows current values\n"
12693     "   vzrange [znear] [zfar] - applies provided values to view",
12694     __FILE__,VZRange, group);
12695   theCommands.Add ("vpurgedisplay",
12696     "vpurgedisplay"
12697     "- removes structures which don't belong to objects displayed in neutral point",
12698     __FILE__, VPurgeDisplay, group);
12699   theCommands.Add("vsetviewsize",
12700     "vsetviewsize size",
12701     __FILE__,VSetViewSize,group);
12702   theCommands.Add("vmoveview",
12703     "vmoveview Dx Dy Dz [Start = 1|0]",
12704     __FILE__,VMoveView,group);
12705   theCommands.Add("vtranslateview",
12706     "vtranslateview Dx Dy Dz [Start = 1|0)]",
12707     __FILE__,VTranslateView,group);
12708   theCommands.Add("vturnview",
12709     "vturnview Ax Ay Az [Start = 1|0]",
12710     __FILE__,VTurnView,group);
12711   theCommands.Add("vtextureenv",
12712     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
12713     "or user-defined file and optionally applying texture mapping parameters\n"
12714     "                  Usage:\n"
12715     "                  vtextureenv off - disables environment mapping\n"
12716     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
12717     "                              std_texture = (0..7)\n"
12718     "                              rep         = {clamp|repeat}\n"
12719     "                              mod         = {decal|modulate}\n"
12720     "                              flt         = {nearest|bilinear|trilinear}\n"
12721     "                              ss, st      - scale factors for s and t texture coordinates\n"
12722     "                              ts, tt      - translation for s and t texture coordinates\n"
12723     "                              rot         - texture rotation angle in degrees",
12724     __FILE__, VTextureEnv, group);
12725   theCommands.Add("vhlr",
12726             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
12727       "\n\t\t: Hidden Line Removal algorithm."
12728       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
12729       "\n\t\t:   -algoType   type of HLR algorithm.\n",
12730     __FILE__,VHLR,group);
12731   theCommands.Add("vhlrtype",
12732               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
12733       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
12734       "\n\t\t:   'algo' - exact HLR algorithm is applied"
12735       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
12736       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
12737     __FILE__,VHLRType,group);
12738   theCommands.Add("vclipplane",
12739               "vclipplane planeName [{0|1}]"
12740       "\n\t\t:   [-equation1 A B C D]"
12741       "\n\t\t:   [-equation2 A B C D]"
12742       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
12743       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
12744       "\n\t\t:   [-maxPlanes]"
12745       "\n\t\t:   [-capping {0|1}]"
12746       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
12747       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
12748       "\n\t\t:       [-texRotate Angle]"
12749       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
12750       "\n\t\t:       [-useObjShader {0|1}]"
12751       "\n\t\t: Clipping planes management:"
12752       "\n\t\t:   -maxPlanes   print plane limit for view"
12753       "\n\t\t:   -delete      delete plane with given name"
12754       "\n\t\t:   {off|on|0|1} turn clipping on/off"
12755       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
12756       "\n\t\t:                applied to active View when list is omitted"
12757       "\n\t\t:   -equation A B C D change plane equation"
12758       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
12759       "\n\t\t: Capping options:"
12760       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
12761       "\n\t\t:   -color R G B          set capping color"
12762       "\n\t\t:   -transparency Value   set capping transparency 0..1"
12763       "\n\t\t:   -texName Texture      set capping texture"
12764       "\n\t\t:   -texScale SX SY       set capping tex scale"
12765       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
12766       "\n\t\t:   -texRotate Angle      set capping tex rotation"
12767       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
12768       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
12769       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
12770       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
12771       __FILE__, VClipPlane, group);
12772   theCommands.Add("vdefaults",
12773                "vdefaults [-absDefl value]"
12774        "\n\t\t:           [-devCoeff value]"
12775        "\n\t\t:           [-angDefl value]"
12776        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
12777     , __FILE__, VDefaults, group);
12778   theCommands.Add("vlight",
12779     "tool to manage light sources, without arguments shows list of lights."
12780     "\n    Main commands: "
12781     "\n      '-clear' to clear lights"
12782     "\n      '-{def}aults' to load deafault lights"
12783     "\n      '-add' <type> to add any light source"
12784     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
12785     "\n      'change' <lightId> to edit light source with specified lightId"
12786     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
12787     "\n        -layer Id"
12788     "\n        -{pos}ition X Y Z"
12789     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
12790     "\n        -color colorName"
12791     "\n        -{head}light 0|1"
12792     "\n        -{sm}oothness value"
12793     "\n        -{int}ensity value"
12794     "\n        -{constAtten}uation value"
12795     "\n        -{linearAtten}uation value"
12796     "\n        -angle angleDeg"
12797     "\n        -{spotexp}onent value"
12798     "\n        -local|-global"
12799     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
12800     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
12801     __FILE__, VLight, group);
12802   theCommands.Add("vraytrace",
12803             "vraytrace [0|1]"
12804     "\n\t\t: Turns on/off ray-tracing renderer."
12805     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
12806     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
12807     __FILE__, VRenderParams, group);
12808   theCommands.Add("vrenderparams",
12809     "\n    Manages rendering parameters: "
12810     "\n      '-raster'                   Disables GPU ray-tracing"
12811     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
12812     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
12813     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
12814     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
12815     "\n      '-rendScale    value        Rendering resolution scale factor"
12816     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
12817     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
12818     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
12819     "\n      '-reflections  on|off'      Enables/disables specular reflections"
12820     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
12821     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
12822     "\n      '-gi           on|off'      Enables/disables global illumination effects"
12823     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
12824     "\n      '-env          on|off'      Enables/disables environment map background"
12825     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
12826     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
12827     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
12828     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
12829     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
12830     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
12831     "\n      '-shadingModel model'       Controls shading model from enumeration"
12832     "\n                                  color, flat, gouraud, phong"
12833     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
12834     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
12835     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
12836     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
12837     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
12838     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
12839     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
12840     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
12841     "\n                                  Show/hide performance counters (flags can be combined)"
12842     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
12843     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
12844     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
12845     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
12846     "\n                                        set state to check structures culled previously."
12847     "\n    Unlike vcaps, these parameters dramatically change visual properties."
12848     "\n    Command is intended to control presentation quality depending on"
12849     "\n    hardware capabilities and performance.",
12850     __FILE__, VRenderParams, group);
12851   theCommands.Add("vstatprofiler",
12852     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
12853     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
12854     "\n                |triagles|points|geomMem|textureMem|frameMem"
12855     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
12856     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
12857     "\n                [-noredraw]"
12858     "\n\t\t: Prints rendering statistics."
12859     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
12860     "\n\t\t:   else - print all performance counters set previously."
12861     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
12862     __FILE__, VStatProfiler, group);
12863   theCommands.Add ("vplace",
12864             "vplace dx dy"
12865     "\n\t\t: Places the point (in pixels) at the center of the window",
12866     __FILE__, VPlace, group);
12867   theCommands.Add("vxrotate",
12868     "vxrotate",
12869     __FILE__,VXRotate,group);
12870
12871     theCommands.Add("vmanipulator",
12872       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
12873       "\n    tool to create and manage AIS manipulators."
12874       "\n    Options: "
12875       "\n      '-attach AISObject'                 attach manipulator to AISObject"
12876       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
12877       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
12878       "\n      '-enableModes    {0|1}'             enable modes when attaching"
12879       "\n      '-detach'                           detach manipulator"
12880       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
12881       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
12882       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
12883       "\n      '-move x y z'                     - move attached object"
12884       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
12885       "\n      '-scale factor'                   - scale attached object"
12886       "\n      '-autoActivate      {0|1}'        - set activation on detection"
12887       "\n      '-followTranslation {0|1}'        - set following translation transform"
12888       "\n      '-followRotation    {0|1}'        - set following rotation transform"
12889       "\n      '-gap value'                      - set gap between sub-parts"
12890       "\n      '-part axis mode    {0|1}'        - set visual part"
12891       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
12892       "\n      '-size value'                     - set size of manipulator"
12893       "\n      '-zoomable {0|1}'                 - set zoom persistence",
12894     __FILE__, VManipulator, group);
12895
12896   theCommands.Add("vselprops",
12897     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
12898     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
12899     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
12900     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
12901     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
12902     "\n    -pickStrategy {first|topmost} : defines picking strategy"
12903     "\n                            'first'   to pick first acceptable (default)"
12904     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
12905     "\n    -pixTol    value        : sets up pixel tolerance"
12906     "\n    -dispMode  dispMode     : sets display mode for highlighting"
12907     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
12908     "\n    -color     {name|r g b} : sets highlight color"
12909     "\n    -transp    value        : sets transparency coefficient for highlight"
12910     "\n    -material  material     : sets highlight material"
12911     "\n    -print                  : prints current state of all mentioned parameters",
12912     __FILE__, VSelectionProperties, group);
12913   theCommands.Add ("vhighlightselected",
12914                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
12915                    __FILE__, VSelectionProperties, group);
12916
12917   theCommands.Add ("vseldump",
12918                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
12919                    "\n\t\t: Generate an image based on detection results:"
12920                    "\n\t\t:   depth       normalized depth values"
12921                    "\n\t\t:   unnormDepth unnormalized depth values"
12922                    "\n\t\t:   object      color of detected object"
12923                    "\n\t\t:   owner       color of detected owner"
12924                    "\n\t\t:   selMode     color of selection mode"
12925                    "\n\t\t:   entity      color of etected entity",
12926                    __FILE__, VDumpSelectionImage, group);
12927
12928 #if defined(_WIN32)
12929   theCommands.Add("vprogressive",
12930     "vprogressive",
12931     __FILE__, VProgressiveMode, group);
12932 #endif
12933 }