0028369: Visualization, Path Tracing - Expose radiance clamping setting in path traci...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_ColorScale.hxx>
23 #include <AIS_Manipulator.hxx>
24 #include <AIS_RubberBand.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_InteractiveObject.hxx>
27 #include <AIS_ListOfInteractive.hxx>
28 #include <AIS_ListIteratorOfListOfInteractive.hxx>
29 #include <DBRep.hxx>
30 #include <Graphic3d_ArrayOfPolylines.hxx>
31 #include <Graphic3d_AspectMarker3d.hxx>
32 #include <Graphic3d_ExportFormat.hxx>
33 #include <Graphic3d_NameOfTextureEnv.hxx>
34 #include <Graphic3d_GraduatedTrihedron.hxx>
35 #include <Graphic3d_TextureEnv.hxx>
36 #include <Graphic3d_TextureParams.hxx>
37 #include <Graphic3d_TypeOfTextureFilter.hxx>
38 #include <Graphic3d_AspectFillArea3d.hxx>
39 #include <ViewerTest.hxx>
40 #include <ViewerTest_AutoUpdater.hxx>
41 #include <ViewerTest_EventManager.hxx>
42 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
43 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_CmdParser.hxx>
45 #include <V3d_AmbientLight.hxx>
46 #include <V3d_DirectionalLight.hxx>
47 #include <V3d_PositionalLight.hxx>
48 #include <V3d_SpotLight.hxx>
49 #include <NCollection_DoubleMap.hxx>
50 #include <NCollection_List.hxx>
51 #include <NCollection_Vector.hxx>
52 #include <AIS_InteractiveContext.hxx>
53 #include <Draw_Interpretor.hxx>
54 #include <Draw.hxx>
55 #include <Draw_Appli.hxx>
56 #include <Image_AlienPixMap.hxx>
57 #include <OpenGl_GraphicDriver.hxx>
58 #include <OSD_Timer.hxx>
59 #include <TColStd_HSequenceOfAsciiString.hxx>
60 #include <TColStd_SequenceOfInteger.hxx>
61 #include <TColStd_HSequenceOfReal.hxx>
62 #include <TColgp_Array1OfPnt2d.hxx>
63 #include <TColStd_MapOfAsciiString.hxx>
64 #include <Aspect_TypeOfLine.hxx>
65 #include <Image_Diff.hxx>
66 #include <Aspect_DisplayConnection.hxx>
67 #include <gp_Pnt.hxx>
68 #include <gp_Dir.hxx>
69 #include <gp_Pln.hxx>
70 #include <PrsMgr_PresentableObject.hxx>
71 #include <Graphic3d_ClipPlane.hxx>
72 #include <NCollection_DataMap.hxx>
73 #include <Graphic3d_Texture2Dmanual.hxx>
74 #include <Prs3d_ShadingAspect.hxx>
75 #include <Prs3d_Drawer.hxx>
76 #include <Prs3d_LineAspect.hxx>
77 #include <Prs3d_Root.hxx>
78
79 #ifdef _WIN32
80 #undef DrawText
81 #endif
82
83 #include <cstdlib>
84
85 #if defined(_WIN32)
86   #include <WNT_WClass.hxx>
87   #include <WNT_Window.hxx>
88 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
89   #include <Cocoa_Window.hxx>
90 #else
91   #include <Xw_Window.hxx>
92   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
93   #include <X11/Xutil.h>
94   #include <tk.h>
95 #endif
96
97 // Auxiliary definitions
98 static const char THE_KEY_DELETE = 127;
99
100 //==============================================================================
101 //  VIEWER GLOBAL VARIABLES
102 //==============================================================================
103
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
106
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
109
110 extern int VErase (Draw_Interpretor& theDI,
111                    Standard_Integer  theArgNb,
112                    const char**      theArgVec);
113
114 #if defined(_WIN32)
115 static Handle(WNT_Window)& VT_GetWindow() {
116   static Handle(WNT_Window) WNTWin;
117   return WNTWin;
118 }
119 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
120 static Handle(Cocoa_Window)& VT_GetWindow()
121 {
122   static Handle(Cocoa_Window) aWindow;
123   return aWindow;
124 }
125 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
126 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
127 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
128
129 #else
130 static Handle(Xw_Window)& VT_GetWindow(){
131   static Handle(Xw_Window) XWWin;
132   return XWWin;
133 }
134
135 static void VProcessEvents(ClientData,int);
136 #endif
137
138 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
139 {
140   static Handle(Aspect_DisplayConnection) aDisplayConnection;
141   return aDisplayConnection;
142 }
143
144 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
145 {
146   GetDisplayConnection() = theDisplayConnection;
147 }
148
149 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
150 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
151 {
152   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
153 #if defined(_WIN32)
154   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156     return aWindow->HWindow();
157 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
158   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
159   if (!aWindow.IsNull())
160   return aWindow->XWindow();
161 #endif
162   return aWindowHandle;
163 }
164 #endif
165
166 static Standard_Boolean MyHLRIsOn = Standard_False;
167
168 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
169 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
170 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
171 static OpenGl_Caps ViewerTest_myDefaultCaps;
172
173 static void OSWindowSetup();
174
175 static struct
176 {
177   Quantity_Color FlatColor;
178   Quantity_Color GradientColor1;
179   Quantity_Color GradientColor2;
180   Aspect_GradientFillMethod FillMethod;
181 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
182
183 //==============================================================================
184 //  EVENT GLOBAL VARIABLES
185 //==============================================================================
186
187 static int Start_Rot = 0;
188 int X_Motion = 0; // Current cursor position
189 int Y_Motion = 0;
190 int X_ButtonPress = 0; // Last ButtonPress position
191 int Y_ButtonPress = 0;
192 Standard_Boolean IsDragged = Standard_False;
193 Standard_Boolean DragFirst = Standard_False;
194 Standard_Boolean TheIsAnimating = Standard_False;
195
196
197 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
198 {
199   static Handle(AIS_RubberBand) aBand;
200   if (aBand.IsNull())
201   {
202     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
203     aBand->SetDisplayMode (0);
204   }
205   return aBand;
206 }
207
208 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
209
210 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
211 {
212   static ViewerTest_MapOfAISManipulators aMap;
213   return aMap;
214 }
215
216 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
217 {
218   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
219   for (; anIt.More(); anIt.Next())
220   {
221     if (anIt.Value()->HasActiveMode())
222     {
223       return anIt.Value();
224     }
225   }
226   return NULL;
227 }
228
229 //==============================================================================
230
231 #ifdef _WIN32
232 static LRESULT WINAPI ViewerWindowProc(
233                                        HWND hwnd,
234                                        UINT uMsg,
235                                        WPARAM wParam,
236                                        LPARAM lParam );
237 static LRESULT WINAPI AdvViewerWindowProc(
238   HWND hwnd,
239   UINT uMsg,
240   WPARAM wParam,
241   LPARAM lParam );
242 #endif
243
244
245 //==============================================================================
246 //function : WClass
247 //purpose  :
248 //==============================================================================
249
250 const Handle(Standard_Transient)& ViewerTest::WClass()
251 {
252   static Handle(Standard_Transient) theWClass;
253 #if defined(_WIN32)
254   if (theWClass.IsNull())
255   {
256     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
257                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
258                                 ::LoadCursorW (NULL, IDC_ARROW));
259   }
260 #endif
261   return theWClass;
262 }
263
264 //==============================================================================
265 //function : CreateName
266 //purpose  : Create numerical name for new object in theMap
267 //==============================================================================
268 template <typename ObjectType>
269 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
270                                     const TCollection_AsciiString& theDefaultString)
271 {
272   if (theObjectMap.IsEmpty())
273     return theDefaultString + TCollection_AsciiString(1);
274
275   Standard_Integer aNextKey = 1;
276   Standard_Boolean isFound = Standard_False;
277   while (!isFound)
278   {
279     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
280     // Look for objects with default names
281     if (theObjectMap.IsBound1(aStringKey))
282     {
283       aNextKey++;
284     }
285     else
286       isFound = Standard_True;
287   }
288
289   return theDefaultString + TCollection_AsciiString(aNextKey);
290 }
291
292 //==============================================================================
293 //structure : ViewerTest_Names
294 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
295 //==============================================================================
296 struct ViewerTest_Names
297 {
298 private:
299   TCollection_AsciiString myDriverName;
300   TCollection_AsciiString myViewerName;
301   TCollection_AsciiString myViewName;
302
303 public:
304
305   const TCollection_AsciiString& GetDriverName () const
306   {
307     return myDriverName;
308   }
309   void SetDriverName (const TCollection_AsciiString& theDriverName)
310   {
311     myDriverName = theDriverName;
312   }
313   const TCollection_AsciiString& GetViewerName () const
314   {
315     return myViewerName;
316   }
317   void SetViewerName (const TCollection_AsciiString& theViewerName)
318   {
319     myViewerName = theViewerName;
320   }
321   const TCollection_AsciiString& GetViewName () const
322   {
323     return myViewName;
324   }
325   void SetViewName (const TCollection_AsciiString& theViewName)
326   {
327     myViewName = theViewName;
328   }
329
330   //===========================================================================
331   //function : Constructor for ViewerTest_Names
332   //purpose  : Get view, viewer, driver names from custom string
333   //===========================================================================
334
335   ViewerTest_Names (const TCollection_AsciiString& theInputString)
336   {
337     TCollection_AsciiString aName(theInputString);
338     if (theInputString.IsEmpty())
339     {
340       // Get current configuration
341       if (ViewerTest_myDrivers.IsEmpty())
342         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
343           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
344       else
345         myDriverName = ViewerTest_myDrivers.Find2
346         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
347
348       if(ViewerTest_myContexts.IsEmpty())
349       {
350         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
351           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
352       }
353       else
354         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
355
356         myViewName = CreateName <Handle(V3d_View)>
357           (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
358     }
359     else
360     {
361       // There is at least view name
362       Standard_Integer aParserNumber = 0;
363       for (Standard_Integer i = 0; i < 3; ++i)
364       {
365         Standard_Integer aParserPos = aName.SearchFromEnd("/");
366         if(aParserPos != -1)
367         {
368           aParserNumber++;
369           aName.Split(aParserPos-1);
370         }
371         else
372           break;
373       }
374       if (aParserNumber == 0)
375       {
376         // Only view name
377         if (!ViewerTest::GetAISContext().IsNull())
378         {
379           myDriverName = ViewerTest_myDrivers.Find2
380           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
381           myViewerName = ViewerTest_myContexts.Find2
382           (ViewerTest::GetAISContext());
383         }
384         else
385         {
386           // There is no opened contexts here, need to create names for viewer and driver
387           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
388             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
389
390           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
391             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
392         }
393         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
394       }
395       else if (aParserNumber == 1)
396       {
397         // Here is viewerName/viewName
398         if (!ViewerTest::GetAISContext().IsNull())
399           myDriverName = ViewerTest_myDrivers.Find2
400           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
401         else
402         {
403           // There is no opened contexts here, need to create name for driver
404           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
405             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
406         }
407         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
408
409         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
410       }
411       else
412       {
413         //Here is driverName/viewerName/viewName
414         myDriverName = TCollection_AsciiString(aName);
415
416         TCollection_AsciiString aViewerName(theInputString);
417         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
418         myViewerName = TCollection_AsciiString(aViewerName);
419
420         myViewName = TCollection_AsciiString(theInputString);
421       }
422     }
423   }
424 };
425
426 //==============================================================================
427 //function : FindContextByView
428 //purpose  : Find AIS_InteractiveContext by View
429 //==============================================================================
430
431 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
432 {
433   Handle(AIS_InteractiveContext) anAISContext;
434
435   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
436        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
437   {
438     if (anIter.Value()->CurrentViewer() == theView->Viewer())
439        return anIter.Key2();
440   }
441   return anAISContext;
442 }
443
444
445 //==============================================================================
446 //function : SetWindowTitle
447 //purpose  : Set window title
448 //==============================================================================
449
450 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
451                      Standard_CString theTitle)
452 {
453 #if defined(_WIN32)
454   const TCollection_ExtendedString theTitleW (theTitle);
455   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
456 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
457   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
458 #else
459   if(GetDisplayConnection()->GetDisplay())
460   {
461     Window aWindow =
462       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
463     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
464   }
465 #endif
466 }
467
468 //==============================================================================
469 //function : IsWindowOverlapped
470 //purpose  : Check if theWindow overlapp another view
471 //==============================================================================
472
473 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
474                                      const Standard_Integer thePxTop,
475                                      const Standard_Integer thePxRight,
476                                      const Standard_Integer thePxBottom,
477                                      TCollection_AsciiString& theViewId)
478 {
479   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
480       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
481   {
482     Standard_Integer aTop = 0,
483       aLeft = 0,
484       aRight = 0,
485       aBottom = 0;
486     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
487     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
488         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
489         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
490         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
491     {
492       theViewId = anIter.Key1();
493       return Standard_True;
494     }
495   }
496   return Standard_False;
497 }
498
499 // Workaround: to create and delete non-orthographic views outside ViewerTest
500 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
501 {
502   ViewerTest_myViews.UnBind1 (theName);
503 }
504
505 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
506                                const Handle(V3d_View)& theView)
507 {
508   ViewerTest_myViews.Bind (theName, theView);
509 }
510
511 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
512 {
513   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
514 }
515 //==============================================================================
516 //function : ViewerInit
517 //purpose  : Create the window viewer and initialize all the global variable
518 //==============================================================================
519
520 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
521                                                 const Standard_Integer thePxTop,
522                                                 const Standard_Integer thePxWidth,
523                                                 const Standard_Integer thePxHeight,
524                                                 Standard_CString theViewName,
525                                                 Standard_CString theDisplayName)
526 {
527   // Default position and dimension of the viewer window.
528   // Note that left top corner is set to be sufficiently small to have
529   // window fit in the small screens (actual for remote desktops, see #23003).
530   // The position corresponds to the window's client area, thus some
531   // gap is added for window frame to be visible.
532   Standard_Integer aPxLeft   = 20;
533   Standard_Integer aPxTop    = 40;
534   Standard_Integer aPxWidth  = 409;
535   Standard_Integer aPxHeight = 409;
536   Standard_Boolean toCreateViewer = Standard_False;
537
538   Handle(OpenGl_GraphicDriver) aGraphicDriver;
539   ViewerTest_Names aViewNames(theViewName);
540   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
541     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
542
543   if (thePxLeft != 0)
544     aPxLeft = thePxLeft;
545   if (thePxTop != 0)
546     aPxTop = thePxTop;
547   if (thePxWidth != 0)
548     aPxWidth = thePxWidth;
549   if (thePxHeight != 0)
550     aPxHeight = thePxHeight;
551
552   // Get graphic driver (create it or get from another view)
553   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
554   {
555     // Get connection string
556   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
557     TCollection_AsciiString aDisplayName(theDisplayName);
558     if (!aDisplayName.IsEmpty())
559       SetDisplayConnection (new Aspect_DisplayConnection ());
560     else
561       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
562   #else
563     (void)theDisplayName; // avoid warning on unused argument
564     SetDisplayConnection (new Aspect_DisplayConnection ());
565   #endif
566
567     if (Draw_VirtualWindows)
568     {
569       // don't waste the time waiting for VSync when window is not displayed on the screen
570       ViewerTest_myDefaultCaps.swapInterval = 0;
571       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
572       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
573     }
574     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
575     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
576
577     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
578     toCreateViewer = Standard_True;
579   }
580   else
581   {
582     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
583   }
584
585   //Dispose the window if input parameters are default
586   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
587   {
588     Standard_Integer aTop = 0,
589                      aLeft = 0,
590                      aRight = 0,
591                      aBottom = 0,
592                      aScreenWidth = 0,
593                      aScreenHeight = 0;
594
595     // Get screen resolution
596 #if defined(_WIN32) || defined(__WIN32__)
597     RECT aWindowSize;
598     GetClientRect(GetDesktopWindow(), &aWindowSize);
599     aScreenHeight = aWindowSize.bottom;
600     aScreenWidth = aWindowSize.right;
601 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
602     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
603 #else
604     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
605     aScreenWidth = WidthOfScreen(aScreen);
606     aScreenHeight = HeightOfScreen(aScreen);
607 #endif
608
609     TCollection_AsciiString anOverlappedViewId("");
610
611     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
612     {
613       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
614
615       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
616         && aRight + 2*aPxWidth + 40 > aScreenWidth)
617       {
618         if (aBottom + aPxHeight + 40 > aScreenHeight)
619         {
620           aPxLeft = 20;
621           aPxTop = 40;
622           break;
623         }
624         aPxLeft = 20;
625         aPxTop = aBottom + 40;
626       }
627       else
628         aPxLeft = aRight + 20;
629     }
630   }
631
632   // Get viewer name
633   TCollection_AsciiString aTitle("3D View - ");
634   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
635
636   // Change name of current active window
637   if (!ViewerTest::CurrentView().IsNull())
638   {
639     TCollection_AsciiString anActiveWindowTitle("3D View - ");
640     anActiveWindowTitle = anActiveWindowTitle
641       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
642     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
643   }
644
645   // Create viewer
646   Handle(V3d_Viewer) a3DViewer;
647   // If it's the single view, we first look for empty context
648   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
649   {
650     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
651       anIter(ViewerTest_myContexts);
652     if (anIter.More())
653       ViewerTest::SetAISContext (anIter.Value());
654     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
655   }
656   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
657   {
658     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
659     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
660   }
661   else if (a3DViewer.IsNull())
662   {
663     toCreateViewer = Standard_True;
664     a3DViewer = new V3d_Viewer(aGraphicDriver);
665     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
666     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
667                                            ViewerTest_DefaultBackground.GradientColor2,
668                                            ViewerTest_DefaultBackground.FillMethod);
669   }
670
671   // AIS context setup
672   if (ViewerTest::GetAISContext().IsNull() ||
673       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
674   {
675     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
676     ViewerTest::SetAISContext (aContext);
677     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
678   }
679   else
680   {
681     ViewerTest::ResetEventManager();
682   }
683
684   // Create window
685 #if defined(_WIN32)
686   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
687                                     Handle(WNT_WClass)::DownCast (WClass()),
688                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
689                                     aPxLeft, aPxTop,
690                                     aPxWidth, aPxHeight,
691                                     Quantity_NOC_BLACK);
692 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
693   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
694                                      aPxLeft, aPxTop,
695                                      aPxWidth, aPxHeight);
696   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
697 #else
698   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
699                                   aTitle.ToCString(),
700                                   aPxLeft, aPxTop,
701                                   aPxWidth, aPxHeight);
702 #endif
703   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
704
705   // View setup
706   Handle(V3d_View) aView = a3DViewer->CreateView();
707   aView->SetWindow (VT_GetWindow());
708   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
709
710   ViewerTest::CurrentView(aView);
711   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
712
713   // Setup for X11 or NT
714   OSWindowSetup();
715
716   // Set parameters for V3d_View and V3d_Viewer
717   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
718   aV3dView->SetComputedMode(Standard_False);
719   MyHLRIsOn = aV3dView->ComputedMode();
720
721   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
722   if (toCreateViewer)
723   {
724     a3DViewer->SetDefaultLights();
725     a3DViewer->SetLightOn();
726   }
727
728   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
729   #if TCL_MAJOR_VERSION  < 8
730   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
731       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
732   #else
733   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
734       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
735   #endif
736   #endif
737
738   VT_GetWindow()->Map();
739
740   // Set the handle of created view in the event manager
741   ViewerTest::ResetEventManager();
742
743   ViewerTest::CurrentView()->Redraw();
744
745   aView.Nullify();
746   a3DViewer.Nullify();
747
748   return aViewNames.GetViewName();
749 }
750
751 //==============================================================================
752 //function : RedrawAllViews
753 //purpose  : Redraw all created views
754 //==============================================================================
755 void ViewerTest::RedrawAllViews()
756 {
757   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
758   for (; aViewIt.More(); aViewIt.Next())
759   {
760     const Handle(V3d_View)& aView = aViewIt.Key2();
761     aView->Redraw();
762   }
763 }
764
765 //==============================================================================
766 //function : Vinit
767 //purpose  : Create the window viewer and initialize all the global variable
768 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
769 //==============================================================================
770
771 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
772 {
773   if (theArgsNb > 9)
774   {
775     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
776               << "Type help for more information.\n";
777     return 1;
778   }
779
780   TCollection_AsciiString aViewName, aDisplayName;
781   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
782   TCollection_AsciiString aName, aValue;
783   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
784   {
785     const TCollection_AsciiString anArg = theArgVec[anArgIt];
786     TCollection_AsciiString anArgCase = anArg;
787     anArgCase.UpperCase();
788     if (ViewerTest::SplitParameter (anArg, aName, aValue))
789     {
790       aName.UpperCase();
791       if (aName.IsEqual ("NAME"))
792       {
793         aViewName = aValue;
794       }
795       else if (aName.IsEqual ("L")
796             || aName.IsEqual ("LEFT"))
797       {
798         aPxLeft = aValue.IntegerValue();
799       }
800       else if (aName.IsEqual ("T")
801             || aName.IsEqual ("TOP"))
802       {
803         aPxTop = aValue.IntegerValue();
804       }
805     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
806       else if (aName.IsEqual ("DISP")
807             || aName.IsEqual ("DISPLAY"))
808       {
809         aDisplayName = aValue;
810       }
811     #endif
812       else if (aName.IsEqual ("W")
813             || aName.IsEqual ("WIDTH"))
814       {
815         aPxWidth = aValue.IntegerValue();
816       }
817       else if (aName.IsEqual ("H")
818             || aName.IsEqual ("HEIGHT"))
819       {
820         aPxHeight = aValue.IntegerValue();
821       }
822       else
823       {
824         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
825       }
826     }
827     else if (aViewName.IsEmpty())
828     {
829       aViewName = anArg;
830     }
831     else
832     {
833       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
834     }
835   }
836
837   ViewerTest_Names aViewNames (aViewName);
838   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
839   {
840     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
841     theDi.Eval (aCommand.ToCString());
842     return 0;
843   }
844
845   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
846                                                             aViewName.ToCString(),
847                                                             aDisplayName.ToCString());
848   theDi << aViewId;
849   return 0;
850 }
851
852 //==============================================================================
853 //function : VHLR
854 //purpose  : hidden lines removal algorithm
855 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
856 //==============================================================================
857
858 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
859 {
860   if (ViewerTest::CurrentView().IsNull())
861   {
862     di << argv[0] << ": Call vinit before this command, please.\n";
863     return 1;
864   }
865
866   if (argc < 2)
867   {
868     di << argv[0] << ": Wrong number of command arguments.\n"
869       << "Type help " << argv[0] << " for more information.\n";
870     return 1;
871   }
872
873   // Enable or disable HLR mode.
874   Standard_Boolean isHLROn =
875     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
876
877   if (isHLROn != MyHLRIsOn)
878   {
879     MyHLRIsOn = isHLROn;
880     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
881   }
882
883   // Show or hide hidden lines in HLR mode.
884   Standard_Boolean isCurrentShowHidden
885     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
886
887   Standard_Boolean isShowHidden =
888     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
889                 : isCurrentShowHidden;
890
891
892   if (isShowHidden != isCurrentShowHidden)
893   {
894     if (isShowHidden)
895     {
896       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
897     }
898     else
899     {
900       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
901     }
902
903     // Redisplay shapes.
904     if (MyHLRIsOn)
905     {
906       AIS_ListOfInteractive aListOfShapes;
907       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
908
909       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
910       {
911         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
912         if (aShape.IsNull())
913         {
914           continue;
915         }
916         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
917       }
918     }
919   }
920
921   ViewerTest::CurrentView()->Update();
922   return 0;
923 }
924
925 //==============================================================================
926 //function : VHLRType
927 //purpose  : change type of using HLR algorithm
928 //==============================================================================
929
930 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
931 {
932   if (ViewerTest::CurrentView().IsNull())
933   {
934     di << argv[0] << ": Call vinit before this command, please.\n";
935     return 1;
936   }
937
938   if (argc < 2)
939   {
940     di << argv[0] << ": Wrong number of command arguments.\n"
941       << "Type help " << argv[0] << " for more information.\n";
942     return 1;
943   }
944
945   Prs3d_TypeOfHLR aTypeOfHLR =
946     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
947
948   if (argc == 2)
949   {
950     AIS_ListOfInteractive aListOfShapes;
951     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
952     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
953     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
954       anIter.More(); anIter.Next())
955     {
956       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
957       if (aShape.IsNull())
958         continue;
959       if (aShape->TypeOfHLR() != aTypeOfHLR)
960         aShape->SetTypeOfHLR (aTypeOfHLR);
961       if (MyHLRIsOn)
962         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
963     }
964     ViewerTest::CurrentView()->Update();
965     return 0;
966   }
967   else
968   {
969     for (Standard_Integer i = 2; i < argc; ++i)
970     {
971       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
972       TCollection_AsciiString aName (argv[i]);
973
974       if (!aMap.IsBound2 (aName))
975       {
976         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
977         continue;
978       }
979       Handle(AIS_Shape) anAISObject =
980         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
981       if (anAISObject.IsNull())
982         continue;
983       anAISObject->SetTypeOfHLR (aTypeOfHLR);
984       if (MyHLRIsOn)
985         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
986     }
987     ViewerTest::CurrentView()->Update();
988   }
989
990   return 0;
991 }
992
993 //==============================================================================
994 //function : FindViewIdByWindowHandle
995 //purpose  : Find theView Id in the map of views by window handle
996 //==============================================================================
997 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
998 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
999 {
1000   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1001        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1002   {
1003     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1004     if (aWindowHandle == theWindowHandle)
1005       return anIter.Key1();
1006   }
1007   return TCollection_AsciiString("");
1008 }
1009 #endif
1010
1011 //==============================================================================
1012 //function : ActivateView
1013 //purpose  : Make the view active
1014 //==============================================================================
1015
1016 void ActivateView (const TCollection_AsciiString& theViewName)
1017 {
1018   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1019   if (!aView.IsNull())
1020   {
1021     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1022     if (!anAISContext.IsNull())
1023     {
1024       if (!ViewerTest::CurrentView().IsNull())
1025       {
1026         TCollection_AsciiString aTitle("3D View - ");
1027         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1028         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1029       }
1030
1031       ViewerTest::CurrentView (aView);
1032       // Update degenerate mode
1033       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1034       ViewerTest::SetAISContext (anAISContext);
1035       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1036       aTitle = aTitle + theViewName + "(*)";
1037       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1038 #if defined(_WIN32) || defined(__WIN32__)
1039       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1040 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1041       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1042 #else
1043       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1044 #endif
1045       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1046       ViewerTest::CurrentView()->Redraw();
1047     }
1048   }
1049 }
1050
1051 //==============================================================================
1052 //function : RemoveView
1053 //purpose  :
1054 //==============================================================================
1055 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1056                              const Standard_Boolean  theToRemoveContext)
1057 {
1058   if (!ViewerTest_myViews.IsBound2 (theView))
1059   {
1060     return;
1061   }
1062
1063   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1064   RemoveView (aViewName, theToRemoveContext);
1065 }
1066
1067 //==============================================================================
1068 //function : RemoveView
1069 //purpose  : Close and remove view from display, clear maps if neccessary
1070 //==============================================================================
1071 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1072 {
1073   if (!ViewerTest_myViews.IsBound1(theViewName))
1074   {
1075     cout << "Wrong view name\n";
1076     return;
1077   }
1078
1079   // Activate another view if it's active now
1080   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1081   {
1082     if (ViewerTest_myViews.Extent() > 1)
1083     {
1084       TCollection_AsciiString aNewViewName;
1085       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
1086            anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1087         if (anIter.Key1() != theViewName)
1088         {
1089           aNewViewName = anIter.Key1();
1090           break;
1091         }
1092         ActivateView (aNewViewName);
1093     }
1094     else
1095     {
1096       Handle(V3d_View) anEmptyView;
1097 #if defined(_WIN32) || defined(__WIN32__)
1098       Handle(WNT_Window) anEmptyWindow;
1099 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1100       Handle(Cocoa_Window) anEmptyWindow;
1101 #else
1102       Handle(Xw_Window) anEmptyWindow;
1103 #endif
1104       VT_GetWindow() = anEmptyWindow;
1105       ViewerTest::CurrentView (anEmptyView);
1106       if (isContextRemoved)
1107       {
1108         Handle(AIS_InteractiveContext) anEmptyContext;
1109         ViewerTest::SetAISContext(anEmptyContext);
1110       }
1111     }
1112   }
1113
1114   // Delete view
1115   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1116   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1117
1118   // Remove view resources
1119   ViewerTest_myViews.UnBind1(theViewName);
1120   aView->Remove();
1121
1122 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1123   XFlush (GetDisplayConnection()->GetDisplay());
1124 #endif
1125
1126   // Keep context opened only if the closed view is last to avoid
1127   // unused empty contexts
1128   if (!aCurrentContext.IsNull())
1129   {
1130     // Check if there are more difined views in the viewer
1131     aCurrentContext->CurrentViewer()->InitDefinedViews();
1132     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1133     {
1134       // Remove driver if there is no viewers that use it
1135       Standard_Boolean isRemoveDriver = Standard_True;
1136       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1137           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1138       {
1139         if (aCurrentContext != anIter.Key2() &&
1140           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1141         {
1142           isRemoveDriver = Standard_False;
1143           break;
1144         }
1145       }
1146
1147       aCurrentContext->RemoveAll (Standard_False);
1148       if(isRemoveDriver)
1149       {
1150         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1151       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1152         #if TCL_MAJOR_VERSION  < 8
1153         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1154         #else
1155         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1156         #endif
1157       #endif
1158       }
1159
1160       ViewerTest_myContexts.UnBind2(aCurrentContext);
1161     }
1162   }
1163   cout << "3D View - " << theViewName << " was deleted.\n";
1164
1165 }
1166
1167 //==============================================================================
1168 //function : VClose
1169 //purpose  : Remove the view defined by its name
1170 //==============================================================================
1171
1172 static int VClose (Draw_Interpretor& /*theDi*/,
1173                    Standard_Integer  theArgsNb,
1174                    const char**      theArgVec)
1175 {
1176   NCollection_List<TCollection_AsciiString> aViewList;
1177   if (theArgsNb > 1)
1178   {
1179     TCollection_AsciiString anArg (theArgVec[1]);
1180     anArg.UpperCase();
1181     if (anArg.IsEqual ("ALL")
1182      || anArg.IsEqual ("*"))
1183     {
1184       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1185            anIter.More(); anIter.Next())
1186       {
1187         aViewList.Append (anIter.Key1());
1188       }
1189       if (aViewList.IsEmpty())
1190       {
1191         std::cout << "No view to close\n";
1192         return 0;
1193       }
1194     }
1195     else
1196     {
1197       ViewerTest_Names aViewName (theArgVec[1]);
1198       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1199       {
1200         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1201         return 1;
1202       }
1203       aViewList.Append (aViewName.GetViewName());
1204     }
1205   }
1206   else
1207   {
1208     // close active view
1209     if (ViewerTest::CurrentView().IsNull())
1210     {
1211       std::cerr << "No active view!\n";
1212       return 1;
1213     }
1214     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1215   }
1216
1217   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1218   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1219        anIter.More(); anIter.Next())
1220   {
1221     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1222   }
1223
1224   return 0;
1225 }
1226
1227 //==============================================================================
1228 //function : VActivate
1229 //purpose  : Activate the view defined by its ID
1230 //==============================================================================
1231
1232 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1233 {
1234   if (theArgsNb > 2)
1235   {
1236     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1237     << "Usage: " << theArgVec[0] << " ViewID\n";
1238     return 1;
1239   }
1240   if(theArgsNb == 1)
1241   {
1242     theDi.Eval("vviewlist");
1243     return 0;
1244   }
1245
1246   TCollection_AsciiString aNameString(theArgVec[1]);
1247   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1248   {
1249     TCollection_AsciiString aTitle("3D View - ");
1250     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1251     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1252     Handle(V3d_View) anEmptyView;
1253 #if defined(_WIN32) || defined(__WIN32__)
1254     Handle(WNT_Window) anEmptyWindow;
1255 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1256     Handle(Cocoa_Window) anEmptyWindow;
1257 #else
1258     Handle(Xw_Window) anEmptyWindow;
1259 #endif
1260     VT_GetWindow() = anEmptyWindow;
1261     ViewerTest::CurrentView (anEmptyView);
1262     ViewerTest::ResetEventManager();
1263     theDi << theArgVec[0] << ": all views are inactive\n";
1264     return 0;
1265   }
1266
1267   ViewerTest_Names aViewNames(aNameString);
1268
1269   // Check if this view exists in the viewer with the driver
1270   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1271   {
1272     theDi << "Wrong view name\n";
1273     return 1;
1274   }
1275
1276   // Check if it is active already
1277   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1278   {
1279     theDi << theArgVec[0] << ": the view is active already\n";
1280     return 0;
1281   }
1282
1283   ActivateView (aViewNames.GetViewName());
1284   return 0;
1285 }
1286
1287 //==============================================================================
1288 //function : VViewList
1289 //purpose  : Print current list of views per viewer and graphic driver ID
1290 //           shared between viewers
1291 //==============================================================================
1292
1293 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1294 {
1295   if (theArgsNb > 2)
1296   {
1297     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1298           << "Usage: " << theArgVec[0] << " name";
1299     return 1;
1300   }
1301   if (ViewerTest_myContexts.Size() < 1)
1302     return 0;
1303
1304   Standard_Boolean isTreeView =
1305     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1306
1307   if (isTreeView)
1308     theDi << theArgVec[0] <<":\n";
1309
1310     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
1311       aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
1312     {
1313       if (isTreeView)
1314         theDi << aDriverIter.Key1() << ":\n";
1315
1316       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1317         aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1318       {
1319         if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1320         {
1321           if (isTreeView)
1322           {
1323             TCollection_AsciiString aContextName(aContextIter.Key1());
1324             theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1325           }
1326
1327           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1328             aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
1329           {
1330             if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1331             {
1332               TCollection_AsciiString aViewName(aViewIter.Key1());
1333               if (isTreeView)
1334               {
1335                 if (aViewIter.Value() == ViewerTest::CurrentView())
1336                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1337                 else
1338                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1339               }
1340               else
1341               {
1342                 theDi << aViewName << " ";
1343               }
1344             }
1345           }
1346         }
1347       }
1348     }
1349   return 0;
1350 }
1351
1352 //==============================================================================
1353 //function : VT_ProcessKeyPress
1354 //purpose  : Handle KeyPress event from a CString
1355 //==============================================================================
1356 void VT_ProcessKeyPress (const char* buf_ret)
1357 {
1358   //cout << "KeyPress" << endl;
1359   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1360   // Letter in alphabetic order
1361
1362   if (!strcasecmp (buf_ret, "A"))
1363   {
1364     // AXO
1365     aView->SetProj(V3d_XposYnegZpos);
1366   }
1367   else if (!strcasecmp (buf_ret, "D"))
1368   {
1369     // Reset
1370     aView->Reset();
1371   }
1372   else if (!strcasecmp (buf_ret, "F"))
1373   {
1374     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1375     {
1376       ViewerTest::GetAISContext()->FitSelected (aView);
1377     }
1378     else
1379     {
1380       // FitAll
1381       aView->FitAll();
1382     }
1383   }
1384   else if (!strcasecmp (buf_ret, "H"))
1385   {
1386     // HLR
1387     cout << "HLR" << endl;
1388     aView->SetComputedMode (!aView->ComputedMode());
1389     MyHLRIsOn = aView->ComputedMode();
1390   }
1391   else if (!strcasecmp (buf_ret, "P"))
1392   {
1393     // Type of HLR
1394     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1395     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1396       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1397     else
1398       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1399     if (aContext->NbSelected()==0)
1400     {
1401       AIS_ListOfInteractive aListOfShapes;
1402       aContext->DisplayedObjects(aListOfShapes);
1403       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1404         anIter.More(); anIter.Next())
1405       {
1406         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1407         if (aShape.IsNull())
1408           continue;
1409         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1410           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1411         else
1412           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1413         aContext->Redisplay (aShape, Standard_False);
1414       }
1415     }
1416     else
1417     {
1418       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1419       {
1420         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1421         if (aShape.IsNull())
1422           continue;
1423         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1424           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1425         else
1426           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1427         aContext->Redisplay (aShape, Standard_False);
1428       }
1429     }
1430
1431     aContext->UpdateCurrentViewer();
1432
1433   }
1434   else if (!strcasecmp (buf_ret, "S"))
1435   {
1436     std::cout << "setup Shaded display mode" << std::endl;
1437
1438     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1439     if(Ctx->NbSelected()==0)
1440       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1441     else{
1442       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1443         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1444       Ctx->UpdateCurrentViewer();
1445     }
1446   }
1447   else if (!strcasecmp (buf_ret, "U"))
1448   {
1449     // Unset display mode
1450     std::cout << "reset display mode to defaults" << std::endl;
1451
1452     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1453     if(Ctx->NbSelected()==0)
1454       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1455     else{
1456       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1457         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1458       Ctx->UpdateCurrentViewer();
1459     }
1460
1461   }
1462   else if (!strcasecmp (buf_ret, "T"))
1463   {
1464     // Top
1465     aView->SetProj(V3d_Zpos);
1466   }
1467   else if (!strcasecmp (buf_ret, "B"))
1468   {
1469     // Bottom
1470     aView->SetProj(V3d_Zneg);
1471   }
1472   else if (!strcasecmp (buf_ret, "L"))
1473   {
1474     // Left
1475     aView->SetProj(V3d_Xneg);
1476   }
1477   else if (!strcasecmp (buf_ret, "R"))
1478   {
1479     // Right
1480     aView->SetProj(V3d_Xpos);
1481   }
1482   else if (!strcasecmp (buf_ret, "W"))
1483   {
1484     std::cout << "setup WireFrame display mode" << std::endl;
1485     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1486     if(Ctx->NbSelected()==0)
1487       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1488     else{
1489       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1490         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1491       Ctx->UpdateCurrentViewer();
1492     }
1493   }
1494   else if (!strcasecmp (buf_ret, ","))
1495   {
1496     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1497   }
1498   else if (!strcasecmp (buf_ret, "."))
1499   {
1500     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1501   }
1502   else if (!strcasecmp (buf_ret, "/"))
1503   {
1504     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1505     if (aCamera->IsStereo())
1506     {
1507       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1508       aView->Redraw();
1509     }
1510   }
1511   else if (!strcasecmp (buf_ret, "*"))
1512   {
1513     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1514     if (aCamera->IsStereo())
1515     {
1516       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1517       aView->Redraw();
1518     }
1519   }
1520   else if (*buf_ret == THE_KEY_DELETE)
1521   {
1522     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1523     if (!aCtx.IsNull()
1524      && aCtx->NbSelected() > 0)
1525     {
1526       Draw_Interprete ("verase");
1527     }
1528   }
1529   else
1530   {
1531     // Number
1532     Standard_Integer Num = Draw::Atoi(buf_ret);
1533     if(Num>=0 && Num<=7)
1534       ViewerTest::StandardModeActivation(Num);
1535   }
1536 }
1537
1538 //==============================================================================
1539 //function : VT_ProcessExpose
1540 //purpose  : Redraw the View on an Expose Event
1541 //==============================================================================
1542 void VT_ProcessExpose()
1543 {
1544   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1545   if (!aView3d.IsNull())
1546   {
1547     aView3d->Redraw();
1548   }
1549 }
1550
1551 //==============================================================================
1552 //function : VT_ProcessConfigure
1553 //purpose  : Resize the View on an Configure Event
1554 //==============================================================================
1555 void VT_ProcessConfigure()
1556 {
1557   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1558   if (aView3d.IsNull())
1559   {
1560     return;
1561   }
1562
1563   aView3d->MustBeResized();
1564   aView3d->Update();
1565   aView3d->Redraw();
1566 }
1567
1568 //==============================================================================
1569 //function : VT_ProcessButton1Press
1570 //purpose  : Picking
1571 //==============================================================================
1572 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1573                                          const char**     theArgVec,
1574                                          Standard_Boolean theToPick,
1575                                          Standard_Boolean theIsShift)
1576 {
1577   if (TheIsAnimating)
1578   {
1579     TheIsAnimating = Standard_False;
1580     return Standard_False;
1581   }
1582
1583   if (theToPick)
1584   {
1585     Standard_Real X, Y, Z;
1586     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1587
1588     Draw::Set (theArgVec[1], X);
1589     Draw::Set (theArgVec[2], Y);
1590     Draw::Set (theArgVec[3], Z);
1591   }
1592
1593   if (theIsShift)
1594   {
1595     ViewerTest::CurrentEventManager()->ShiftSelect();
1596   }
1597   else
1598   {
1599     ViewerTest::CurrentEventManager()->Select();
1600   }
1601
1602   return Standard_False;
1603 }
1604
1605 //==============================================================================
1606 //function : VT_ProcessButton1Release
1607 //purpose  : End selecting
1608 //==============================================================================
1609 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1610 {
1611   if (IsDragged)
1612   {
1613     IsDragged = Standard_False;
1614     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1615     if (theIsShift)
1616     {
1617       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1618                        X_Motion, Y_Motion);
1619     }
1620     else
1621     {
1622       EM->Select (X_ButtonPress, Y_ButtonPress,
1623                   X_Motion, Y_Motion);
1624     }
1625   }
1626 }
1627
1628 //==============================================================================
1629 //function : VT_ProcessButton3Press
1630 //purpose  : Start Rotation
1631 //==============================================================================
1632 void VT_ProcessButton3Press()
1633 {
1634   Start_Rot = 1;
1635   if (MyHLRIsOn)
1636   {
1637     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1638   }
1639   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1640 }
1641
1642 //==============================================================================
1643 //function : VT_ProcessButton3Release
1644 //purpose  : End rotation
1645 //==============================================================================
1646 void VT_ProcessButton3Release()
1647 {
1648   if (Start_Rot)
1649   {
1650     Start_Rot = 0;
1651     if (MyHLRIsOn)
1652     {
1653       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1654     }
1655   }
1656 }
1657
1658 //==============================================================================
1659 //function : ProcessControlButton1Motion
1660 //purpose  : Zoom
1661 //==============================================================================
1662
1663 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1664 static void ProcessControlButton1Motion()
1665 {
1666   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1667
1668   X_ButtonPress = X_Motion;
1669   Y_ButtonPress = Y_Motion;
1670 }
1671 #endif
1672
1673 //==============================================================================
1674 //function : VT_ProcessControlButton2Motion
1675 //purpose  : Panning
1676 //==============================================================================
1677 void VT_ProcessControlButton2Motion()
1678 {
1679   Standard_Integer aDx = X_Motion - X_ButtonPress;
1680   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1681
1682   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1683
1684   ViewerTest::CurrentView()->Pan (aDx, aDy);
1685
1686   X_ButtonPress = X_Motion;
1687   Y_ButtonPress = Y_Motion;
1688 }
1689
1690 //==============================================================================
1691 //function : VT_ProcessControlButton3Motion
1692 //purpose  : Rotation
1693 //==============================================================================
1694 void VT_ProcessControlButton3Motion()
1695 {
1696   if (Start_Rot)
1697   {
1698     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1699   }
1700 }
1701
1702 //==============================================================================
1703 //function : VT_ProcessMotion
1704 //purpose  :
1705 //==============================================================================
1706 void VT_ProcessMotion()
1707 {
1708   //pre-hilights detected objects at mouse position
1709
1710   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1711   EM->MoveTo(X_Motion, Y_Motion);
1712 }
1713
1714
1715 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1716 {
1717   Xpix = X_Motion;Ypix=Y_Motion;
1718 }
1719
1720 //==============================================================================
1721 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1722 //purpose  : Switches to an axonometric, top, left and other views
1723 //==============================================================================
1724
1725 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1726 {
1727   if ( ViewerTest::CurrentView().IsNull() )
1728   {
1729     di<<"Call vinit before this command, please\n";
1730     return 1;
1731   }
1732
1733   ViewerTest::CurrentView()->SetProj(ori);
1734   return 0;
1735 }
1736
1737 //==============================================================================
1738 //function : VAxo
1739 //purpose  : Switch to an Axonometric view
1740 //Draw arg : No args
1741 //==============================================================================
1742
1743 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1744 {
1745   return ViewProject(di, V3d_XposYnegZpos);
1746 }
1747
1748 //==============================================================================
1749 //function : VTop
1750 //purpose  : Switch to a Top View
1751 //Draw arg : No args
1752 //==============================================================================
1753
1754 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1755 {
1756   return ViewProject(di, V3d_Zpos);
1757 }
1758
1759 //==============================================================================
1760 //function : VBottom
1761 //purpose  : Switch to a Bottom View
1762 //Draw arg : No args
1763 //==============================================================================
1764
1765 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1766 {
1767   return ViewProject(di, V3d_Zneg);
1768 }
1769
1770 //==============================================================================
1771 //function : VLeft
1772 //purpose  : Switch to a Left View
1773 //Draw arg : No args
1774 //==============================================================================
1775
1776 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1777 {
1778   return ViewProject(di, V3d_Xneg);
1779 }
1780
1781 //==============================================================================
1782 //function : VRight
1783 //purpose  : Switch to a Right View
1784 //Draw arg : No args
1785 //==============================================================================
1786
1787 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1788 {
1789   return ViewProject(di, V3d_Xpos);
1790 }
1791
1792 //==============================================================================
1793 //function : VFront
1794 //purpose  : Switch to a Front View
1795 //Draw arg : No args
1796 //==============================================================================
1797
1798 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1799 {
1800   return ViewProject(di, V3d_Yneg);
1801 }
1802
1803 //==============================================================================
1804 //function : VBack
1805 //purpose  : Switch to a Back View
1806 //Draw arg : No args
1807 //==============================================================================
1808
1809 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1810 {
1811   return ViewProject(di, V3d_Ypos);
1812 }
1813
1814 //==============================================================================
1815 //function : VHelp
1816 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1817 //Draw arg : No args
1818 //==============================================================================
1819
1820 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1821 {
1822
1823   di << "Q : Quit the application\n";
1824
1825   di << "=========================\n";
1826   di << "F : FitAll\n";
1827   di << "T : TopView\n";
1828   di << "B : BottomView\n";
1829   di << "R : RightView\n";
1830   di << "L : LeftView\n";
1831   di << "A : AxonometricView\n";
1832   di << "D : ResetView\n";
1833
1834   di << "=========================\n";
1835   di << "S : Shading\n";
1836   di << "W : Wireframe\n";
1837   di << "H : HidelLineRemoval\n";
1838   di << "U : Unset display mode\n";
1839   di << "Delete : Remove selection from viewer\n";
1840
1841   di << "=========================\n";
1842   di << "Selection mode \n";
1843   di << "0 : Shape\n";
1844   di << "1 : Vertex\n";
1845   di << "2 : Edge\n";
1846   di << "3 : Wire\n";
1847   di << "4 : Face\n";
1848   di << "5 : Shell\n";
1849   di << "6 : Solid\n";
1850   di << "7 : Compound\n";
1851
1852   di << "=========================\n";
1853   di << "Z : Switch Z clipping On/Off\n";
1854   di << ", : Hilight next detected\n";
1855   di << ". : Hilight previous detected\n";
1856
1857   return 0;
1858 }
1859
1860 #ifdef _WIN32
1861
1862 static Standard_Boolean Ppick = 0;
1863 static Standard_Integer Pargc = 0;
1864 static const char**           Pargv = NULL;
1865
1866
1867 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1868                                           UINT Msg,
1869                                           WPARAM wParam,
1870                                           LPARAM lParam )
1871 {
1872   if (!ViewerTest_myViews.IsEmpty()) {
1873
1874     WPARAM fwKeys = wParam;
1875
1876     switch( Msg ) {
1877     case WM_CLOSE:
1878        {
1879          // Delete view from map of views
1880          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1881          return 0;
1882        }
1883        break;
1884     case WM_ACTIVATE:
1885       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1886         || ViewerTest::CurrentView().IsNull())
1887       {
1888         // Activate inactive window
1889         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1890         {
1891           ActivateView (FindViewIdByWindowHandle(hwnd));
1892         }
1893       }
1894       break;
1895
1896     case WM_LBUTTONUP:
1897       if (IsDragged && !DragFirst)
1898       {
1899         if (!GetActiveAISManipulator().IsNull())
1900         {
1901           GetActiveAISManipulator()->StopTransform();
1902           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1903         }
1904
1905         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1906         {
1907           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1908           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1909         }
1910
1911         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1912       }
1913       IsDragged = Standard_False;
1914       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1915
1916     case WM_RBUTTONUP:
1917       if (IsDragged && !DragFirst)
1918       {
1919         if (!GetActiveAISManipulator().IsNull())
1920         {
1921           GetActiveAISManipulator()->StopTransform (Standard_False);
1922           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1923         }
1924         IsDragged = Standard_False;
1925       }
1926       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1927
1928     case WM_LBUTTONDOWN:
1929       if (!GetActiveAISManipulator().IsNull())
1930       {
1931         IsDragged = ( fwKeys == MK_LBUTTON );
1932       }
1933       else
1934       {
1935         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1936       }
1937
1938       if (IsDragged)
1939       {
1940         DragFirst = Standard_True;
1941         X_ButtonPress = LOWORD(lParam);
1942         Y_ButtonPress = HIWORD(lParam);
1943       }
1944       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1945
1946     case WM_MOUSEMOVE:
1947       if (IsDragged)
1948       {
1949         X_Motion = LOWORD (lParam);
1950         Y_Motion = HIWORD (lParam);
1951         if (!GetActiveAISManipulator().IsNull())
1952         {
1953           if (DragFirst)
1954           {
1955             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1956           }
1957           else
1958           {
1959             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1960             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1961           }
1962         }
1963         else
1964         {
1965           bool toRedraw = false;
1966           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1967           {
1968             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1969             toRedraw = true;
1970           }
1971
1972           RECT aRect;
1973           if (GetClientRect (hwnd, &aRect))
1974           {
1975             int aHeight = aRect.bottom - aRect.top;
1976             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1977             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1978             toRedraw = true;
1979           }
1980           if (toRedraw)
1981           {
1982             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1983           }
1984         }
1985
1986         DragFirst = Standard_False;
1987       }
1988       else
1989         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1990       break;
1991
1992     default:
1993       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1994     }
1995     return 0;
1996   }
1997   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1998 }
1999
2000
2001 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2002                                        UINT Msg,
2003                                        WPARAM wParam,
2004                                        LPARAM lParam )
2005 {
2006   static int Up = 1;
2007   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2008   if (aView.IsNull())
2009   {
2010     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2011   }
2012
2013     PAINTSTRUCT    ps;
2014
2015     switch( Msg ) {
2016     case WM_PAINT:
2017       BeginPaint(hwnd, &ps);
2018       EndPaint(hwnd, &ps);
2019       VT_ProcessExpose();
2020       break;
2021
2022     case WM_SIZE:
2023       VT_ProcessConfigure();
2024       break;
2025     case WM_MOVE:
2026     case WM_MOVING:
2027     case WM_SIZING:
2028       switch (aView->RenderingParams().StereoMode)
2029       {
2030         case Graphic3d_StereoMode_RowInterlaced:
2031         case Graphic3d_StereoMode_ColumnInterlaced:
2032         case Graphic3d_StereoMode_ChessBoard:
2033           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2034           break;
2035         default:
2036           break;
2037       }
2038       break;
2039
2040     case WM_KEYDOWN:
2041       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2042       {
2043         char c[2];
2044         c[0] = (char) wParam;
2045         c[1] = '\0';
2046         if (wParam == VK_DELETE)
2047         {
2048           c[0] = THE_KEY_DELETE;
2049         }
2050         // comma
2051         else if (wParam == VK_OEM_COMMA)
2052         {
2053           c[0] = ',';
2054         }
2055         // dot
2056         else if (wParam == VK_OEM_PERIOD)
2057         {
2058           c[0] = '.';
2059         }
2060         else if (wParam == VK_DIVIDE)
2061         {
2062           c[0] = '/';
2063         }
2064         // dot
2065         else if (wParam == VK_MULTIPLY)
2066         {
2067           c[0] = '*';
2068         }
2069         VT_ProcessKeyPress (c);
2070       }
2071       break;
2072
2073     case WM_LBUTTONUP:
2074     case WM_MBUTTONUP:
2075     case WM_RBUTTONUP:
2076       Up = 1;
2077       VT_ProcessButton3Release();
2078       break;
2079
2080     case WM_LBUTTONDOWN:
2081     case WM_MBUTTONDOWN:
2082     case WM_RBUTTONDOWN:
2083       {
2084         WPARAM fwKeys = wParam;
2085
2086         Up = 0;
2087
2088         X_ButtonPress = LOWORD(lParam);
2089         Y_ButtonPress = HIWORD(lParam);
2090
2091         if (Msg == WM_LBUTTONDOWN)
2092         {
2093           if ((fwKeys & MK_CONTROL) != 0)
2094           {
2095             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2096           }
2097           else
2098           {
2099             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2100           }
2101         }
2102         else if (Msg == WM_RBUTTONDOWN)
2103         {
2104           // Start rotation
2105           VT_ProcessButton3Press();
2106         }
2107       }
2108       break;
2109
2110     case WM_MOUSEWHEEL:
2111     {
2112       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2113       if (wParam & MK_CONTROL)
2114       {
2115         if (aView->Camera()->IsStereo())
2116         {
2117           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2118           if (aFocus > 0.2
2119            && aFocus < 2.0)
2120           {
2121             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2122             aView->Redraw();
2123           }
2124         }
2125       }
2126       else
2127       {
2128         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2129       }
2130       break;
2131     }
2132
2133     case WM_MOUSEMOVE:
2134       {
2135         //cout << "\t WM_MOUSEMOVE" << endl;
2136         WPARAM fwKeys = wParam;
2137         X_Motion = LOWORD(lParam);
2138         Y_Motion = HIWORD(lParam);
2139
2140         if ( Up &&
2141           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2142           {
2143             Up = 0;
2144             X_ButtonPress = LOWORD(lParam);
2145             Y_ButtonPress = HIWORD(lParam);
2146
2147             if ((fwKeys & MK_RBUTTON) != 0) {
2148               // Start rotation
2149               VT_ProcessButton3Press();
2150             }
2151           }
2152
2153           if ((fwKeys & MK_CONTROL) != 0)
2154           {
2155             if ((fwKeys & MK_LBUTTON) != 0)
2156             {
2157               ProcessControlButton1Motion();
2158             }
2159             else if ((fwKeys & MK_MBUTTON) != 0
2160                  || ((fwKeys & MK_LBUTTON) != 0
2161                   && (fwKeys & MK_RBUTTON) != 0))
2162             {
2163               VT_ProcessControlButton2Motion();
2164             }
2165             else if ((fwKeys & MK_RBUTTON) != 0)
2166             {
2167               VT_ProcessControlButton3Motion();
2168             }
2169           }
2170           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2171           {
2172             VT_ProcessMotion();
2173           }
2174       }
2175       break;
2176
2177     default:
2178       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2179     }
2180     return 0L;
2181 }
2182
2183 //==============================================================================
2184 //function : ViewerMainLoop
2185 //purpose  : Get a Event on the view and dispatch it
2186 //==============================================================================
2187
2188
2189 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2190 {
2191   Ppick = (argc > 0)? 1 : 0;
2192   Pargc = argc;
2193   Pargv = argv;
2194
2195   if ( Ppick ) {
2196     MSG msg;
2197     msg.wParam = 1;
2198
2199     cout << "Start picking" << endl;
2200
2201     while ( Ppick == 1 ) {
2202       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2203       if (GetMessageW (&msg, NULL, 0, 0))
2204       {
2205         TranslateMessage (&msg);
2206         DispatchMessageW (&msg);
2207       }
2208     }
2209
2210     cout << "Picking done" << endl;
2211   }
2212
2213   return Ppick;
2214 }
2215
2216 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2217
2218 int min( int a, int b )
2219 {
2220   if( a<b )
2221     return a;
2222   else
2223     return b;
2224 }
2225
2226 int max( int a, int b )
2227 {
2228   if( a>b )
2229     return a;
2230   else
2231     return b;
2232 }
2233
2234 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2235
2236 {
2237   static XEvent aReport;
2238   Standard_Boolean pick = argc > 0;
2239   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2240   XNextEvent (aDisplay, &aReport);
2241
2242   // Handle event for the chosen display connection
2243   switch (aReport.type) {
2244       case ClientMessage:
2245         {
2246           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2247           {
2248             // Close the window
2249             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2250           }
2251         }
2252         return 0;
2253      case FocusIn:
2254       {
2255          // Activate inactive view
2256          Window aWindow = GetWindowHandle(VT_GetWindow());
2257          if(aWindow != aReport.xfocus.window)
2258          {
2259            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2260          }
2261       }
2262       break;
2263       case Expose:
2264         {
2265           VT_ProcessExpose();
2266         }
2267         break;
2268       case ConfigureNotify:
2269         {
2270           VT_ProcessConfigure();
2271         }
2272         break;
2273       case KeyPress:
2274         {
2275
2276           KeySym ks_ret ;
2277           char buf_ret[11] ;
2278           int ret_len ;
2279           XComposeStatus status_in_out;
2280
2281           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2282             (char *) buf_ret , 10 ,
2283             &ks_ret , &status_in_out ) ;
2284
2285
2286           buf_ret[ret_len] = '\0' ;
2287
2288           if (ret_len)
2289           {
2290             VT_ProcessKeyPress (buf_ret);
2291           }
2292         }
2293         break;
2294       case ButtonPress:
2295         {
2296           X_ButtonPress = aReport.xbutton.x;
2297           Y_ButtonPress = aReport.xbutton.y;
2298
2299           if (aReport.xbutton.button == Button1)
2300           {
2301             if (aReport.xbutton.state & ControlMask)
2302             {
2303               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2304             }
2305             else
2306             {
2307               IsDragged = Standard_True;
2308               DragFirst = Standard_True;
2309             }
2310           }
2311           else if (aReport.xbutton.button == Button3)
2312           {
2313             // Start rotation
2314             VT_ProcessButton3Press();
2315           }
2316         }
2317         break;
2318       case ButtonRelease:
2319         {
2320           if( IsDragged )
2321           {
2322             if( !DragFirst )
2323             {
2324               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2325               {
2326                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2327                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2328               }
2329             }
2330
2331             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2332             if( aContext.IsNull() )
2333             {
2334               cout << "The context is null. Please use vinit before createmesh" << endl;
2335               return 0;
2336             }
2337
2338             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2339             if( aReport.xbutton.button==1 )
2340               if( DragFirst )
2341                 if( ShiftPressed )
2342                 {
2343                   aContext->ShiftSelect (Standard_True);
2344                 }
2345                 else
2346                 {
2347                   aContext->Select (Standard_True);
2348                 }
2349               else
2350                 if( ShiftPressed )
2351                 {
2352                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2353                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2354                                         ViewerTest::CurrentView(), Standard_True);
2355                 }
2356                 else
2357                 {
2358                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2359                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2360                                    ViewerTest::CurrentView(), Standard_True);
2361                 }
2362             else
2363               VT_ProcessButton3Release();
2364
2365             IsDragged = Standard_False;
2366           }
2367           else
2368             VT_ProcessButton3Release();
2369         }
2370         break;
2371       case MotionNotify:
2372         {
2373           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2374           {
2375             break;
2376           }
2377           if( IsDragged )
2378           {
2379             if( !DragFirst )
2380             {
2381               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2382               {
2383                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2384               }
2385             }
2386
2387             X_Motion = aReport.xmotion.x;
2388             Y_Motion = aReport.xmotion.y;
2389             DragFirst = Standard_False;
2390
2391             Window aWindow = GetWindowHandle(VT_GetWindow());
2392             Window aRoot;
2393             int anX, anY;
2394             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2395             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2396             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2397             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2398             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2399           }
2400           else
2401           {
2402             X_Motion = aReport.xmotion.x;
2403             Y_Motion = aReport.xmotion.y;
2404
2405             // remove all the ButtonMotionMaskr
2406             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2407
2408             if ( aReport.xmotion.state & ControlMask ) {
2409               if ( aReport.xmotion.state & Button1Mask ) {
2410                 ProcessControlButton1Motion();
2411               }
2412               else if ( aReport.xmotion.state & Button2Mask ) {
2413                 VT_ProcessControlButton2Motion();
2414               }
2415               else if ( aReport.xmotion.state & Button3Mask ) {
2416                 VT_ProcessControlButton3Motion();
2417               }
2418             }
2419             else
2420             {
2421               VT_ProcessMotion();
2422             }
2423           }
2424         }
2425         break;
2426 }
2427 return pick;
2428 }
2429
2430 //==============================================================================
2431 //function : VProcessEvents
2432 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2433 //       event in the Viewer window
2434 //==============================================================================
2435
2436 static void VProcessEvents(ClientData,int)
2437 {
2438   NCollection_Vector<int> anEventNumbers;
2439   // Get number of messages from every display
2440   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2441        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2442   {
2443     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2444   }
2445     // Handle events for every display
2446   int anEventIter = 0;
2447   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2448        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2449   {
2450     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2451          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2452     {
2453       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2454       int anEventResult = ViewerMainLoop( 0, NULL);
2455       // If window is closed or context was not found finish current event processing loop
2456       if (!anEventResult)
2457         return;
2458     }
2459   }
2460
2461   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2462
2463 }
2464 #endif
2465
2466 //==============================================================================
2467 //function : OSWindowSetup
2468 //purpose  : Setup for the X11 window to be able to cath the event
2469 //==============================================================================
2470
2471
2472 static void OSWindowSetup()
2473 {
2474 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2475   // X11
2476
2477   Window  window   = VT_GetWindow()->XWindow();
2478   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2479   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2480   XSynchronize(aDisplay, 1);
2481
2482   // X11 : For keyboard on SUN
2483   XWMHints wmhints;
2484   wmhints.flags = InputHint;
2485   wmhints.input = 1;
2486
2487   XSetWMHints( aDisplay, window, &wmhints);
2488
2489   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2490     ButtonPressMask | ButtonReleaseMask |
2491     StructureNotifyMask |
2492     PointerMotionMask |
2493     Button1MotionMask | Button2MotionMask |
2494     Button3MotionMask | FocusChangeMask
2495     );
2496   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2497   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2498
2499   XSynchronize(aDisplay, 0);
2500
2501 #else
2502   // _WIN32
2503 #endif
2504
2505 }
2506
2507 //==============================================================================
2508 //function : VFit
2509 //purpose  :
2510 //==============================================================================
2511
2512 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2513 {
2514   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2515   if (aView.IsNull())
2516   {
2517     std::cout << "Error: no active viewer!\n";
2518     return 1;
2519   }
2520
2521   Standard_Boolean toFit = Standard_True;
2522   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2523   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2524   {
2525     TCollection_AsciiString anArg (theArgv[anArgIter]);
2526     anArg.LowerCase();
2527     if (anUpdateTool.parseRedrawMode (anArg))
2528     {
2529       continue;
2530     }
2531     else if (anArg == "-selected")
2532     {
2533       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2534       toFit = Standard_False;
2535     }
2536     else
2537     {
2538       std::cout << "Syntax error at '" << anArg << "'\n";
2539     }
2540   }
2541
2542   if (toFit)
2543   {
2544     aView->FitAll (0.01, Standard_False);
2545   }
2546   return 0;
2547 }
2548
2549 //=======================================================================
2550 //function : VFitArea
2551 //purpose  : Fit view to show area located between two points
2552 //         : given in world 2D or 3D coordinates.
2553 //=======================================================================
2554 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2555 {
2556   Handle(V3d_View) aView = ViewerTest::CurrentView();
2557   if (aView.IsNull())
2558   {
2559     std::cerr << theArgVec[0] << "Error: No active view.\n";
2560     return 1;
2561   }
2562
2563   // Parse arguments.
2564   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2565   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2566
2567   if (theArgNb == 5)
2568   {
2569     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2570     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2571     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2572     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2573   }
2574   else if (theArgNb == 7)
2575   {
2576     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2577     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2578     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2579     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2580     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2581     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2582   }
2583   else
2584   {
2585     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2586     theDI.PrintHelp(theArgVec[0]);
2587     return 1;
2588   }
2589
2590   // Convert model coordinates to view space
2591   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2592   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2593   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2594
2595   // Determine fit area
2596   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2597   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2598
2599   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2600
2601   if (aDiagonal < Precision::Confusion())
2602   {
2603     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2604     return 1;
2605   }
2606
2607   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2608   return 0;
2609 }
2610
2611 //==============================================================================
2612 //function : VZFit
2613 //purpose  : ZFitall, no DRAW arguments
2614 //Draw arg : No args
2615 //==============================================================================
2616 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2617 {
2618   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2619
2620   if (aCurrentView.IsNull())
2621   {
2622     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2623     return 1;
2624   }
2625
2626   if (theArgsNb == 1)
2627   {
2628     aCurrentView->ZFitAll();
2629     aCurrentView->Redraw();
2630     return 0;
2631   }
2632
2633   Standard_Real aScale = 1.0;
2634
2635   if (theArgsNb >= 2)
2636   {
2637     aScale = Draw::Atoi (theArgVec[1]);
2638   }
2639
2640   aCurrentView->ZFitAll (aScale);
2641   aCurrentView->Redraw();
2642
2643   return 0;
2644 }
2645
2646 //==============================================================================
2647 //function : VRepaint
2648 //purpose  :
2649 //==============================================================================
2650 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2651 {
2652   Handle(V3d_View) V = ViewerTest::CurrentView();
2653   if ( !V.IsNull() ) V->Redraw(); return 0;
2654 }
2655
2656 //==============================================================================
2657 //function : VClear
2658 //purpose  : Remove all the object from the viewer
2659 //Draw arg : No args
2660 //==============================================================================
2661
2662 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2663 {
2664   Handle(V3d_View) V = ViewerTest::CurrentView();
2665   if(!V.IsNull())
2666     ViewerTest::Clear();
2667   return 0;
2668 }
2669
2670 //==============================================================================
2671 //function : VPick
2672 //purpose  :
2673 //==============================================================================
2674
2675 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2676 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2677
2678 if ( argc < 4 ) {
2679   di << argv[0] << "Invalid number of arguments\n";
2680   return 1;
2681 }
2682
2683 while (ViewerMainLoop( argc, argv)) {
2684 }
2685
2686 return 0;
2687 }
2688
2689 //==============================================================================
2690 //function : VSetBg
2691 //purpose  : Load image as background
2692 //==============================================================================
2693
2694 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2695 {
2696   if (argc < 2 || argc > 3)
2697   {
2698     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2699     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2700     return 1;
2701   }
2702
2703   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2704   if(AISContext.IsNull())
2705   {
2706     di << "use 'vinit' command before " << argv[0] << "\n";
2707     return 1;
2708   }
2709
2710   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2711   if (argc == 3)
2712   {
2713     const char* szType = argv[2];
2714     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2715     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2716     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2717     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2718     else
2719     {
2720       di << "Wrong fill type : " << szType << "\n";
2721       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2722       return 1;
2723     }
2724   }
2725
2726   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2727   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2728
2729   return 0;
2730 }
2731
2732 //==============================================================================
2733 //function : VSetBgMode
2734 //purpose  : Change background image fill type
2735 //==============================================================================
2736
2737 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2738 {
2739   if (argc != 2)
2740   {
2741     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2742     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2743     return 1;
2744   }
2745
2746   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2747   if(AISContext.IsNull())
2748   {
2749     di << "use 'vinit' command before " << argv[0] << "\n";
2750     return 1;
2751   }
2752   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2753   const char* szType = argv[1];
2754   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2755   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2756   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2757   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2758   else
2759   {
2760     di << "Wrong fill type : " << szType << "\n";
2761     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2762     return 1;
2763   }
2764   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2765   V3dView->SetBgImageStyle(aFillType, Standard_True);
2766   return 0;
2767 }
2768
2769 //==============================================================================
2770 //function : VSetGradientBg
2771 //purpose  : Mount gradient background
2772 //==============================================================================
2773 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2774 {
2775   if (argc != 8 )
2776   {
2777     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2778     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2779     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2780     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2781     return 1;
2782   }
2783
2784   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2785   if(AISContext.IsNull())
2786   {
2787     di << "use 'vinit' command before " << argv[0] << "\n";
2788     return 1;
2789   }
2790   if (argc == 8)
2791   {
2792
2793     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2794     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2795     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2796     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2797
2798     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2799     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2800     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2801
2802     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2803     int aType = Draw::Atoi(argv[7]);
2804     if( aType < 0 || aType > 8 )
2805     {
2806       di << "Wrong fill type \n";
2807       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2808       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2809       return 1;
2810     }
2811
2812     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2813
2814     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2815     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2816   }
2817
2818   return 0;
2819 }
2820
2821 //==============================================================================
2822 //function : VSetGradientBgMode
2823 //purpose  : Change gradient background fill style
2824 //==============================================================================
2825 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2826 {
2827   if (argc != 2 )
2828   {
2829     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2830     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2831     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2832     return 1;
2833   }
2834
2835   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2836   if(AISContext.IsNull())
2837   {
2838     di << "use 'vinit' command before " << argv[0] << "\n";
2839     return 1;
2840   }
2841   if (argc == 2)
2842   {
2843     int aType = Draw::Atoi(argv[1]);
2844     if( aType < 0 || aType > 8 )
2845     {
2846       di << "Wrong fill type \n";
2847       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2848       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2849       return 1;
2850     }
2851
2852     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2853
2854     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2855     V3dView->SetBgGradientStyle( aMethod, 1 );
2856   }
2857
2858   return 0;
2859 }
2860
2861 //==============================================================================
2862 //function : VSetColorBg
2863 //purpose  : Set color background
2864 //==============================================================================
2865 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2866 {
2867   if (argc != 4 )
2868   {
2869     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2870     di << "R,G,B = [0..255]\n";
2871     return 1;
2872   }
2873
2874   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2875   if(AISContext.IsNull())
2876   {
2877     di << "use 'vinit' command before " << argv[0] << "\n";
2878     return 1;
2879   }
2880   if (argc == 4)
2881   {
2882
2883     Standard_Real R = Draw::Atof(argv[1])/255.;
2884     Standard_Real G = Draw::Atof(argv[2])/255.;
2885     Standard_Real B = Draw::Atof(argv[3])/255.;
2886     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2887
2888     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2889     V3dView->SetBackgroundColor( aColor );
2890     V3dView->Update();
2891   }
2892
2893   return 0;
2894 }
2895
2896 //==============================================================================
2897 //function : VSetDefaultBg
2898 //purpose  : Set default viewer background fill color
2899 //==============================================================================
2900 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2901 {
2902   if (theArgNb != 4
2903    && theArgNb != 8)
2904   {
2905     std::cout << "Error: wrong syntax! See usage:\n";
2906     theDI.PrintHelp (theArgVec[0]);
2907     return 1;
2908   }
2909
2910   ViewerTest_DefaultBackground.FillMethod =
2911     theArgNb == 4 ? Aspect_GFM_NONE
2912                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2913
2914   if (theArgNb == 4)
2915   {
2916     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2917     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2918     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2919     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2920   }
2921   else
2922   {
2923     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2924     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2925     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2926     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2927
2928     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2929     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2930     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2931     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2932   }
2933
2934   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2935        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2936   {
2937     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2938     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2939     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2940                                          ViewerTest_DefaultBackground.GradientColor2,
2941                                          ViewerTest_DefaultBackground.FillMethod);
2942   }
2943
2944   return 0;
2945 }
2946
2947 //==============================================================================
2948 //function : VScale
2949 //purpose  : View Scaling
2950 //==============================================================================
2951
2952 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2953 {
2954   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2955   if ( V3dView.IsNull() ) return 1;
2956
2957   if ( argc != 4 ) {
2958     di << argv[0] << "Invalid number of arguments\n";
2959     return 1;
2960   }
2961   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2962   return 0;
2963 }
2964 //==============================================================================
2965 //function : VZBuffTrihedron
2966 //purpose  :
2967 //==============================================================================
2968
2969 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2970                             Standard_Integer  theArgNb,
2971                             const char**      theArgVec)
2972 {
2973   Handle(V3d_View) aView = ViewerTest::CurrentView();
2974   if (aView.IsNull())
2975   {
2976     std::cout << "Error: no active viewer!\n";
2977     return 1;
2978   }
2979
2980   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2981
2982   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2983   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2984   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2985   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2986   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2987   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2988   Standard_Real                 aScale        = 0.1;
2989   Standard_Real                 aSizeRatio    = 0.8;
2990   Standard_Real                 anArrowDiam   = 0.05;
2991   Standard_Integer              aNbFacets     = 12;
2992   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2993   {
2994     Standard_CString        anArg = theArgVec[anArgIter];
2995     TCollection_AsciiString aFlag (anArg);
2996     aFlag.LowerCase();
2997     if (anUpdateTool.parseRedrawMode (aFlag))
2998     {
2999       continue;
3000     }
3001     else if (aFlag == "-on")
3002     {
3003       continue;
3004     }
3005     else if (aFlag == "-off")
3006     {
3007       aView->TriedronErase();
3008       return 0;
3009     }
3010     else if (aFlag == "-pos"
3011           || aFlag == "-position"
3012           || aFlag == "-corner")
3013     {
3014       if (++anArgIter >= theArgNb)
3015       {
3016         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3017         return 1;
3018       }
3019
3020       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3021       aPosName.LowerCase();
3022       if (aPosName == "center")
3023       {
3024         aPosition = Aspect_TOTP_CENTER;
3025       }
3026       else if (aPosName == "left_lower"
3027             || aPosName == "lower_left"
3028             || aPosName == "leftlower"
3029             || aPosName == "lowerleft")
3030       {
3031         aPosition = Aspect_TOTP_LEFT_LOWER;
3032       }
3033       else if (aPosName == "left_upper"
3034             || aPosName == "upper_left"
3035             || aPosName == "leftupper"
3036             || aPosName == "upperleft")
3037       {
3038         aPosition = Aspect_TOTP_LEFT_UPPER;
3039       }
3040       else if (aPosName == "right_lower"
3041             || aPosName == "lower_right"
3042             || aPosName == "rightlower"
3043             || aPosName == "lowerright")
3044       {
3045         aPosition = Aspect_TOTP_RIGHT_LOWER;
3046       }
3047       else if (aPosName == "right_upper"
3048             || aPosName == "upper_right"
3049             || aPosName == "rightupper"
3050             || aPosName == "upperright")
3051       {
3052         aPosition = Aspect_TOTP_RIGHT_UPPER;
3053       }
3054       else
3055       {
3056         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3057         return 1;
3058       }
3059     }
3060     else if (aFlag == "-type")
3061     {
3062       if (++anArgIter >= theArgNb)
3063       {
3064         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3065         return 1;
3066       }
3067
3068       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3069       aTypeName.LowerCase();
3070       if (aTypeName == "wireframe"
3071        || aTypeName == "wire")
3072       {
3073         aVisType = V3d_WIREFRAME;
3074       }
3075       else if (aTypeName == "zbuffer"
3076             || aTypeName == "shaded")
3077       {
3078         aVisType = V3d_ZBUFFER;
3079       }
3080       else
3081       {
3082         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3083       }
3084     }
3085     else if (aFlag == "-scale")
3086     {
3087       if (++anArgIter >= theArgNb)
3088       {
3089         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3090         return 1;
3091       }
3092
3093       aScale = Draw::Atof (theArgVec[anArgIter]);
3094     }
3095     else if (aFlag == "-size"
3096           || aFlag == "-sizeratio")
3097     {
3098       if (++anArgIter >= theArgNb)
3099       {
3100         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3101         return 1;
3102       }
3103
3104       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3105     }
3106     else if (aFlag == "-arrowdiam"
3107           || aFlag == "-arrowdiameter")
3108     {
3109       if (++anArgIter >= theArgNb)
3110       {
3111         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3112         return 1;
3113       }
3114
3115       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3116     }
3117     else if (aFlag == "-nbfacets")
3118     {
3119       if (++anArgIter >= theArgNb)
3120       {
3121         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3122         return 1;
3123       }
3124
3125       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3126     }
3127     else if (aFlag == "-colorlabel"
3128           || aFlag == "-colorlabels")
3129     {
3130       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3131                                                            theArgVec + anArgIter + 1,
3132                                                            aLabelsColor);
3133       if (aNbParsed == 0)
3134       {
3135         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3136         return 1;
3137       }
3138       anArgIter += aNbParsed;
3139     }
3140     else if (aFlag == "-colorarrowx")
3141     {
3142       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3143                                                            theArgVec + anArgIter + 1,
3144                                                            anArrowColorX);
3145       if (aNbParsed == 0)
3146       {
3147         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3148         return 1;
3149       }
3150       anArgIter += aNbParsed;
3151     }
3152     else if (aFlag == "-colorarrowy")
3153     {
3154       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3155                                                            theArgVec + anArgIter + 1,
3156                                                            anArrowColorY);
3157       if (aNbParsed == 0)
3158       {
3159         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3160         return 1;
3161       }
3162       anArgIter += aNbParsed;
3163     }
3164     else if (aFlag == "-colorarrowz")
3165     {
3166       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3167                                                            theArgVec + anArgIter + 1,
3168                                                            anArrowColorZ);
3169       if (aNbParsed == 0)
3170       {
3171         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3172         return 1;
3173       }
3174       anArgIter += aNbParsed;
3175     }
3176     else
3177     {
3178       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3179       return 1;
3180     }
3181   }
3182
3183   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3184                                aSizeRatio, anArrowDiam, aNbFacets);
3185   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3186   aView->ZFitAll();
3187   return 0;
3188 }
3189
3190 //==============================================================================
3191 //function : VRotate
3192 //purpose  : Camera Rotating
3193 //==============================================================================
3194
3195 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3196 {
3197   Handle(V3d_View) aView = ViewerTest::CurrentView();
3198   if (aView.IsNull())
3199   {
3200     std::cout << "No active view!\n";
3201     return 1;
3202   }
3203
3204   Standard_Boolean hasFlags = Standard_False;
3205   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3206   {
3207     Standard_CString        anArg (theArgVec[anArgIter]);
3208     TCollection_AsciiString aFlag (anArg);
3209     aFlag.LowerCase();
3210     if (aFlag == "-mousestart"
3211      || aFlag == "-mousefrom")
3212     {
3213       hasFlags = Standard_True;
3214       if (anArgIter + 2 >= theArgNb)
3215       {
3216         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3217         return 1;
3218       }
3219
3220       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3221       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3222       aView->StartRotation (anX, anY);
3223     }
3224     else if (aFlag == "-mousemove")
3225     {
3226       hasFlags = Standard_True;
3227       if (anArgIter + 2 >= theArgNb)
3228       {
3229         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3230         return 1;
3231       }
3232
3233       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3234       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3235       aView->Rotation (anX, anY);
3236     }
3237     else if (theArgNb != 4
3238           && theArgNb != 7)
3239     {
3240       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3241       return 1;
3242     }
3243   }
3244
3245   if (hasFlags)
3246   {
3247     return 0;
3248   }
3249   else if (theArgNb == 4)
3250   {
3251     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3252     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3253     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3254     aView->Rotate (anAX, anAY, anAZ);
3255     return 0;
3256   }
3257   else if (theArgNb == 7)
3258   {
3259     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3260     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3261     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3262
3263     Standard_Real anX = Draw::Atof (theArgVec[4]);
3264     Standard_Real anY = Draw::Atof (theArgVec[5]);
3265     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3266
3267     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3268     return 0;
3269   }
3270
3271   std::cout << "Error: Invalid number of arguments\n";
3272   return 1;
3273 }
3274
3275 //==============================================================================
3276 //function : VZoom
3277 //purpose  : View zoom in / out (relative to current zoom)
3278 //==============================================================================
3279
3280 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3281   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3282   if ( V3dView.IsNull() ) {
3283     return 1;
3284   }
3285
3286   if ( argc == 2 ) {
3287     Standard_Real coef = Draw::Atof(argv[1]);
3288     if ( coef <= 0.0 ) {
3289       di << argv[1] << "Invalid value\n";
3290       return 1;
3291     }
3292     V3dView->SetZoom( Draw::Atof(argv[1]) );
3293     return 0;
3294   } else {
3295     di << argv[0] << " Invalid number of arguments\n";
3296     return 1;
3297   }
3298 }
3299
3300 //==============================================================================
3301 //function : VPan
3302 //purpose  : View panning (in pixels)
3303 //==============================================================================
3304
3305 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3306   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3307   if ( V3dView.IsNull() ) return 1;
3308
3309   if ( argc == 3 ) {
3310     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3311     return 0;
3312   } else {
3313     di << argv[0] << " Invalid number of arguments\n";
3314     return 1;
3315   }
3316 }
3317
3318 //==============================================================================
3319 //function : VPlace
3320 //purpose  : Place the point (in pixels) at the center of the window
3321 //==============================================================================
3322 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3323 {
3324   Handle(V3d_View) aView = ViewerTest::CurrentView();
3325   if (aView.IsNull())
3326   {
3327     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3328     return 1;
3329   }
3330
3331   if (theArgNb != 3)
3332   {
3333     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3334     return 1;
3335   }
3336
3337   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3338
3339   return 0;
3340 }
3341
3342 //==============================================================================
3343 //function : VExport
3344 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3345 //==============================================================================
3346
3347 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3348 {
3349   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3350   if (V3dView.IsNull())
3351     return 1;
3352
3353   if (argc == 1)
3354   {
3355     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3356     return 1;
3357   }
3358
3359   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3360   TCollection_AsciiString aFormatStr;
3361
3362   TCollection_AsciiString aFileName (argv[1]);
3363   Standard_Integer aLen = aFileName.Length();
3364
3365   if (argc > 2)
3366   {
3367     aFormatStr = TCollection_AsciiString (argv[2]);
3368   }
3369   else if (aLen >= 4)
3370   {
3371     if (aFileName.Value (aLen - 2) == '.')
3372     {
3373       aFormatStr = aFileName.ToCString() + aLen - 2;
3374     }
3375     else if (aFileName.Value (aLen - 3) == '.')
3376     {
3377       aFormatStr = aFileName.ToCString() + aLen - 3;
3378     }
3379     else
3380     {
3381       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3382       return 1;
3383     }
3384   }
3385   else
3386   {
3387     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3388     return 1;
3389   }
3390
3391   aFormatStr.UpperCase();
3392   if (aFormatStr == "PS")
3393     anExpFormat = Graphic3d_EF_PostScript;
3394   else if (aFormatStr == "EPS")
3395     anExpFormat = Graphic3d_EF_EnhPostScript;
3396   else if (aFormatStr == "TEX")
3397     anExpFormat = Graphic3d_EF_TEX;
3398   else if (aFormatStr == "PDF")
3399     anExpFormat = Graphic3d_EF_PDF;
3400   else if (aFormatStr == "SVG")
3401     anExpFormat = Graphic3d_EF_SVG;
3402   else if (aFormatStr == "PGF")
3403     anExpFormat = Graphic3d_EF_PGF;
3404   else if (aFormatStr == "EMF")
3405     anExpFormat = Graphic3d_EF_EMF;
3406   else
3407   {
3408     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3409     return 1;
3410   }
3411
3412   Standard_DISABLE_DEPRECATION_WARNINGS
3413   try
3414   {
3415     if (!V3dView->Export (argv[1], anExpFormat))
3416     {
3417       di << "Error: export of image to " << aFormatStr << " failed!\n";
3418     }
3419   }
3420   catch (Standard_Failure)
3421   {
3422     di << "Error: export of image to " << aFormatStr << " failed";
3423     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
3424   }
3425   Standard_ENABLE_DEPRECATION_WARNINGS
3426   return 0;
3427 }
3428
3429 static int VColorScale (Draw_Interpretor& theDI,
3430                         Standard_Integer  theArgNb,
3431                         const char**      theArgVec)
3432 {
3433   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3434   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3435   if (aContext.IsNull())
3436   {
3437     std::cout << "Error: no active view!\n";
3438     return 1;
3439   }
3440   if (theArgNb <= 1)
3441   {
3442     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3443     return 1;
3444   }
3445
3446   Handle(AIS_ColorScale) aColorScale;
3447   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3448   {
3449     // find existing object
3450     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3451     if (aColorScale.IsNull())
3452     {
3453       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3454       return 1;
3455     }
3456   }
3457
3458   if (theArgNb <= 2)
3459   {
3460     if (aColorScale.IsNull())
3461     {
3462       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3463       return 1;
3464     }
3465
3466     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3467           << "Min range: "            << aColorScale->GetMin() << "\n"
3468           << "Max range: "            << aColorScale->GetMax() << "\n"
3469           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3470           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3471           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3472           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3473           << "Label position: ";
3474     switch (aColorScale->GetLabelPosition())
3475     {
3476       case Aspect_TOCSP_NONE:
3477         theDI << "None\n";
3478         break;
3479       case Aspect_TOCSP_LEFT:
3480         theDI << "Left\n";
3481         break;
3482       case Aspect_TOCSP_RIGHT:
3483         theDI << "Right\n";
3484         break;
3485       case Aspect_TOCSP_CENTER:
3486         theDI << "Center\n";
3487         break;
3488     }
3489     return 0;
3490   }
3491
3492   if (aColorScale.IsNull())
3493   {
3494     aColorScale = new AIS_ColorScale();
3495     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3496     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3497   }
3498
3499   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3500   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3501   {
3502     Standard_CString        anArg = theArgVec[anArgIter];
3503     TCollection_AsciiString aFlag (anArg);
3504     aFlag.LowerCase();
3505     if (anUpdateTool.parseRedrawMode (aFlag))
3506     {
3507       continue;
3508     }
3509     else if (aFlag == "-range")
3510     {
3511       if (anArgIter + 3 >= theArgNb)
3512       {
3513         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3514         return 1;
3515       }
3516
3517       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3518       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3519       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3520       if (!aRangeMin.IsRealValue()
3521        || !aRangeMax.IsRealValue())
3522       {
3523         std::cout << "Error: the range values should be real!\n";
3524         return 1;
3525       }
3526       else if (!aNbIntervals.IsIntegerValue())
3527       {
3528         std::cout << "Error: the number of intervals should be integer!\n";
3529         return 1;
3530       }
3531
3532       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3533       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3534     }
3535     else if (aFlag == "-font")
3536     {
3537       if (anArgIter + 1 >= theArgNb)
3538       {
3539         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3540         return 1;
3541       }
3542       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3543       if (!aFontArg.IsIntegerValue())
3544       {
3545         std::cout << "Error: HeightFont value should be integer!\n";
3546         return 1;
3547       }
3548
3549       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3550       anArgIter += 1;
3551     }
3552     else if (aFlag == "-textpos")
3553     {
3554       if (anArgIter + 1 >= theArgNb)
3555       {
3556         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3557         return 1;
3558       }
3559
3560       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3561       aTextPosArg.LowerCase();
3562       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3563       if (aTextPosArg == "none")
3564       {
3565         aLabPosition = Aspect_TOCSP_NONE;
3566       }
3567       else if (aTextPosArg == "left")
3568       {
3569         aLabPosition = Aspect_TOCSP_LEFT;
3570       }
3571       else if (aTextPosArg == "right")
3572       {
3573         aLabPosition = Aspect_TOCSP_RIGHT;
3574       }
3575       else if (aTextPosArg == "center")
3576       {
3577         aLabPosition = Aspect_TOCSP_CENTER;
3578       }
3579       else
3580       {
3581         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3582         return 1;
3583       }
3584       aColorScale->SetLabelPosition (aLabPosition);
3585     }
3586     else if (aFlag == "-logarithmic"
3587           || aFlag == "-log")
3588     {
3589       if (anArgIter + 1 >= theArgNb)
3590       {
3591         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3592         return 1;
3593       }
3594
3595       Standard_Boolean IsLog;
3596       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3597       {
3598         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3599         return 1;
3600       }
3601       aColorScale->SetLogarithmic (IsLog);
3602     }
3603     else if (aFlag == "-huerange"
3604           || aFlag == "-hue")
3605     {
3606       if (anArgIter + 2 >= theArgNb)
3607       {
3608         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3609         return 1;
3610       }
3611
3612       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3613       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3614       aColorScale->SetHueRange (aHueMin, aHueMax);
3615     }
3616     else if (aFlag == "-colorrange")
3617     {
3618       Quantity_Color aColorMin, aColorMax;
3619       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3620                                                             theArgVec + (anArgIter + 1),
3621                                                             aColorMin);
3622       anArgIter += aNbParsed1;
3623       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3624                                                             theArgVec + (anArgIter + 1),
3625                                                             aColorMax);
3626       anArgIter += aNbParsed2;
3627       if (aNbParsed1 == 0
3628        || aNbParsed2 == 0)
3629       {
3630         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3631         return 1;
3632       }
3633
3634       aColorScale->SetColorRange (aColorMin, aColorMax);
3635     }
3636     else if (aFlag == "-reversed"
3637           || aFlag == "-inverted"
3638           || aFlag == "-topdown"
3639           || aFlag == "-bottomup")
3640     {
3641       Standard_Boolean toEnable = Standard_True;
3642       if (anArgIter + 1 < theArgNb
3643        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3644       {
3645         ++anArgIter;
3646       }
3647       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3648     }
3649     else if (aFlag == "-smooth"
3650           || aFlag == "-smoothtransition")
3651     {
3652       Standard_Boolean toEnable = Standard_True;
3653       if (anArgIter + 1 < theArgNb
3654        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3655       {
3656         ++anArgIter;
3657       }
3658       aColorScale->SetSmoothTransition (toEnable);
3659     }
3660     else if (aFlag == "-xy")
3661     {
3662       if (anArgIter + 2 >= theArgNb)
3663       {
3664         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3665         return 1;
3666       }
3667
3668       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3669       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3670       if (!anX.IsIntegerValue()
3671        || !anY.IsIntegerValue())
3672       {
3673         std::cout << "Error: coordinates should be integer values!\n";
3674         return 1;
3675       }
3676
3677       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3678     }
3679     else if (aFlag == "-width"
3680           || aFlag == "-w"
3681           || aFlag == "-breadth")
3682     {
3683       if (anArgIter + 1 >= theArgNb)
3684       {
3685         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3686         return 1;
3687       }
3688
3689       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3690       if (!aBreadth.IsIntegerValue())
3691       {
3692         std::cout << "Error: a width should be an integer value!\n";
3693         return 1;
3694       }
3695       aColorScale->SetBreadth (aBreadth.IntegerValue());
3696     }
3697     else if (aFlag == "-height"
3698           || aFlag == "-h")
3699     {
3700       if (anArgIter + 1 >= theArgNb)
3701       {
3702         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3703         return 1;
3704       }
3705
3706       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3707       if (!aHeight.IsIntegerValue())
3708       {
3709         std::cout << "Error: a width should be an integer value!\n";
3710         return 1;
3711       }
3712       aColorScale->SetHeight (aHeight.IntegerValue());
3713     }
3714     else if (aFlag == "-color")
3715     {
3716       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3717       {
3718         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3719         return 1;
3720       }
3721       else if (anArgIter + 2 >= theArgNb)
3722       {
3723         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3724         return 1;
3725       }
3726
3727       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3728       if (!anInd.IsIntegerValue())
3729       {
3730         std::cout << "Error: Index value should be integer!\n";
3731         return 1;
3732       }
3733       const Standard_Integer anIndex = anInd.IntegerValue();
3734       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3735       {
3736         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3737         return 1;
3738       }
3739
3740       Quantity_Color aColor;
3741       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3742                                                            theArgVec + (anArgIter + 1),
3743                                                            aColor);
3744       if (aNbParsed == 0)
3745       {
3746         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3747         return 1;
3748       }
3749       aColorScale->SetIntervalColor (aColor, anIndex);
3750       aColorScale->SetColorType (Aspect_TOCSD_USER);
3751       anArgIter += aNbParsed;
3752     }
3753     else if (aFlag == "-label")
3754     {
3755       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3756       {
3757         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3758         return 1;
3759       }
3760       else if (anArgIter + 2 >= theArgNb)
3761       {
3762         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3763         return 1;
3764       }
3765
3766       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3767       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
3768       {
3769         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
3770         return 1;
3771       }
3772
3773       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3774       aColorScale->SetLabel     (aText, anIndex);
3775       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3776       anArgIter += 2;
3777     }
3778     else if (aFlag == "-labelat"
3779           || aFlag == "-labat"
3780           || aFlag == "-labelatborder"
3781           || aFlag == "-labatborder"
3782           || aFlag == "-labelatcenter"
3783           || aFlag == "-labatcenter")
3784     {
3785       Standard_Boolean toEnable = Standard_True;
3786       if (aFlag == "-labelat"
3787        || aFlag == "-labat")
3788       {
3789         Standard_Integer aLabAtBorder = -1;
3790         if (++anArgIter >= theArgNb)
3791         {
3792           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
3793           anAtBorder.LowerCase();
3794           if (anAtBorder == "border")
3795           {
3796             aLabAtBorder = 1;
3797           }
3798           else if (anAtBorder == "center")
3799           {
3800             aLabAtBorder = 0;
3801           }
3802         }
3803         if (aLabAtBorder == -1)
3804         {
3805           std::cout << "Syntax error at argument '" << anArg << "'!\n";
3806           return 1;
3807         }
3808         toEnable = (aLabAtBorder == 1);
3809       }
3810       else if (anArgIter + 1 < theArgNb
3811             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3812       {
3813         ++anArgIter;
3814       }
3815       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
3816                                   || aFlag == "-labatcenter"
3817                                    ? !toEnable
3818                                    :  toEnable);
3819     }
3820     else if (aFlag == "-colors")
3821     {
3822       Aspect_SequenceOfColor aSeq;
3823       for (;;)
3824       {
3825         Quantity_Color aColor;
3826         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3827                                                              theArgVec + (anArgIter + 1),
3828                                                              aColor);
3829         if (aNbParsed == 0)
3830         {
3831           break;
3832         }
3833         anArgIter += aNbParsed;
3834         aSeq.Append (aColor);
3835       }
3836       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
3837       {
3838         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3839                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
3840         return 1;
3841       }
3842
3843       aColorScale->SetColors    (aSeq);
3844       aColorScale->SetColorType (Aspect_TOCSD_USER);
3845     }
3846     else if (aFlag == "-labels"
3847           || aFlag == "-freelabels")
3848     {
3849       if (anArgIter + 1 >= theArgNb)
3850       {
3851         std::cout << "Syntax error at argument '" << anArg << "'!\n";
3852         return 1;
3853       }
3854
3855       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
3856                                  ? aColorScale->GetNumberOfIntervals() + 1
3857                                  : aColorScale->GetNumberOfIntervals();
3858       if (aFlag == "-freelabels")
3859       {
3860         ++anArgIter;
3861         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
3862       }
3863       if (anArgIter + aNbLabels >= theArgNb)
3864       {
3865         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
3866         return 1;
3867       }
3868
3869       TColStd_SequenceOfExtendedString aSeq;
3870       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
3871       {
3872         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
3873       }
3874       aColorScale->SetLabels (aSeq);
3875       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3876     }
3877     else if (aFlag == "-title")
3878     {
3879       if (anArgIter + 1 >= theArgNb)
3880       {
3881         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3882         return 1;
3883       }
3884
3885       Standard_Boolean isTwoArgs = Standard_False;
3886       if (anArgIter + 2 < theArgNb)
3887       {
3888         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3889         aSecondArg.LowerCase();
3890       Standard_DISABLE_DEPRECATION_WARNINGS
3891         if (aSecondArg == "none")
3892         {
3893           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
3894           isTwoArgs = Standard_True;
3895         }
3896         else if (aSecondArg == "left")
3897         {
3898           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
3899           isTwoArgs = Standard_True;
3900         }
3901         else if (aSecondArg == "right")
3902         {
3903           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
3904           isTwoArgs = Standard_True;
3905         }
3906         else if (aSecondArg == "center")
3907         {
3908           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
3909           isTwoArgs = Standard_True;
3910         }
3911       Standard_ENABLE_DEPRECATION_WARNINGS
3912       }
3913
3914       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
3915       if (isTwoArgs)
3916       {
3917         anArgIter += 1;
3918       }
3919       anArgIter += 1;
3920     }
3921     else if (aFlag == "-demoversion"
3922           || aFlag == "-demo")
3923     {
3924       aColorScale->SetPosition (0, 0);
3925       aColorScale->SetTextHeight (16);
3926       aColorScale->SetRange (0.0, 100.0);
3927       aColorScale->SetNumberOfIntervals (10);
3928       aColorScale->SetBreadth (0);
3929       aColorScale->SetHeight  (0);
3930       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
3931       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
3932       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
3933     }
3934     else if (aFlag == "-findcolor")
3935     {
3936       if (anArgIter + 1 >= theArgNb)
3937       {
3938         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3939         return 1;
3940       }
3941
3942       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3943
3944       if (!anArg1.IsRealValue())
3945       {
3946         std::cout << "Error: the value should be real!\n";
3947         return 1;
3948       }
3949
3950       Quantity_Color aColor;
3951       aColorScale->FindColor (anArg1.RealValue(), aColor);
3952       theDI << Quantity_Color::StringName (aColor.Name());
3953       return 0;
3954     }
3955     else
3956     {
3957       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3958       return 1;
3959     }
3960   }
3961
3962   Standard_Integer aWinWidth = 0, aWinHeight = 0;
3963   aView->Window()->Size (aWinWidth, aWinHeight);
3964   if (aColorScale->GetBreadth() == 0)
3965   {
3966     aColorScale->SetBreadth (aWinWidth);
3967   }
3968   if (aColorScale->GetHeight() == 0)
3969   {
3970     aColorScale->SetHeight (aWinHeight);
3971   }
3972   aColorScale->SetToUpdate();
3973   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
3974   return 0;
3975 }
3976
3977 //==============================================================================
3978 //function : VGraduatedTrihedron
3979 //purpose  : Displays or hides a graduated trihedron
3980 //==============================================================================
3981 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
3982                                   Quantity_Color& theColor)
3983 {
3984   Quantity_NameOfColor aColorName;
3985   TCollection_AsciiString aVal = theValue;
3986   aVal.UpperCase();
3987   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
3988   {
3989     return Standard_False;
3990   }
3991   theColor = Quantity_Color (aColorName);
3992   return Standard_True;
3993 }
3994
3995 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
3996 {
3997   if (theArgNum < 2)
3998   {
3999     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4000               << theArgs[0] <<"' for more information.\n";
4001     return 1;  //TCL_ERROR
4002   }
4003
4004   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4005   TCollection_AsciiString aParseKey;
4006   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4007   {
4008     TCollection_AsciiString anArg (theArgs [anArgIt]);
4009
4010     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4011     {
4012       aParseKey = anArg;
4013       aParseKey.Remove (1);
4014       aParseKey.LowerCase();
4015       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4016       continue;
4017     }
4018
4019     if (aParseKey.IsEmpty())
4020     {
4021       continue;
4022     }
4023
4024     aMapOfArgs(aParseKey)->Append (anArg);
4025   }
4026
4027   // Check parameters
4028   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4029        aMapIt.More(); aMapIt.Next())
4030   {
4031     const TCollection_AsciiString& aKey = aMapIt.Key();
4032     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4033
4034     // Bool key, without arguments
4035     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4036         && anArgs->IsEmpty())
4037     {
4038       continue;
4039     }
4040
4041     // One argument
4042     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4043           && anArgs->Length() == 1)
4044     {
4045       continue;
4046     }
4047
4048     // On/off arguments
4049     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4050         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4051         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4052         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4053         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4054     {
4055       continue;
4056     }
4057
4058     // One string argument
4059     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4060           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4061           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4062     {
4063       continue;
4064     }
4065
4066     // One integer argument
4067     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4068           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4069           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4070           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4071          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4072     {
4073       continue;
4074     }
4075
4076     // One real argument
4077     if ( aKey.IsEqual ("arrowlength")
4078          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4079     {
4080       continue;
4081     }
4082
4083     // Two string arguments
4084     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4085          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4086     {
4087       continue;
4088     }
4089
4090     TCollection_AsciiString aLowerKey;
4091     aLowerKey  = "-";
4092     aLowerKey += aKey;
4093     aLowerKey.LowerCase();
4094     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4095     std::cout << "Type help for more information.\n";
4096     return 1;
4097   }
4098
4099   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4100   if (anAISContext.IsNull())
4101   {
4102     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4103     return 1;
4104   }
4105
4106   Standard_Boolean toDisplay = Standard_True;
4107   Quantity_Color aColor;
4108   Graphic3d_GraduatedTrihedron aTrihedronData;
4109   // Process parameters
4110   Handle(TColStd_HSequenceOfAsciiString) aValues;
4111   if (aMapOfArgs.Find ("off", aValues))
4112   {
4113     toDisplay = Standard_False;
4114   }
4115
4116   // AXES NAMES
4117   if (aMapOfArgs.Find ("xname", aValues))
4118   {
4119     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4120   }
4121   if (aMapOfArgs.Find ("yname", aValues))
4122   {
4123     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4124   }
4125   if (aMapOfArgs.Find ("zname", aValues))
4126   {
4127     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4128   }
4129   if (aMapOfArgs.Find ("xdrawname", aValues))
4130   {
4131     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4132   }
4133   if (aMapOfArgs.Find ("ydrawname", aValues))
4134   {
4135     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4136   }
4137   if (aMapOfArgs.Find ("zdrawname", aValues))
4138   {
4139     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4140   }
4141   if (aMapOfArgs.Find ("xnameoffset", aValues))
4142   {
4143     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4144   }
4145   if (aMapOfArgs.Find ("ynameoffset", aValues))
4146   {
4147     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4148   }
4149   if (aMapOfArgs.Find ("znameoffset", aValues))
4150   {
4151     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4152   }
4153
4154   // COLORS
4155   if (aMapOfArgs.Find ("xnamecolor", aValues))
4156   {
4157     if (!GetColor (aValues->Value(1), aColor))
4158     {
4159       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4160       return 1;
4161     }
4162     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4163   }
4164   if (aMapOfArgs.Find ("ynamecolor", aValues))
4165   {
4166     if (!GetColor (aValues->Value(1), aColor))
4167     {
4168       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4169       return 1;
4170     }
4171     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4172   }
4173   if (aMapOfArgs.Find ("znamecolor", aValues))
4174   {
4175     if (!GetColor (aValues->Value(1), aColor))
4176     {
4177       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4178       return 1;
4179     }
4180     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4181   }
4182   if (aMapOfArgs.Find ("xcolor", aValues))
4183   {
4184     if (!GetColor (aValues->Value(1), aColor))
4185     {
4186       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4187       return 1;
4188     }
4189     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4190   }
4191   if (aMapOfArgs.Find ("ycolor", aValues))
4192   {
4193     if (!GetColor (aValues->Value(1), aColor))
4194     {
4195       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4196       return 1;
4197     }
4198     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4199   }
4200   if (aMapOfArgs.Find ("zcolor", aValues))
4201   {
4202     if (!GetColor (aValues->Value(1), aColor))
4203     {
4204       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4205       return 1;
4206     }
4207     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4208   }
4209
4210   // TICKMARKS
4211   if (aMapOfArgs.Find ("xticks", aValues))
4212   {
4213     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4214   }
4215   if (aMapOfArgs.Find ("yticks", aValues))
4216   {
4217     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4218   }
4219   if (aMapOfArgs.Find ("zticks", aValues))
4220   {
4221     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4222   }
4223   if (aMapOfArgs.Find ("xticklength", aValues))
4224   {
4225     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4226   }
4227   if (aMapOfArgs.Find ("yticklength", aValues))
4228   {
4229     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4230   }
4231   if (aMapOfArgs.Find ("zticklength", aValues))
4232   {
4233     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4234   }
4235   if (aMapOfArgs.Find ("xdrawticks", aValues))
4236   {
4237     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4238   }
4239   if (aMapOfArgs.Find ("ydrawticks", aValues))
4240   {
4241     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4242   }
4243   if (aMapOfArgs.Find ("zdrawticks", aValues))
4244   {
4245     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4246   }
4247
4248   // VALUES
4249   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4250   {
4251     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4252   }
4253   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4254   {
4255     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4256   }
4257   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4258   {
4259     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4260   }
4261   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4262   {
4263     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4264   }
4265   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4266   {
4267     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4268   }
4269   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4270   {
4271     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4272   }
4273
4274   // ARROWS
4275   if (aMapOfArgs.Find ("arrowlength", aValues))
4276   {
4277     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4278   }
4279
4280   // FONTS
4281   if (aMapOfArgs.Find ("namefont", aValues))
4282   {
4283     aTrihedronData.SetNamesFont (aValues->Value(1));
4284   }
4285   if (aMapOfArgs.Find ("valuesfont", aValues))
4286   {
4287     aTrihedronData.SetValuesFont (aValues->Value(1));
4288   }
4289
4290   if (aMapOfArgs.Find ("drawgrid", aValues))
4291   {
4292     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4293   }
4294   if (aMapOfArgs.Find ("drawaxes", aValues))
4295   {
4296     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4297   }
4298
4299   // The final step: display of erase trihedron
4300   if (toDisplay)
4301   {
4302     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4303   }
4304   else
4305   {
4306     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4307   }
4308
4309   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4310   ViewerTest::CurrentView()->Redraw();
4311
4312   return 0;
4313 }
4314
4315 //==============================================================================
4316 //function : VTile
4317 //purpose  :
4318 //==============================================================================
4319 static int VTile (Draw_Interpretor& theDI,
4320                   Standard_Integer  theArgNb,
4321                   const char**      theArgVec)
4322 {
4323   Handle(V3d_View) aView = ViewerTest::CurrentView();
4324   if (aView.IsNull())
4325   {
4326     std::cerr << "Error: no active viewer.\n";
4327     return 1;
4328   }
4329
4330   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4331   if (theArgNb < 2)
4332   {
4333     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4334           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4335           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4336     return 0;
4337   }
4338
4339   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4340   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4341   {
4342     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4343     anArg.LowerCase();
4344     if (anArg == "-lowerleft"
4345      || anArg == "-upperleft")
4346     {
4347       if (anArgIter + 3 < theArgNb)
4348       {
4349         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4350         return 1;
4351       }
4352       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4353       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4354       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4355     }
4356     else if (anArg == "-total"
4357           || anArg == "-totalsize"
4358           || anArg == "-viewsize")
4359     {
4360       if (anArgIter + 3 < theArgNb)
4361       {
4362         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4363         return 1;
4364       }
4365       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4366       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4367       if (aTile.TotalSize.x() < 1
4368        || aTile.TotalSize.y() < 1)
4369       {
4370         std::cerr << "Error: total size is incorrect.\n";
4371         return 1;
4372       }
4373     }
4374     else if (anArg == "-tilesize")
4375     {
4376       if (anArgIter + 3 < theArgNb)
4377       {
4378         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4379         return 1;
4380       }
4381
4382       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4383       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4384       if (aTile.TileSize.x() < 1
4385        || aTile.TileSize.y() < 1)
4386       {
4387         std::cerr << "Error: tile size is incorrect.\n";
4388         return 1;
4389       }
4390     }
4391     else if (anArg == "-unset")
4392     {
4393       aView->Camera()->SetTile (Graphic3d_CameraTile());
4394       aView->Redraw();
4395       return 0;
4396     }
4397   }
4398
4399   if (aTile.TileSize.x() < 1
4400    || aTile.TileSize.y() < 1)
4401   {
4402     std::cerr << "Error: tile size is undefined.\n";
4403     return 1;
4404   }
4405   else if (aTile.TotalSize.x() < 1
4406         || aTile.TotalSize.y() < 1)
4407   {
4408     std::cerr << "Error: total size is undefined.\n";
4409     return 1;
4410   }
4411
4412   aView->Camera()->SetTile (aTile);
4413   aView->Redraw();
4414   return 0;
4415 }
4416
4417 //! Format ZLayer ID.
4418 inline const char* formZLayerId (const Standard_Integer theLayerId)
4419 {
4420   switch (theLayerId)
4421   {
4422     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4423     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4424     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4425     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4426     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4427     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4428   }
4429   return "";
4430 }
4431
4432 //! Print the ZLayer information.
4433 inline void printZLayerInfo (Draw_Interpretor& theDI,
4434                              const Graphic3d_ZLayerSettings& theLayer)
4435 {
4436   if (!theLayer.Name().IsEmpty())
4437   {
4438     theDI << "  Name: " << theLayer.Name() << "\n";
4439   }
4440   if (theLayer.IsImmediate())
4441   {
4442     theDI << "  Immediate: TRUE\n";
4443   }
4444   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4445   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4446   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4447   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4448   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4449   {
4450     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4451   }
4452 }
4453
4454 //==============================================================================
4455 //function : VZLayer
4456 //purpose  : Test z layer operations for v3d viewer
4457 //==============================================================================
4458 static int VZLayer (Draw_Interpretor& theDI,
4459                     Standard_Integer  theArgNb,
4460                     const char**      theArgVec)
4461 {
4462   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4463   if (aContextAIS.IsNull())
4464   {
4465     std::cout << "No active viewer!\n";
4466     return 1;
4467   }
4468
4469   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4470   if (theArgNb < 2)
4471   {
4472     TColStd_SequenceOfInteger aLayers;
4473     aViewer->GetAllZLayers (aLayers);
4474     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4475     {
4476       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4477       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4478       printZLayerInfo (theDI, aSettings);
4479     }
4480     return 1;
4481   }
4482
4483   Standard_Integer anArgIter = 1;
4484   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4485   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4486   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4487   {
4488     ++anArgIter;
4489   }
4490
4491   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4492   if (aFirstArg.IsIntegerValue())
4493   {
4494     ++anArgIter;
4495     aLayerId = aFirstArg.IntegerValue();
4496   }
4497   else
4498   {
4499     aFirstArg.LowerCase();
4500     if (aFirstArg == "default"
4501      || aFirstArg == "def")
4502     {
4503       aLayerId = Graphic3d_ZLayerId_Default;
4504       ++anArgIter;
4505     }
4506     else if (aFirstArg == "top")
4507     {
4508       aLayerId = Graphic3d_ZLayerId_Top;
4509       ++anArgIter;
4510     }
4511     else if (aFirstArg == "topmost")
4512     {
4513       aLayerId = Graphic3d_ZLayerId_Topmost;
4514       ++anArgIter;
4515     }
4516     else if (aFirstArg == "overlay"
4517           || aFirstArg == "toposd")
4518     {
4519       aLayerId = Graphic3d_ZLayerId_TopOSD;
4520       ++anArgIter;
4521     }
4522     else if (aFirstArg == "underlay"
4523           || aFirstArg == "botosd")
4524     {
4525       aLayerId = Graphic3d_ZLayerId_BotOSD;
4526       ++anArgIter;
4527     }
4528     else
4529     {
4530       TColStd_SequenceOfInteger aLayers;
4531       aViewer->GetAllZLayers (aLayers);
4532       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4533       {
4534         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4535         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4536         {
4537           aLayerId = aLayeriter.Value();
4538           ++anArgIter;
4539           break;
4540         }
4541       }
4542     }
4543   }
4544
4545   for (; anArgIter < theArgNb; ++anArgIter)
4546   {
4547     // perform operation
4548     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4549     anArg.LowerCase();
4550     if (anUpdateTool.parseRedrawMode (anArg))
4551     {
4552       //
4553     }
4554     else if (anArg == "-add"
4555           || anArg == "add")
4556     {
4557       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4558       if (!aViewer->AddZLayer (aLayerId))
4559       {
4560         std::cout << "Error: can not add a new z layer!\n";
4561         return 0;
4562       }
4563
4564       theDI << aLayerId;
4565     }
4566     else if (anArg == "-del"
4567           || anArg == "-delete"
4568           || anArg == "del")
4569     {
4570       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4571       {
4572         if (++anArgIter >= theArgNb)
4573         {
4574           std::cout << "Syntax error: id of z layer to remove is missing\n";
4575           return 1;
4576         }
4577
4578         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4579       }
4580
4581       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4582        || aLayerId == Graphic3d_ZLayerId_Default
4583        || aLayerId == Graphic3d_ZLayerId_Top
4584        || aLayerId == Graphic3d_ZLayerId_Topmost
4585        || aLayerId == Graphic3d_ZLayerId_TopOSD
4586        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4587       {
4588         std::cout << "Syntax error: standard Z layer can not be removed\n";
4589         return 1;
4590       }
4591
4592       // move all object displayed in removing layer to default layer
4593       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4594            anObjIter.More(); anObjIter.Next())
4595       {
4596         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4597         if (aPrs.IsNull()
4598          || aPrs->ZLayer() != aLayerId)
4599         {
4600           continue;
4601         }
4602         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4603       }
4604
4605       if (!aViewer->RemoveZLayer (aLayerId))
4606       {
4607         std::cout << "Z layer can not be removed!\n";
4608       }
4609       else
4610       {
4611         theDI << aLayerId << " ";
4612       }
4613     }
4614     else if (anArg == "-get"
4615           || anArg == "get")
4616     {
4617       TColStd_SequenceOfInteger aLayers;
4618       aViewer->GetAllZLayers (aLayers);
4619       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4620       {
4621         theDI << aLayeriter.Value() << " ";
4622       }
4623
4624       theDI << "\n";
4625     }
4626     else if (anArg == "-name")
4627     {
4628       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4629       {
4630         std::cout << "Syntax error: id of Z layer is missing\n";
4631         return 1;
4632       }
4633
4634       if (++anArgIter >= theArgNb)
4635       {
4636         std::cout << "Syntax error: name is missing\n";
4637         return 1;
4638       }
4639
4640       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4641       aSettings.SetName (theArgVec[anArgIter]);
4642       aViewer->SetZLayerSettings (aLayerId, aSettings);
4643     }
4644     else if (anArg == "-origin")
4645     {
4646       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4647       {
4648         std::cout << "Syntax error: id of Z layer is missing\n";
4649         return 1;
4650       }
4651
4652       if (anArgIter + 2 >= theArgNb)
4653       {
4654         std::cout << "Syntax error: origin coordinates are missing\n";
4655         return 1;
4656       }
4657
4658       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4659       gp_XYZ anOrigin;
4660       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4661       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4662       anOrigin.SetZ (0.0);
4663       if (anArgIter + 3 < theArgNb)
4664       {
4665         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4666         anArgIter += 3;
4667       }
4668       else
4669       {
4670         anArgIter += 2;
4671       }
4672       aSettings.SetOrigin (anOrigin);
4673       aViewer->SetZLayerSettings (aLayerId, aSettings);
4674     }
4675     else if (anArg == "-settings"
4676           || anArg == "settings")
4677     {
4678       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4679       {
4680         if (++anArgIter >= theArgNb)
4681         {
4682           std::cout << "Syntax error: id of Z layer is missing\n";
4683           return 1;
4684         }
4685
4686         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4687       }
4688
4689       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4690       printZLayerInfo (theDI, aSettings);
4691     }
4692     else if (anArg == "-enable"
4693           || anArg == "enable"
4694           || anArg == "-disable"
4695           || anArg == "disable")
4696     {
4697       const Standard_Boolean toEnable = anArg == "-enable"
4698                                      || anArg == "enable";
4699       if (++anArgIter >= theArgNb)
4700       {
4701         std::cout << "Syntax error: option name is missing\n";
4702         return 1;
4703       }
4704
4705       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4706       aSubOp.LowerCase();
4707       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4708       {
4709         if (++anArgIter >= theArgNb)
4710         {
4711           std::cout << "Syntax error: id of Z layer is missing\n";
4712           return 1;
4713         }
4714
4715         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4716       }
4717
4718       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4719       if (aSubOp == "depthtest"
4720        || aSubOp == "test")
4721       {
4722         aSettings.SetEnableDepthTest (toEnable);
4723       }
4724       else if (aSubOp == "depthwrite"
4725             || aSubOp == "write")
4726       {
4727         aSettings.SetEnableDepthWrite (toEnable);
4728       }
4729       else if (aSubOp == "depthclear"
4730             || aSubOp == "clear")
4731       {
4732         aSettings.SetClearDepth (toEnable);
4733       }
4734       else if (aSubOp == "depthoffset"
4735             || aSubOp == "offset")
4736       {
4737         Graphic3d_PolygonOffset aParams;
4738         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4739         if (toEnable)
4740         {
4741           if (anArgIter + 2 >= theArgNb)
4742           {
4743             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4744             return 1;
4745           }
4746
4747           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4748           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4749         }
4750         aSettings.SetPolygonOffset (aParams);
4751       }
4752       else if (aSubOp == "positiveoffset"
4753             || aSubOp == "poffset")
4754       {
4755         if (toEnable)
4756         {
4757           aSettings.SetDepthOffsetPositive();
4758         }
4759         else
4760         {
4761           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4762         }
4763       }
4764       else if (aSubOp == "negativeoffset"
4765             || aSubOp == "noffset")
4766       {
4767         if (toEnable)
4768         {
4769           aSettings.SetDepthOffsetNegative();
4770         }
4771         else
4772         {
4773           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4774         }
4775       }
4776       else if (aSubOp == "textureenv")
4777       {
4778         aSettings.SetEnvironmentTexture (toEnable);
4779       }
4780
4781       aViewer->SetZLayerSettings (aLayerId, aSettings);
4782     }
4783     else
4784     {
4785       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4786       return 1;
4787     }
4788   }
4789
4790   return 0;
4791 }
4792
4793 // The interactive presentation of 2d layer item
4794 // for "vlayerline" command it provides a presentation of
4795 // line with user-defined linewidth, linetype and transparency.
4796 class V3d_LineItem : public AIS_InteractiveObject
4797 {
4798 public:
4799   // CASCADE RTTI
4800   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4801
4802   // constructor
4803   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4804                                Standard_Real X2, Standard_Real Y2,
4805                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4806                                Standard_Real theWidth    = 0.5,
4807                                Standard_Real theTransp   = 1.0);
4808
4809   private:
4810
4811   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4812                 const Handle(Prs3d_Presentation)& thePresentation,
4813                 const Standard_Integer theMode) Standard_OVERRIDE;
4814
4815   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4816                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4817   {}
4818
4819 private:
4820
4821   Standard_Real       myX1, myY1, myX2, myY2;
4822   Aspect_TypeOfLine   myType;
4823   Standard_Real       myWidth;
4824 };
4825
4826 // default constructor for line item
4827 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4828                            Standard_Real X2, Standard_Real Y2,
4829                            Aspect_TypeOfLine theType,
4830                            Standard_Real theWidth,
4831                            Standard_Real theTransp) :
4832   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4833   myType(theType), myWidth(theWidth)
4834 {
4835   SetTransparency (1-theTransp);
4836 }
4837
4838 // render line
4839 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4840                             const Handle(Prs3d_Presentation)& thePresentation,
4841                             const Standard_Integer /*theMode*/)
4842 {
4843   thePresentation->Clear();
4844   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4845   Standard_Integer aWidth, aHeight;
4846   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4847   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4848   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4849   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4850   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4851   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4852   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4853   aGroup->AddPrimitiveArray (aPrim);
4854 }
4855
4856 //=============================================================================
4857 //function : VLayerLine
4858 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4859 //         : linewidth, transparency coefficient
4860 //============================================================================
4861 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4862 {
4863   // get the active view
4864   Handle(V3d_View) aView = ViewerTest::CurrentView();
4865   if (aView.IsNull())
4866   {
4867     di << "Call vinit before!\n";
4868     return 1;
4869   }
4870   else if (argc < 5)
4871   {
4872     di << "Use: " << argv[0];
4873     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4874     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4875     di << "              0 - solid  \n";
4876     di << "              1 - dashed \n";
4877     di << "              2 - dot    \n";
4878     di << "              3 - dashdot\n";
4879     di << " transparency : { 0.0 - 1.0 } \n";
4880     di << "                  0.0 - transparent\n";
4881     di << "                  1.0 - visible    \n";
4882     return 1;
4883   }
4884
4885   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4886   // get the input params
4887   Standard_Real X1 = Draw::Atof(argv[1]);
4888   Standard_Real Y1 = Draw::Atof(argv[2]);
4889   Standard_Real X2 = Draw::Atof(argv[3]);
4890   Standard_Real Y2 = Draw::Atof(argv[4]);
4891
4892   Standard_Real aWidth = 0.5;
4893   Standard_Real aTransparency = 1.0;
4894
4895   // has width
4896   if (argc > 5)
4897     aWidth = Draw::Atof(argv[5]);
4898
4899   // select appropriate line type
4900   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
4901   if (argc > 6
4902   && !ViewerTest::ParseLineType (argv[6], aLineType))
4903   {
4904     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
4905     return 1;
4906   }
4907
4908   // has transparency
4909   if (argc > 7)
4910   {
4911     aTransparency = Draw::Atof(argv[7]);
4912     if (aTransparency < 0 || aTransparency > 1.0)
4913       aTransparency = 1.0;
4914   }
4915
4916   static Handle (V3d_LineItem) aLine;
4917   if (!aLine.IsNull())
4918   {
4919     aContext->Erase (aLine, Standard_False);
4920   }
4921   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4922                             aLineType, aWidth,
4923                             aTransparency);
4924
4925   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4926   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4927   aLine->SetToUpdate();
4928   aContext->Display (aLine, Standard_True);
4929
4930   return 0;
4931 }
4932
4933
4934 //==============================================================================
4935 //function : VGrid
4936 //purpose  :
4937 //==============================================================================
4938
4939 static int VGrid (Draw_Interpretor& /*theDI*/,
4940                   Standard_Integer  theArgNb,
4941                   const char**      theArgVec)
4942 {
4943   // get the active view
4944   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4945   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4946   if (aView.IsNull() || aViewer.IsNull())
4947   {
4948     std::cerr << "No active view. Please call vinit.\n";
4949     return 1;
4950   }
4951
4952   Aspect_GridType     aType = aViewer->GridType();
4953   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4954
4955   Standard_Integer anIter = 1;
4956   for (; anIter < theArgNb; ++anIter)
4957   {
4958     const char* aValue = theArgVec[anIter];
4959     if (*aValue == 'r')
4960     {
4961       aType = Aspect_GT_Rectangular;
4962     }
4963     else if (*aValue == 'c')
4964     {
4965       aType = Aspect_GT_Circular;
4966     }
4967     else if (*aValue == 'l')
4968     {
4969       aMode = Aspect_GDM_Lines;
4970     }
4971     else if (*aValue == 'p')
4972     {
4973       aMode = Aspect_GDM_Points;
4974     }
4975     else if (strcmp (aValue, "off" ) == 0)
4976     {
4977       aViewer->DeactivateGrid();
4978       return 0;
4979     }
4980     else
4981     {
4982       break;
4983     }
4984   }
4985
4986   Standard_Integer aTail = (theArgNb - anIter);
4987   if (aTail == 0)
4988   {
4989     aViewer->ActivateGrid (aType, aMode);
4990     return 0;
4991   }
4992   else if (aTail != 2 && aTail != 5)
4993   {
4994     std::cerr << "Incorrect arguments number! Usage:\n"
4995               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
4996     return 1;
4997   }
4998
4999   Quantity_Length anOriginX, anOriginY;
5000   Quantity_PlaneAngle aRotAngle;
5001   if (aType == Aspect_GT_Rectangular)
5002   {
5003     Quantity_Length aRStepX, aRStepY;
5004     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5005
5006     anOriginX = Draw::Atof (theArgVec[anIter++]);
5007     anOriginY = Draw::Atof (theArgVec[anIter++]);
5008     if (aTail == 5)
5009     {
5010       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5011       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5012       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5013     }
5014     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5015     aViewer->ActivateGrid (aType, aMode);
5016   }
5017   else if (aType == Aspect_GT_Circular)
5018   {
5019     Quantity_Length aRadiusStep;
5020     Standard_Integer aDivisionNumber;
5021     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5022
5023     anOriginX = Draw::Atof (theArgVec[anIter++]);
5024     anOriginY = Draw::Atof (theArgVec[anIter++]);
5025     if (aTail == 5)
5026     {
5027       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5028       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5029       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5030     }
5031
5032     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5033     aViewer->ActivateGrid (aType, aMode);
5034   }
5035
5036   return 0;
5037 }
5038
5039 //==============================================================================
5040 //function : VPriviledgedPlane
5041 //purpose  :
5042 //==============================================================================
5043
5044 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5045                               Standard_Integer  theArgNb,
5046                               const char**      theArgVec)
5047 {
5048   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5049   {
5050     std::cerr << "Error: wrong number of arguments! See usage:\n";
5051     theDI.PrintHelp (theArgVec[0]);
5052     return 1;
5053   }
5054
5055   // get the active viewer
5056   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5057   if (aViewer.IsNull())
5058   {
5059     std::cerr << "Error: no active viewer. Please call vinit.\n";
5060     return 1;
5061   }
5062
5063   if (theArgNb == 1)
5064   {
5065     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5066     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5067     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5068     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5069     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5070           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5071           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5072     return 0;
5073   }
5074
5075   Standard_Integer anArgIdx = 1;
5076   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5077   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5078   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5079   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5080   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5081   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5082
5083   gp_Ax3 aPriviledgedPlane;
5084   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5085   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5086   if (theArgNb > 7)
5087   {
5088     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5089     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5090     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5091     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5092     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5093   }
5094   else
5095   {
5096     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5097   }
5098
5099   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5100
5101   return 0;
5102 }
5103
5104 //==============================================================================
5105 //function : VConvert
5106 //purpose  :
5107 //==============================================================================
5108
5109 static int VConvert (Draw_Interpretor& theDI,
5110                      Standard_Integer  theArgNb,
5111                      const char**      theArgVec)
5112 {
5113   // get the active view
5114   Handle(V3d_View) aView = ViewerTest::CurrentView();
5115   if (aView.IsNull())
5116   {
5117     std::cerr << "Error: no active view. Please call vinit.\n";
5118     return 1;
5119   }
5120
5121   enum { Model, Ray, View, Window, Grid } aMode = Model;
5122
5123   // access coordinate arguments
5124   TColStd_SequenceOfReal aCoord;
5125   Standard_Integer anArgIdx = 1;
5126   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5127   {
5128     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5129     if (!anArg.IsRealValue())
5130     {
5131       break;
5132     }
5133     aCoord.Append (anArg.RealValue());
5134   }
5135
5136   // non-numeric argument too early
5137   if (aCoord.IsEmpty())
5138   {
5139     std::cerr << "Error: wrong number of arguments! See usage:\n";
5140     theDI.PrintHelp (theArgVec[0]);
5141     return 1;
5142   }
5143
5144   // collect all other arguments and options
5145   for (; anArgIdx < theArgNb; ++anArgIdx)
5146   {
5147     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5148     anArg.LowerCase();
5149     if      (anArg == "window") aMode = Window;
5150     else if (anArg == "view")   aMode = View;
5151     else if (anArg == "grid")   aMode = Grid;
5152     else if (anArg == "ray")    aMode = Ray;
5153     else
5154     {
5155       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5156       theDI.PrintHelp (theArgVec[0]);
5157       return 1;
5158     }
5159   }
5160
5161   // complete input checks
5162   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5163       (aCoord.Length() == 2 && theArgNb > 4) ||
5164       (aCoord.Length() == 3 && theArgNb > 5))
5165   {
5166     std::cerr << "Error: wrong number of arguments! See usage:\n";
5167     theDI.PrintHelp (theArgVec[0]);
5168     return 1;
5169   }
5170
5171   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5172   Standard_Integer aXYp[2] = {0, 0};
5173
5174   // convert one-dimensional coordinate
5175   if (aCoord.Length() == 1)
5176   {
5177     switch (aMode)
5178     {
5179       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
5180       case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
5181       default:
5182         std::cerr << "Error: wrong arguments! See usage:\n";
5183         theDI.PrintHelp (theArgVec[0]);
5184         return 1;
5185     }
5186   }
5187
5188   // convert 2D coordinates from projection or view reference space
5189   if (aCoord.Length() == 2)
5190   {
5191     switch (aMode)
5192     {
5193       case Model :
5194         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5195         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5196         return 0;
5197
5198       case View :
5199         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5200         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5201         return 0;
5202
5203       case Window :
5204         aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
5205         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5206         return 0;
5207
5208       case Grid :
5209         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5210         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5211         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5212         return 0;
5213
5214       case Ray :
5215         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5216                                 (Standard_Integer) aCoord (2),
5217                                 aXYZ[0], aXYZ[1], aXYZ[2],
5218                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5219         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5220         return 0;
5221
5222       default:
5223         std::cerr << "Error: wrong arguments! See usage:\n";
5224         theDI.PrintHelp (theArgVec[0]);
5225         return 1;
5226     }
5227   }
5228
5229   // convert 3D coordinates from view reference space
5230   else if (aCoord.Length() == 3)
5231   {
5232     switch (aMode)
5233     {
5234       case Window :
5235         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5236         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5237         return 0;
5238
5239       case Grid :
5240         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5241         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5242         return 0;
5243
5244       default:
5245         std::cerr << "Error: wrong arguments! See usage:\n";
5246         theDI.PrintHelp (theArgVec[0]);
5247         return 1;
5248     }
5249   }
5250
5251   return 0;
5252 }
5253
5254 //==============================================================================
5255 //function : VFps
5256 //purpose  :
5257 //==============================================================================
5258
5259 static int VFps (Draw_Interpretor& theDI,
5260                  Standard_Integer  theArgNb,
5261                  const char**      theArgVec)
5262 {
5263   // get the active view
5264   Handle(V3d_View) aView = ViewerTest::CurrentView();
5265   if (aView.IsNull())
5266   {
5267     std::cerr << "No active view. Please call vinit.\n";
5268     return 1;
5269   }
5270
5271   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5272   if (aFramesNb <= 0)
5273   {
5274     std::cerr << "Incorrect arguments!\n";
5275     return 1;
5276   }
5277
5278   // the time is meaningless for first call
5279   // due to async OpenGl rendering
5280   aView->Redraw();
5281
5282   // redraw view in loop to estimate average values
5283   OSD_Timer aTimer;
5284   aTimer.Start();
5285   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5286   {
5287     aView->Redraw();
5288   }
5289   aTimer.Stop();
5290   Standard_Real aCpu;
5291   const Standard_Real aTime = aTimer.ElapsedTime();
5292   aTimer.OSD_Chronometer::Show (aCpu);
5293
5294   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5295   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5296
5297   // return statistics
5298   theDI << "FPS: " << aFpsAver << "\n"
5299         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5300
5301   // compute additional statistics in ray-tracing mode
5302   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5303
5304   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5305   {
5306     Standard_Integer aSizeX;
5307     Standard_Integer aSizeY;
5308
5309     aView->Window()->Size (aSizeX, aSizeY);
5310
5311     // 1 shadow ray and 1 secondary ray pew each bounce
5312     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5313
5314     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5315   }
5316
5317   return 0;
5318 }
5319
5320 //==============================================================================
5321 //function : VGlDebug
5322 //purpose  :
5323 //==============================================================================
5324
5325 static int VGlDebug (Draw_Interpretor& theDI,
5326                      Standard_Integer  theArgNb,
5327                      const char**      theArgVec)
5328 {
5329   Handle(OpenGl_GraphicDriver) aDriver;
5330   Handle(V3d_View) aView = ViewerTest::CurrentView();
5331   if (!aView.IsNull())
5332   {
5333     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5334   }
5335   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5336   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5337
5338   if (theArgNb < 2)
5339   {
5340     TCollection_AsciiString aDebActive, aSyncActive;
5341     if (aCaps == NULL)
5342     {
5343       aCaps = aDefCaps;
5344     }
5345     else
5346     {
5347       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5348                                                                   "GL_ARB_debug_output");
5349       aDebActive = isActive ? " (active)" : " (inactive)";
5350       if (isActive)
5351       {
5352         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5353         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5354       }
5355     }
5356
5357     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5358           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5359           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5360           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5361     return 0;
5362   }
5363
5364   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5365   {
5366     Standard_CString        anArg     = theArgVec[anArgIter];
5367     TCollection_AsciiString anArgCase (anArg);
5368     anArgCase.LowerCase();
5369     Standard_Boolean toEnableDebug = Standard_True;
5370     if (anArgCase == "-glsl"
5371      || anArgCase == "-glslwarn"
5372      || anArgCase == "-glslwarns"
5373      || anArgCase == "-glslwarnings")
5374     {
5375       Standard_Boolean toShowWarns = Standard_True;
5376       if (++anArgIter < theArgNb
5377       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5378       {
5379         --anArgIter;
5380       }
5381       aDefCaps->glslWarnings = toShowWarns;
5382       if (aCaps != NULL)
5383       {
5384         aCaps->glslWarnings = toShowWarns;
5385       }
5386     }
5387     else if (anArgCase == "-extra"
5388           || anArgCase == "-extramsg"
5389           || anArgCase == "-extramessages")
5390     {
5391       Standard_Boolean toShow = Standard_True;
5392       if (++anArgIter < theArgNb
5393       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5394       {
5395         --anArgIter;
5396       }
5397       aDefCaps->suppressExtraMsg = !toShow;
5398       if (aCaps != NULL)
5399       {
5400         aCaps->suppressExtraMsg = !toShow;
5401       }
5402     }
5403     else if (anArgCase == "-noextra"
5404           || anArgCase == "-noextramsg"
5405           || anArgCase == "-noextramessages")
5406     {
5407       Standard_Boolean toSuppress = Standard_True;
5408       if (++anArgIter < theArgNb
5409       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5410       {
5411         --anArgIter;
5412       }
5413       aDefCaps->suppressExtraMsg = toSuppress;
5414       if (aCaps != NULL)
5415       {
5416         aCaps->suppressExtraMsg = toSuppress;
5417       }
5418     }
5419     else if (anArgCase == "-sync")
5420     {
5421       Standard_Boolean toSync = Standard_True;
5422       if (++anArgIter < theArgNb
5423       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5424       {
5425         --anArgIter;
5426       }
5427       aDefCaps->contextSyncDebug = toSync;
5428       if (toSync)
5429       {
5430         aDefCaps->contextDebug = Standard_True;
5431       }
5432     }
5433     else if (anArgCase == "-debug")
5434     {
5435       if (++anArgIter < theArgNb
5436       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5437       {
5438         --anArgIter;
5439       }
5440       aDefCaps->contextDebug = toEnableDebug;
5441     }
5442     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5443           && (anArgIter + 1 == theArgNb))
5444     {
5445       // simple alias to turn on almost everything
5446       aDefCaps->contextDebug     = toEnableDebug;
5447       aDefCaps->contextSyncDebug = toEnableDebug;
5448       aDefCaps->glslWarnings     = toEnableDebug;
5449     }
5450     else
5451     {
5452       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5453       return 1;
5454     }
5455   }
5456
5457   return 0;
5458 }
5459
5460 //==============================================================================
5461 //function : VVbo
5462 //purpose  :
5463 //==============================================================================
5464
5465 static int VVbo (Draw_Interpretor& theDI,
5466                  Standard_Integer  theArgNb,
5467                  const char**      theArgVec)
5468 {
5469   const Standard_Boolean toSet    = (theArgNb > 1);
5470   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5471   if (toSet)
5472   {
5473     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5474   }
5475
5476   // get the context
5477   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5478   if (aContextAIS.IsNull())
5479   {
5480     if (!toSet)
5481     {
5482       std::cerr << "No active view!\n";
5483     }
5484     return 1;
5485   }
5486   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5487   if (!aDriver.IsNull())
5488   {
5489     if (!toSet)
5490     {
5491       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5492     }
5493     else
5494     {
5495       aDriver->ChangeOptions().vboDisable = toUseVbo;
5496     }
5497   }
5498
5499   return 0;
5500 }
5501
5502 //==============================================================================
5503 //function : VCaps
5504 //purpose  :
5505 //==============================================================================
5506
5507 static int VCaps (Draw_Interpretor& theDI,
5508                   Standard_Integer  theArgNb,
5509                   const char**      theArgVec)
5510 {
5511   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5512   Handle(OpenGl_GraphicDriver)   aDriver;
5513   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5514   if (!aContext.IsNull())
5515   {
5516     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5517     aCaps   = &aDriver->ChangeOptions();
5518   }
5519
5520   if (theArgNb < 2)
5521   {
5522     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5523     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5524     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5525     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5526     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5527     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5528     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5529     return 0;
5530   }
5531
5532   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5533   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5534   {
5535     Standard_CString        anArg     = theArgVec[anArgIter];
5536     TCollection_AsciiString anArgCase (anArg);
5537     anArgCase.LowerCase();
5538     if (anUpdateTool.parseRedrawMode (anArg))
5539     {
5540       continue;
5541     }
5542     else if (anArgCase == "-vsync"
5543           || anArgCase == "-swapinterval")
5544     {
5545       Standard_Boolean toEnable = Standard_True;
5546       if (++anArgIter < theArgNb
5547       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5548       {
5549         --anArgIter;
5550       }
5551       aCaps->swapInterval = toEnable;
5552     }
5553     else if (anArgCase == "-ffp")
5554     {
5555       Standard_Boolean toEnable = Standard_True;
5556       if (++anArgIter < theArgNb
5557       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5558       {
5559         --anArgIter;
5560       }
5561       aCaps->ffpEnable = toEnable;
5562     }
5563     else if (anArgCase == "-vbo")
5564     {
5565       Standard_Boolean toEnable = Standard_True;
5566       if (++anArgIter < theArgNb
5567       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5568       {
5569         --anArgIter;
5570       }
5571       aCaps->vboDisable = !toEnable;
5572     }
5573     else if (anArgCase == "-sprite"
5574           || anArgCase == "-sprites")
5575     {
5576       Standard_Boolean toEnable = Standard_True;
5577       if (++anArgIter < theArgNb
5578       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5579       {
5580         --anArgIter;
5581       }
5582       aCaps->pntSpritesDisable = !toEnable;
5583     }
5584     else if (anArgCase == "-softmode")
5585     {
5586       Standard_Boolean toEnable = Standard_True;
5587       if (++anArgIter < theArgNb
5588       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5589       {
5590         --anArgIter;
5591       }
5592       aCaps->contextNoAccel = toEnable;
5593     }
5594     else if (anArgCase == "-accel"
5595           || anArgCase == "-acceleration")
5596     {
5597       Standard_Boolean toEnable = Standard_True;
5598       if (++anArgIter < theArgNb
5599       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5600       {
5601         --anArgIter;
5602       }
5603       aCaps->contextNoAccel = !toEnable;
5604     }
5605     else if (anArgCase == "-compat"
5606           || anArgCase == "-compatprofile"
5607           || anArgCase == "-compatible"
5608           || anArgCase == "-compatibleprofile")
5609     {
5610       Standard_Boolean toEnable = Standard_True;
5611       if (++anArgIter < theArgNb
5612       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5613       {
5614         --anArgIter;
5615       }
5616       aCaps->contextCompatible = toEnable;
5617       if (!aCaps->contextCompatible)
5618       {
5619         aCaps->ffpEnable = Standard_False;
5620       }
5621     }
5622     else if (anArgCase == "-core"
5623           || anArgCase == "-coreprofile")
5624     {
5625       Standard_Boolean toEnable = Standard_True;
5626       if (++anArgIter < theArgNb
5627       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5628       {
5629         --anArgIter;
5630       }
5631       aCaps->contextCompatible = !toEnable;
5632       if (!aCaps->contextCompatible)
5633       {
5634         aCaps->ffpEnable = Standard_False;
5635       }
5636     }
5637     else if (anArgCase == "-stereo"
5638           || anArgCase == "-quadbuffer")
5639     {
5640       Standard_Boolean toEnable = Standard_True;
5641       if (++anArgIter < theArgNb
5642       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5643       {
5644         --anArgIter;
5645       }
5646       aCaps->contextStereo = toEnable;
5647     }
5648     else
5649     {
5650       std::cout << "Error: unknown argument '" << anArg << "'\n";
5651       return 1;
5652     }
5653   }
5654   if (aCaps != &ViewerTest_myDefaultCaps)
5655   {
5656     ViewerTest_myDefaultCaps = *aCaps;
5657   }
5658   return 0;
5659 }
5660
5661 //==============================================================================
5662 //function : VMemGpu
5663 //purpose  :
5664 //==============================================================================
5665
5666 static int VMemGpu (Draw_Interpretor& theDI,
5667                     Standard_Integer  theArgNb,
5668                     const char**      theArgVec)
5669 {
5670   // get the context
5671   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5672   if (aContextAIS.IsNull())
5673   {
5674     std::cerr << "No active view. Please call vinit.\n";
5675     return 1;
5676   }
5677
5678   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5679   if (aDriver.IsNull())
5680   {
5681     std::cerr << "Graphic driver not available.\n";
5682     return 1;
5683   }
5684
5685   Standard_Size aFreeBytes = 0;
5686   TCollection_AsciiString anInfo;
5687   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5688   {
5689     std::cerr << "Information not available.\n";
5690     return 1;
5691   }
5692
5693   if (theArgNb > 1 && *theArgVec[1] == 'f')
5694   {
5695     theDI << Standard_Real (aFreeBytes);
5696   }
5697   else
5698   {
5699     theDI << anInfo;
5700   }
5701
5702   return 0;
5703 }
5704
5705 // ==============================================================================
5706 // function : VReadPixel
5707 // purpose  :
5708 // ==============================================================================
5709 static int VReadPixel (Draw_Interpretor& theDI,
5710                        Standard_Integer  theArgNb,
5711                        const char**      theArgVec)
5712 {
5713   // get the active view
5714   Handle(V3d_View) aView = ViewerTest::CurrentView();
5715   if (aView.IsNull())
5716   {
5717     std::cerr << "No active view. Please call vinit.\n";
5718     return 1;
5719   }
5720   else if (theArgNb < 3)
5721   {
5722     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5723     return 1;
5724   }
5725
5726   Image_PixMap::ImgFormat aFormat     = Image_PixMap::ImgRGBA;
5727   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
5728
5729   Standard_Integer aWidth, aHeight;
5730   aView->Window()->Size (aWidth, aHeight);
5731   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5732   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5733   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5734   {
5735     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5736     return 1;
5737   }
5738
5739   Standard_Boolean toShowName = Standard_False;
5740   Standard_Boolean toShowHls  = Standard_False;
5741   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5742   {
5743     const char* aParam = theArgVec[anIter];
5744     if ( strcasecmp( aParam, "rgb" ) == 0 )
5745     {
5746       aFormat     = Image_PixMap::ImgRGB;
5747       aBufferType = Graphic3d_BT_RGB;
5748     }
5749     else if ( strcasecmp( aParam, "hls" ) == 0 )
5750     {
5751       aFormat     = Image_PixMap::ImgRGB;
5752       aBufferType = Graphic3d_BT_RGB;
5753       toShowHls   = Standard_True;
5754     }
5755     else if ( strcasecmp( aParam, "rgbf" ) == 0 )
5756     {
5757       aFormat     = Image_PixMap::ImgRGBF;
5758       aBufferType = Graphic3d_BT_RGB;
5759     }
5760     else if ( strcasecmp( aParam, "rgba" ) == 0 )
5761     {
5762       aFormat     = Image_PixMap::ImgRGBA;
5763       aBufferType = Graphic3d_BT_RGBA;
5764     }
5765     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
5766     {
5767       aFormat     = Image_PixMap::ImgRGBAF;
5768       aBufferType = Graphic3d_BT_RGBA;
5769     }
5770     else if ( strcasecmp( aParam, "depth" ) == 0 )
5771     {
5772       aFormat     = Image_PixMap::ImgGrayF;
5773       aBufferType = Graphic3d_BT_Depth;
5774     }
5775     else if ( strcasecmp( aParam, "name" ) == 0 )
5776     {
5777       toShowName = Standard_True;
5778     }
5779   }
5780
5781   Image_PixMap anImage;
5782   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5783   {
5784     std::cerr << "Image allocation failed\n";
5785     return 1;
5786   }
5787   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5788   {
5789     std::cerr << "Image dump failed\n";
5790     return 1;
5791   }
5792
5793   Quantity_Parameter anAlpha;
5794   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5795   if (toShowName)
5796   {
5797     if (aBufferType == Graphic3d_BT_RGBA)
5798     {
5799       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5800     }
5801     else
5802     {
5803       theDI << Quantity_Color::StringName (aColor.Name());
5804     }
5805   }
5806   else
5807   {
5808     switch (aBufferType)
5809     {
5810       default:
5811       case Graphic3d_BT_RGB:
5812       {
5813         if (toShowHls)
5814         {
5815           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5816         }
5817         else
5818         {
5819           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5820         }
5821         break;
5822       }
5823       case Graphic3d_BT_RGBA:
5824       {
5825         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5826         break;
5827       }
5828       case Graphic3d_BT_Depth:
5829       {
5830         theDI << aColor.Red();
5831         break;
5832       }
5833     }
5834   }
5835
5836   return 0;
5837 }
5838
5839 //==============================================================================
5840 //function : VDiffImage
5841 //purpose  : The draw-command compares two images.
5842 //==============================================================================
5843
5844 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5845 {
5846   if (theArgNb < 6)
5847   {
5848     theDI << "Not enough arguments.\n";
5849     return 1;
5850   }
5851
5852   // image file names
5853   const char* anImgPathRef = theArgVec[1];
5854   const char* anImgPathNew = theArgVec[2];
5855
5856   // get string tolerance and check its validity
5857   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5858   if (aTolColor < 0.0)
5859     aTolColor = 0.0;
5860   if (aTolColor > 1.0)
5861     aTolColor = 1.0;
5862
5863   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5864   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5865
5866   // image file of difference
5867   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5868
5869   // compare the images
5870   Image_Diff aComparer;
5871   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5872   {
5873     return 1;
5874   }
5875
5876   aComparer.SetColorTolerance (aTolColor);
5877   aComparer.SetBorderFilterOn (isBorderFilterOn);
5878   Standard_Integer aDiffColorsNb = aComparer.Compare();
5879   theDI << aDiffColorsNb << "\n";
5880
5881   // save image of difference
5882   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5883   {
5884     aComparer.SaveDiffImage (aDiffImagePath);
5885   }
5886
5887   return 0;
5888 }
5889
5890 //=======================================================================
5891 //function : VSelect
5892 //purpose  : Emulates different types of selection by mouse:
5893 //           1) single click selection
5894 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5895 //           3) selection with polygon having corners at
5896 //           pixel positions (x1,y1),...,(xn,yn)
5897 //           4) any of these selections with shift button pressed
5898 //=======================================================================
5899 static Standard_Integer VSelect (Draw_Interpretor& di,
5900                                  Standard_Integer argc,
5901                                  const char ** argv)
5902 {
5903   if(argc < 3)
5904   {
5905     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5906     return 1;
5907   }
5908
5909   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5910   if(myAIScontext.IsNull())
5911   {
5912     di << "use 'vinit' command before " << argv[0] << "\n";
5913     return 1;
5914   }
5915
5916   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5917   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5918   TCollection_AsciiString anArg;
5919   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5920   anArg.LowerCase();
5921   if (anArg == "-allowoverlap")
5922   {
5923     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5924       : argc == 7;
5925     if (!isValidated)
5926     {
5927       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5928       return 1;
5929     }
5930
5931     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5932     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5933     aCoordsNb -= 2;
5934   }
5935
5936   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5937   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5938   if(aCoordsNb == 2)
5939   {
5940     if(isShiftSelection)
5941       aCurrentEventManager->ShiftSelect();
5942     else
5943       aCurrentEventManager->Select();
5944   }
5945   else if(aCoordsNb == 4)
5946   {
5947     if(isShiftSelection)
5948       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5949     else
5950       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5951   }
5952   else
5953   {
5954     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
5955
5956     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
5957       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
5958
5959     if(isShiftSelection)
5960       aCurrentEventManager->ShiftSelect(aPolyline);
5961     else
5962       aCurrentEventManager->Select(aPolyline);
5963   }
5964   return 0;
5965 }
5966
5967 //=======================================================================
5968 //function : VMoveTo
5969 //purpose  : Emulates cursor movement to defined pixel position
5970 //=======================================================================
5971 static Standard_Integer VMoveTo (Draw_Interpretor& di,
5972                                 Standard_Integer argc,
5973                                 const char ** argv)
5974 {
5975   if(argc != 3)
5976   {
5977     di << "Usage : " << argv[0] << " x y\n";
5978     return 1;
5979   }
5980
5981   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5982   if(aContext.IsNull())
5983   {
5984     di << "use 'vinit' command before " << argv[0] << "\n";
5985     return 1;
5986   }
5987   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
5988   return 0;
5989 }
5990
5991 namespace
5992 {
5993   //! Global map storing all animations registered in ViewerTest.
5994   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
5995
5996   //! The animation calling the Draw Harness command.
5997   class ViewerTest_AnimationProc : public AIS_Animation
5998   {
5999   public:
6000
6001     //! Main constructor.
6002     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6003                               Draw_Interpretor* theDI,
6004                               const TCollection_AsciiString& theCommand)
6005     : AIS_Animation (theAnimationName),
6006       myDrawInter(theDI),
6007       myCommand  (theCommand)
6008     {
6009       //
6010     }
6011
6012   protected:
6013
6014     //! Evaluate the command.
6015     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6016     {
6017       TCollection_AsciiString aCmd = myCommand;
6018       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6019       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6020       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6021       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6022       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6023       myDrawInter->Eval (aCmd.ToCString());
6024     }
6025
6026     //! Find the keyword in the command and replace it with value.
6027     //! @return the position of the keyword to pass value
6028     void replace (TCollection_AsciiString&       theCmd,
6029                   const TCollection_AsciiString& theKey,
6030                   const TCollection_AsciiString& theVal)
6031     {
6032       TCollection_AsciiString aCmd (theCmd);
6033       aCmd.LowerCase();
6034       const Standard_Integer aPos = aCmd.Search (theKey);
6035       if (aPos == -1)
6036       {
6037         return;
6038       }
6039
6040       TCollection_AsciiString aPart1, aPart2;
6041       Standard_Integer aPart1To = aPos - 1;
6042       if (aPart1To >= 1
6043        && aPart1To <= theCmd.Length())
6044       {
6045         aPart1 = theCmd.SubString (1, aPart1To);
6046       }
6047
6048       Standard_Integer aPart2From = aPos + theKey.Length();
6049       if (aPart2From >= 1
6050        && aPart2From <= theCmd.Length())
6051       {
6052         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6053       }
6054
6055       theCmd = aPart1 + theVal + aPart2;
6056     }
6057
6058   protected:
6059
6060     Draw_Interpretor*       myDrawInter;
6061     TCollection_AsciiString myCommand;
6062
6063   };
6064
6065   //! Replace the animation with the new one.
6066   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6067                                 Handle(AIS_Animation)&       theAnimation,
6068                                 const Handle(AIS_Animation)& theAnimationNew)
6069   {
6070     theAnimationNew->CopyFrom (theAnimation);
6071     if (!theParentAnimation.IsNull())
6072     {
6073       theParentAnimation->Replace (theAnimation, theAnimationNew);
6074     }
6075     else
6076     {
6077       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6078       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6079     }
6080     theAnimation = theAnimationNew;
6081   }
6082
6083   //! Parse the point.
6084   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6085   {
6086     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6087     if (!anXYZ[0].IsRealValue()
6088      || !anXYZ[1].IsRealValue()
6089      || !anXYZ[2].IsRealValue())
6090     {
6091       return Standard_False;
6092     }
6093
6094     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6095     return Standard_True;
6096   }
6097
6098   //! Parse the quaternion.
6099   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6100   {
6101     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6102     if (!anXYZW[0].IsRealValue()
6103      || !anXYZW[1].IsRealValue()
6104      || !anXYZW[2].IsRealValue()
6105      || !anXYZW[3].IsRealValue())
6106     {
6107       return Standard_False;
6108     }
6109
6110     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6111     return Standard_True;
6112   }
6113
6114 }
6115
6116 //=================================================================================================
6117 //function : VViewParams
6118 //purpose  : Gets or sets AIS View characteristics
6119 //=================================================================================================
6120 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6121 {
6122   Handle(V3d_View) aView = ViewerTest::CurrentView();
6123   if (aView.IsNull())
6124   {
6125     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6126     return 1;
6127   }
6128
6129   Standard_Boolean toSetProj     = Standard_False;
6130   Standard_Boolean toSetUp       = Standard_False;
6131   Standard_Boolean toSetAt       = Standard_False;
6132   Standard_Boolean toSetEye      = Standard_False;
6133   Standard_Boolean toSetScale    = Standard_False;
6134   Standard_Boolean toSetSize     = Standard_False;
6135   Standard_Boolean toSetCenter2d = Standard_False;
6136   Quantity_Factor  aViewScale = aView->Scale();
6137   Quantity_Length  aViewSize  = 1.0;
6138   Graphic3d_Vec2i  aCenter2d;
6139   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6140   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6141   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6142   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6143   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6144   if (theArgsNb == 1)
6145   {
6146     // print all of the available view parameters
6147     char aText[4096];
6148     Sprintf (aText,
6149              "Scale: %g\n"
6150              "Proj:  %12g %12g %12g\n"
6151              "Up:    %12g %12g %12g\n"
6152              "At:    %12g %12g %12g\n"
6153              "Eye:   %12g %12g %12g\n",
6154               aViewScale,
6155               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6156               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6157               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6158               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6159     theDi << aText;
6160     return 0;
6161   }
6162
6163   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6164   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6165   {
6166     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6167     anArg.LowerCase();
6168     if (anUpdateTool.parseRedrawMode (anArg))
6169     {
6170       continue;
6171     }
6172     else if (anArg == "-cmd"
6173           || anArg == "-command"
6174           || anArg == "-args")
6175     {
6176       char aText[4096];
6177       Sprintf (aText,
6178                "-scale %g "
6179                "-proj %g %g %g "
6180                "-up %g %g %g "
6181                "-at %g %g %g\n",
6182                 aViewScale,
6183                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6184                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6185                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6186       theDi << aText;
6187     }
6188     else if (anArg == "-scale"
6189           || anArg == "-size")
6190     {
6191       if (anArgIter + 1 < theArgsNb
6192        && *theArgVec[anArgIter + 1] != '-')
6193       {
6194         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6195         if (aValueArg.IsRealValue())
6196         {
6197           ++anArgIter;
6198           if (anArg == "-scale")
6199           {
6200             toSetScale = Standard_True;
6201             aViewScale = aValueArg.RealValue();
6202           }
6203           else if (anArg == "-size")
6204           {
6205             toSetSize = Standard_True;
6206             aViewSize = aValueArg.RealValue();
6207           }
6208           continue;
6209         }
6210       }
6211       if (anArg == "-scale")
6212       {
6213         theDi << "Scale: " << aView->Scale() << "\n";
6214       }
6215       else if (anArg == "-size")
6216       {
6217         Graphic3d_Vec2d aSizeXY;
6218         aView->Size (aSizeXY.x(), aSizeXY.y());
6219         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6220       }
6221     }
6222     else if (anArg == "-eye"
6223           || anArg == "-at"
6224           || anArg == "-up"
6225           || anArg == "-proj")
6226     {
6227       if (anArgIter + 3 < theArgsNb)
6228       {
6229         gp_XYZ anXYZ;
6230         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6231         {
6232           anArgIter += 3;
6233           if (anArg == "-eye")
6234           {
6235             toSetEye = Standard_True;
6236             aViewEye = anXYZ;
6237           }
6238           else if (anArg == "-at")
6239           {
6240             toSetAt = Standard_True;
6241             aViewAt = anXYZ;
6242           }
6243           else if (anArg == "-up")
6244           {
6245             toSetUp = Standard_True;
6246             aViewUp = anXYZ;
6247           }
6248           else if (anArg == "-proj")
6249           {
6250             toSetProj = Standard_True;
6251             aViewProj = anXYZ;
6252           }
6253           continue;
6254         }
6255       }
6256
6257       if (anArg == "-eye")
6258       {
6259         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6260       }
6261       else if (anArg == "-at")
6262       {
6263         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6264       }
6265       else if (anArg == "-up")
6266       {
6267         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6268       }
6269       else if (anArg == "-proj")
6270       {
6271         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6272       }
6273     }
6274     else if (anArg == "-center")
6275     {
6276       if (anArgIter + 2 < theArgsNb)
6277       {
6278         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6279         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6280         if (anX.IsIntegerValue()
6281          && anY.IsIntegerValue())
6282         {
6283           toSetCenter2d = Standard_True;
6284           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6285         }
6286       }
6287     }
6288     else
6289     {
6290       std::cout << "Syntax error at '" << anArg << "'\n";
6291       return 1;
6292     }
6293   }
6294
6295   // change view parameters in proper order
6296   if (toSetScale)
6297   {
6298     aView->SetScale (aViewScale);
6299   }
6300   if (toSetSize)
6301   {
6302     aView->SetSize (aViewSize);
6303   }
6304   if (toSetEye)
6305   {
6306     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6307   }
6308   if (toSetAt)
6309   {
6310     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6311   }
6312   if (toSetProj)
6313   {
6314     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6315   }
6316   if (toSetUp)
6317   {
6318     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6319   }
6320   if (toSetCenter2d)
6321   {
6322     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6323   }
6324
6325   return 0;
6326 }
6327
6328 //==============================================================================
6329 //function : VAnimation
6330 //purpose  :
6331 //==============================================================================
6332 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6333                                     Standard_Integer  theArgNb,
6334                                     const char**      theArgVec)
6335 {
6336   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6337   if (theArgNb < 2)
6338   {
6339     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6340          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6341     {
6342       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6343     }
6344     return 0;
6345   }
6346   if (aCtx.IsNull())
6347   {
6348     std::cout << "Error: no active view\n";
6349     return 1;
6350   }
6351
6352   Standard_Integer anArgIter = 1;
6353   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6354   if (aNameArg.IsEmpty())
6355   {
6356     std::cout << "Syntax error: animation name is not defined.\n";
6357     return 1;
6358   }
6359
6360   TCollection_AsciiString aNameArgLower = aNameArg;
6361   aNameArgLower.LowerCase();
6362   if (aNameArgLower == "-reset"
6363    || aNameArgLower == "-clear")
6364   {
6365     ViewerTest_AnimationTimelineMap.Clear();
6366     return 0;
6367   }
6368   else if (aNameArg.Value (1) == '-')
6369   {
6370     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6371     return 1;
6372   }
6373
6374   const char* aNameSplitter = "/";
6375   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6376   if (aSplitPos == -1)
6377   {
6378     aNameSplitter = ".";
6379     aSplitPos = aNameArg.Search (aNameSplitter);
6380   }
6381
6382   // find existing or create a new animation by specified name within syntax "parent.child".
6383   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6384   for (; !aNameArg.IsEmpty();)
6385   {
6386     TCollection_AsciiString aNameParent;
6387     if (aSplitPos != -1)
6388     {
6389       if (aSplitPos == aNameArg.Length())
6390       {
6391         std::cout << "Syntax error: animation name is not defined.\n";
6392         return 1;
6393       }
6394
6395       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6396       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6397
6398       aSplitPos = aNameArg.Search (aNameSplitter);
6399     }
6400     else
6401     {
6402       aNameParent = aNameArg;
6403       aNameArg.Clear();
6404     }
6405
6406     if (anAnimation.IsNull())
6407     {
6408       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6409       {
6410         anAnimation = new AIS_Animation (aNameParent);
6411         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6412       }
6413       aRootAnimation = anAnimation;
6414     }
6415     else
6416     {
6417       aParentAnimation = anAnimation;
6418       anAnimation = aParentAnimation->Find (aNameParent);
6419       if (anAnimation.IsNull())
6420       {
6421         anAnimation = new AIS_Animation (aNameParent);
6422         aParentAnimation->Add (anAnimation);
6423       }
6424     }
6425   }
6426
6427   if (anArgIter >= theArgNb)
6428   {
6429     // just print the list of children
6430     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
6431     {
6432       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
6433     }
6434     return 0;
6435   }
6436
6437   // animation parameters
6438   Standard_Boolean toPlay = Standard_False;
6439   Standard_Real aPlaySpeed     = 1.0;
6440   Standard_Real aPlayStartTime = anAnimation->StartPts();
6441   Standard_Real aPlayDuration  = anAnimation->Duration();
6442   Standard_Integer aFpsNum     = 0;
6443   Standard_Integer aFpsDen     = 1;
6444   Standard_Boolean isFreeCamera = Standard_False;
6445   Standard_Boolean isLockLoop   = Standard_False;
6446   Handle(V3d_View) aView = ViewerTest::CurrentView();
6447   for (; anArgIter < theArgNb; ++anArgIter)
6448   {
6449     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6450     anArg.LowerCase();
6451     // general options
6452     if (anArg == "-reset"
6453      || anArg == "-clear")
6454     {
6455       anAnimation->Clear();
6456     }
6457     else if (anArg == "-remove"
6458           || anArg == "-del"
6459           || anArg == "-delete")
6460     {
6461       if (!aParentAnimation.IsNull())
6462       {
6463         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
6464       }
6465       else
6466       {
6467         aParentAnimation->Remove (anAnimation);
6468       }
6469     }
6470     // playback options
6471     else if (anArg == "-play")
6472     {
6473       toPlay = Standard_True;
6474       if (++anArgIter < theArgNb)
6475       {
6476         if (*theArgVec[anArgIter] == '-')
6477         {
6478           --anArgIter;
6479           continue;
6480         }
6481         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
6482
6483         if (++anArgIter < theArgNb)
6484         {
6485           if (*theArgVec[anArgIter] == '-')
6486           {
6487             --anArgIter;
6488             continue;
6489           }
6490           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6491         }
6492       }
6493     }
6494     else if (anArg == "-resume")
6495     {
6496       toPlay = Standard_True;
6497       aPlayStartTime = anAnimation->ElapsedTime();
6498       if (++anArgIter < theArgNb)
6499       {
6500         if (*theArgVec[anArgIter] == '-')
6501         {
6502           --anArgIter;
6503           continue;
6504         }
6505
6506         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6507       }
6508     }
6509     else if (anArg == "-playspeed"
6510           || anArg == "-speed")
6511     {
6512       if (++anArgIter >= theArgNb)
6513       {
6514         std::cout << "Syntax error at " << anArg << ".\n";
6515         return 1;
6516       }
6517       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
6518     }
6519     else if (anArg == "-lock"
6520           || anArg == "-lockloop"
6521           || anArg == "-playlockloop")
6522     {
6523       isLockLoop = Standard_True;
6524     }
6525     else if (anArg == "-freecamera"
6526           || anArg == "-playfreecamera"
6527           || anArg == "-freelook")
6528     {
6529       isFreeCamera = Standard_True;
6530     }
6531     else if (anArg == "-fps")
6532     {
6533       if (++anArgIter >= theArgNb)
6534       {
6535         std::cout << "Syntax error at " << anArg << ".\n";
6536         return 1;
6537       }
6538
6539       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
6540       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
6541       if (aSplitIndex == 0)
6542       {
6543         aFpsNum = aFpsArg.IntegerValue();
6544       }
6545       else
6546       {
6547         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
6548         aFpsArg.Split (aFpsArg.Length() - 1);
6549         const TCollection_AsciiString aNumStr = aFpsArg;
6550         aFpsNum = aNumStr.IntegerValue();
6551         aFpsDen = aDenStr.IntegerValue();
6552         if (aFpsDen < 1)
6553         {
6554           std::cout << "Syntax error at " << anArg << ".\n";
6555           return 1;
6556         }
6557       }
6558     }
6559     // animation definition options
6560     else if (anArg == "-start"
6561           || anArg == "-starttime"
6562           || anArg == "-startpts")
6563     {
6564       if (++anArgIter >= theArgNb)
6565       {
6566         std::cout << "Syntax error at " << anArg << ".\n";
6567         return 1;
6568       }
6569
6570       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
6571       aRootAnimation->UpdateTotalDuration();
6572     }
6573     else if (anArg == "-end"
6574           || anArg == "-endtime"
6575           || anArg == "-endpts")
6576     {
6577       if (++anArgIter >= theArgNb)
6578       {
6579         std::cout << "Syntax error at " << anArg << ".\n";
6580         return 1;
6581       }
6582
6583       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
6584       aRootAnimation->UpdateTotalDuration();
6585     }
6586     else if (anArg == "-dur"
6587           || anArg == "-duration")
6588     {
6589       if (++anArgIter >= theArgNb)
6590       {
6591         std::cout << "Syntax error at " << anArg << ".\n";
6592         return 1;
6593       }
6594
6595       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
6596       aRootAnimation->UpdateTotalDuration();
6597     }
6598     else if (anArg == "-command"
6599           || anArg == "-cmd"
6600           || anArg == "-invoke"
6601           || anArg == "-eval"
6602           || anArg == "-proc")
6603     {
6604       if (++anArgIter >= theArgNb)
6605       {
6606         std::cout << "Syntax error at " << anArg << ".\n";
6607         return 1;
6608       }
6609
6610       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
6611       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
6612     }
6613     else if (anArg == "-objecttrsf"
6614           || anArg == "-objectransformation"
6615           || anArg == "-objtransformation"
6616           || anArg == "-objtrsf"
6617           || anArg == "-object"
6618           || anArg == "-obj")
6619     {
6620       if (++anArgIter >= theArgNb)
6621       {
6622         std::cout << "Syntax error at " << anArg << ".\n";
6623         return 1;
6624       }
6625
6626       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
6627       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
6628       if (!aMapOfAIS.IsBound2 (anObjName))
6629       {
6630         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
6631         return 1;
6632       }
6633
6634       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
6635       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
6636       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
6637       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
6638       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
6639       Standard_Boolean isTrsfSet = Standard_False;
6640       Standard_Integer aTrsfArgIter = anArgIter + 1;
6641       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
6642       {
6643         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
6644         aTrsfArg.LowerCase();
6645         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
6646         if (aTrsfArg.StartsWith ("-rotation")
6647          || aTrsfArg.StartsWith ("-rot"))
6648         {
6649           isTrsfSet = Standard_True;
6650           if (aTrsfArgIter + 4 >= theArgNb
6651           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
6652           {
6653             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6654             return 1;
6655           }
6656           aTrsfArgIter += 4;
6657         }
6658         else if (aTrsfArg.StartsWith ("-location")
6659               || aTrsfArg.StartsWith ("-loc"))
6660         {
6661           isTrsfSet = Standard_True;
6662           if (aTrsfArgIter + 3 >= theArgNb
6663           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
6664           {
6665             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6666             return 1;
6667           }
6668           aTrsfArgIter += 3;
6669         }
6670         else if (aTrsfArg.StartsWith ("-scale"))
6671         {
6672           isTrsfSet = Standard_True;
6673           if (++aTrsfArgIter >= theArgNb)
6674           {
6675             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6676             return 1;
6677           }
6678
6679           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
6680           if (!aScaleStr.IsRealValue())
6681           {
6682             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6683             return 1;
6684           }
6685           aScales[anIndex] = aScaleStr.RealValue();
6686         }
6687         else
6688         {
6689           anArgIter = aTrsfArgIter - 1;
6690           break;
6691         }
6692       }
6693       if (!isTrsfSet)
6694       {
6695         std::cout << "Syntax error at " << anArg << ".\n";
6696         return 1;
6697       }
6698       else if (aTrsfArgIter >= theArgNb)
6699       {
6700         anArgIter = theArgNb;
6701       }
6702
6703       aTrsfs[0].SetRotation        (aRotQuats[0]);
6704       aTrsfs[1].SetRotation        (aRotQuats[1]);
6705       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
6706       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
6707       aTrsfs[0].SetScaleFactor     (aScales[0]);
6708       aTrsfs[1].SetScaleFactor     (aScales[1]);
6709
6710       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
6711       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
6712     }
6713     else if (anArg == "-viewtrsf"
6714           || anArg == "-view")
6715     {
6716       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
6717       if (aCamAnimation.IsNull())
6718       {
6719         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
6720         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
6721       }
6722
6723       Handle(Graphic3d_Camera) aCams[2] =
6724       {
6725         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
6726         new Graphic3d_Camera (aCamAnimation->View()->Camera())
6727       };
6728
6729       Standard_Boolean isTrsfSet = Standard_False;
6730       Standard_Integer aViewArgIter = anArgIter + 1;
6731       for (; aViewArgIter < theArgNb; ++aViewArgIter)
6732       {
6733         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
6734         aViewArg.LowerCase();
6735         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
6736         if (aViewArg.StartsWith ("-scale"))
6737         {
6738           isTrsfSet = Standard_True;
6739           if (++aViewArgIter >= theArgNb)
6740           {
6741             std::cout << "Syntax error at " << anArg << ".\n";
6742             return 1;
6743           }
6744
6745           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
6746           if (!aScaleStr.IsRealValue())
6747           {
6748             std::cout << "Syntax error at " << aViewArg << ".\n";
6749             return 1;
6750           }
6751           Standard_Real aScale = aScaleStr.RealValue();
6752           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
6753           aCams[anIndex]->SetScale (aScale);
6754         }
6755         else if (aViewArg.StartsWith ("-eye")
6756               || aViewArg.StartsWith ("-center")
6757               || aViewArg.StartsWith ("-at")
6758               || aViewArg.StartsWith ("-up"))
6759         {
6760           isTrsfSet = Standard_True;
6761           gp_XYZ anXYZ;
6762           if (aViewArgIter + 3 >= theArgNb
6763           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
6764           {
6765             std::cout << "Syntax error at " << aViewArg << ".\n";
6766             return 1;
6767           }
6768           aViewArgIter += 3;
6769
6770           if (aViewArg.StartsWith ("-eye"))
6771           {
6772             aCams[anIndex]->SetEye (anXYZ);
6773           }
6774           else if (aViewArg.StartsWith ("-center")
6775                 || aViewArg.StartsWith ("-at"))
6776           {
6777             aCams[anIndex]->SetCenter (anXYZ);
6778           }
6779           else if (aViewArg.StartsWith ("-up"))
6780           {
6781             aCams[anIndex]->SetUp (anXYZ);
6782           }
6783         }
6784         else
6785         {
6786           anArgIter = aViewArgIter - 1;
6787           break;
6788         }
6789       }
6790       if (!isTrsfSet)
6791       {
6792         std::cout << "Syntax error at " << anArg << ".\n";
6793         return 1;
6794       }
6795       else if (aViewArgIter >= theArgNb)
6796       {
6797         anArgIter = theArgNb;
6798       }
6799
6800       aCamAnimation->SetCameraStart(aCams[0]);
6801       aCamAnimation->SetCameraEnd  (aCams[1]);
6802     }
6803     else
6804     {
6805       std::cout << "Syntax error at " << anArg << ".\n";
6806       return 1;
6807     }
6808   }
6809
6810   if (!toPlay)
6811   {
6812     return 0;
6813   }
6814
6815   // Start animation timeline and process frame updating.
6816   TheIsAnimating = Standard_True;
6817   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
6818   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
6819   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
6820   if (isFreeCamera)
6821   {
6822     aView->Camera()->Copy (aCameraBack);
6823   }
6824
6825   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
6826   if (aFpsNum <= 0)
6827   {
6828     while (!anAnimation->IsStopped())
6829     {
6830       aCameraBack->Copy (aView->Camera());
6831       const Standard_Real aPts = anAnimation->UpdateTimer();
6832       if (isFreeCamera)
6833       {
6834         aView->Camera()->Copy (aCameraBack);
6835       }
6836
6837       if (aPts >= anUpperPts)
6838       {
6839         anAnimation->Pause();
6840         break;
6841       }
6842
6843       if (aView->IsInvalidated())
6844       {
6845         aView->Redraw();
6846       }
6847       else
6848       {
6849         aView->RedrawImmediate();
6850       }
6851
6852       if (!isLockLoop)
6853       {
6854         // handle user events
6855         theDI.Eval ("after 1 set waiter 1");
6856         theDI.Eval ("vwait waiter");
6857       }
6858       if (!TheIsAnimating)
6859       {
6860         anAnimation->Pause();
6861         theDI << aPts;
6862         break;
6863       }
6864     }
6865
6866     if (aView->IsInvalidated())
6867     {
6868       aView->Redraw();
6869     }
6870     else
6871     {
6872       aView->RedrawImmediate();
6873     }
6874   }
6875   else
6876   {
6877     OSD_Timer aPerfTimer;
6878     aPerfTimer.Start();
6879
6880     // Manage frame-rated animation here
6881     Standard_Real aPts = aPlayStartTime;
6882     int64_t aNbFrames = 0;
6883     for (; aPts <= anUpperPts;)
6884     {
6885       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
6886       aPts = aPlayStartTime + aRecPts;
6887       ++aNbFrames;
6888       if (!anAnimation->Update (aPts))
6889       {
6890         break;
6891       }
6892
6893       aView->Redraw();
6894     }
6895
6896     aPerfTimer.Stop();
6897     anAnimation->Stop();
6898     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
6899     theDI << "Average FPS: " << aRecFps << "\n"
6900           << "Nb. Frames: "  << Standard_Real(aNbFrames);
6901
6902     aView->Redraw();
6903   }
6904
6905   aView->SetImmediateUpdate (wasImmediateUpdate);
6906   TheIsAnimating = Standard_False;
6907   return 0;
6908 }
6909
6910
6911 //=======================================================================
6912 //function : VChangeSelected
6913 //purpose  : Adds the shape to selection or remove one from it
6914 //=======================================================================
6915 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6916                                 Standard_Integer argc,
6917                                 const char ** argv)
6918 {
6919   if(argc != 2)
6920   {
6921     di<<"Usage : " << argv[0] << " shape \n";
6922     return 1;
6923   }
6924   //get AIS_Shape:
6925   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6926   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6927   TCollection_AsciiString aName(argv[1]);
6928   Handle(AIS_InteractiveObject) anAISObject;
6929
6930   if(!aMap.IsBound2(aName))
6931   {
6932     di<<"Use 'vdisplay' before";
6933     return 1;
6934   }
6935   else
6936   {
6937     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6938     if(anAISObject.IsNull()){
6939       di<<"No interactive object \n";
6940       return 1;
6941     }
6942
6943     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
6944   }
6945   return 0;
6946 }
6947
6948 //=======================================================================
6949 //function : VNbSelected
6950 //purpose  : Returns number of selected objects
6951 //=======================================================================
6952 static Standard_Integer VNbSelected (Draw_Interpretor& di,
6953                                 Standard_Integer argc,
6954                                 const char ** argv)
6955 {
6956   if(argc != 1)
6957   {
6958     di << "Usage : " << argv[0] << "\n";
6959     return 1;
6960   }
6961   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6962   if(aContext.IsNull())
6963   {
6964     di << "use 'vinit' command before " << argv[0] << "\n";
6965     return 1;
6966   }
6967   di << aContext->NbSelected() << "\n";
6968   return 0;
6969 }
6970
6971 //=======================================================================
6972 //function : VPurgeDisplay
6973 //purpose  : Switches altialiasing on or off
6974 //=======================================================================
6975 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
6976                                 Standard_Integer argc,
6977                                 const char ** argv)
6978 {
6979   if (argc > 1)
6980   {
6981     di << "Usage : " << argv[0] << "\n";
6982     return 1;
6983   }
6984   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6985   if (aContext.IsNull())
6986   {
6987     di << "use 'vinit' command before " << argv[0] << "\n";
6988     return 1;
6989   }
6990
6991   di << aContext->PurgeDisplay() << "\n";
6992   return 0;
6993 }
6994
6995 //=======================================================================
6996 //function : VSetViewSize
6997 //purpose  :
6998 //=======================================================================
6999 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7000                                 Standard_Integer argc,
7001                                 const char ** argv)
7002 {
7003   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7004   if(aContext.IsNull())
7005   {
7006     di << "use 'vinit' command before " << argv[0] << "\n";
7007     return 1;
7008   }
7009   if(argc != 2)
7010   {
7011     di<<"Usage : " << argv[0] << " Size\n";
7012     return 1;
7013   }
7014   Standard_Real aSize = Draw::Atof (argv[1]);
7015   if (aSize <= 0.)
7016   {
7017     di<<"Bad Size value  : " << aSize << "\n";
7018     return 1;
7019   }
7020
7021   Handle(V3d_View) aView = ViewerTest::CurrentView();
7022   aView->SetSize(aSize);
7023   return 0;
7024 }
7025
7026 //=======================================================================
7027 //function : VMoveView
7028 //purpose  :
7029 //=======================================================================
7030 static Standard_Integer VMoveView (Draw_Interpretor& di,
7031                                 Standard_Integer argc,
7032                                 const char ** argv)
7033 {
7034   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7035   if(aContext.IsNull())
7036   {
7037     di << "use 'vinit' command before " << argv[0] << "\n";
7038     return 1;
7039   }
7040   if(argc < 4 || argc > 5)
7041   {
7042     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7043     return 1;
7044   }
7045   Standard_Real Dx = Draw::Atof (argv[1]);
7046   Standard_Real Dy = Draw::Atof (argv[2]);
7047   Standard_Real Dz = Draw::Atof (argv[3]);
7048   Standard_Boolean aStart = Standard_True;
7049   if (argc == 5)
7050   {
7051       aStart = (Draw::Atoi (argv[4]) > 0);
7052   }
7053
7054   Handle(V3d_View) aView = ViewerTest::CurrentView();
7055   aView->Move(Dx,Dy,Dz,aStart);
7056   return 0;
7057 }
7058
7059 //=======================================================================
7060 //function : VTranslateView
7061 //purpose  :
7062 //=======================================================================
7063 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7064                                 Standard_Integer argc,
7065                                 const char ** argv)
7066 {
7067   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7068   if(aContext.IsNull())
7069   {
7070     di << "use 'vinit' command before " << argv[0] << "\n";
7071     return 1;
7072   }
7073   if(argc < 4 || argc > 5)
7074   {
7075     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7076     return 1;
7077   }
7078   Standard_Real Dx = Draw::Atof (argv[1]);
7079   Standard_Real Dy = Draw::Atof (argv[2]);
7080   Standard_Real Dz = Draw::Atof (argv[3]);
7081   Standard_Boolean aStart = Standard_True;
7082   if (argc == 5)
7083   {
7084       aStart = (Draw::Atoi (argv[4]) > 0);
7085   }
7086
7087   Handle(V3d_View) aView = ViewerTest::CurrentView();
7088   aView->Translate(Dx,Dy,Dz,aStart);
7089   return 0;
7090 }
7091
7092 //=======================================================================
7093 //function : VTurnView
7094 //purpose  :
7095 //=======================================================================
7096 static Standard_Integer VTurnView (Draw_Interpretor& di,
7097                                 Standard_Integer argc,
7098                                 const char ** argv)
7099 {
7100   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7101   if(aContext.IsNull()) {
7102     di << "use 'vinit' command before " << argv[0] << "\n";
7103     return 1;
7104   }
7105   if(argc < 4 || argc > 5){
7106     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7107     return 1;
7108   }
7109   Standard_Real Ax = Draw::Atof (argv[1]);
7110   Standard_Real Ay = Draw::Atof (argv[2]);
7111   Standard_Real Az = Draw::Atof (argv[3]);
7112   Standard_Boolean aStart = Standard_True;
7113   if (argc == 5)
7114   {
7115       aStart = (Draw::Atoi (argv[4]) > 0);
7116   }
7117
7118   Handle(V3d_View) aView = ViewerTest::CurrentView();
7119   aView->Turn(Ax,Ay,Az,aStart);
7120   return 0;
7121 }
7122
7123 //==============================================================================
7124 //function : VTextureEnv
7125 //purpose  : ENables or disables environment mapping
7126 //==============================================================================
7127 class OCC_TextureEnv : public Graphic3d_TextureEnv
7128 {
7129 public:
7130   OCC_TextureEnv(const Standard_CString FileName);
7131   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7132   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7133                             const Standard_Boolean theModulateFlag,
7134                             const Graphic3d_TypeOfTextureFilter theFilter,
7135                             const Standard_ShortReal theXScale,
7136                             const Standard_ShortReal theYScale,
7137                             const Standard_ShortReal theXShift,
7138                             const Standard_ShortReal theYShift,
7139                             const Standard_ShortReal theAngle);
7140   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7141 };
7142 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7143
7144 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7145   : Graphic3d_TextureEnv(theFileName)
7146 {
7147 }
7148
7149 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7150   : Graphic3d_TextureEnv(theTexId)
7151 {
7152 }
7153
7154 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7155                                           const Standard_Boolean theModulateFlag,
7156                                           const Graphic3d_TypeOfTextureFilter theFilter,
7157                                           const Standard_ShortReal theXScale,
7158                                           const Standard_ShortReal theYScale,
7159                                           const Standard_ShortReal theXShift,
7160                                           const Standard_ShortReal theYShift,
7161                                           const Standard_ShortReal theAngle)
7162 {
7163   myParams->SetRepeat     (theRepeatFlag);
7164   myParams->SetModulate   (theModulateFlag);
7165   myParams->SetFilter     (theFilter);
7166   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7167   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7168   myParams->SetRotation   (theAngle);
7169 }
7170
7171 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7172 {
7173   // get the active view
7174   Handle(V3d_View) aView = ViewerTest::CurrentView();
7175   if (aView.IsNull())
7176   {
7177     std::cerr << "No active view. Please call vinit.\n";
7178     return 1;
7179   }
7180
7181   // Checking the input arguments
7182   Standard_Boolean anEnableFlag = Standard_False;
7183   Standard_Boolean isOk         = theArgNb >= 2;
7184   if (isOk)
7185   {
7186     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7187     anEnableFlag = anEnableOpt.IsEqual("on");
7188     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7189   }
7190   if (anEnableFlag)
7191   {
7192     isOk = (theArgNb == 3 || theArgNb == 11);
7193     if (isOk)
7194     {
7195       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7196       isOk = (!aTextureOpt.IsIntegerValue() ||
7197              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7198
7199       if (isOk && theArgNb == 11)
7200       {
7201         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7202                                 aModulateOpt(theArgVec[4]),
7203                                 aFilterOpt  (theArgVec[5]),
7204                                 aSScaleOpt  (theArgVec[6]),
7205                                 aTScaleOpt  (theArgVec[7]),
7206                                 aSTransOpt  (theArgVec[8]),
7207                                 aTTransOpt  (theArgVec[9]),
7208                                 anAngleOpt  (theArgVec[10]);
7209         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7210                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7211                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7212                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7213                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7214                 anAngleOpt.IsRealValue());
7215       }
7216     }
7217   }
7218
7219   if (!isOk)
7220   {
7221     std::cerr << "Usage :" << std::endl;
7222     std::cerr << theArgVec[0] << " off" << std::endl;
7223     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;
7224     return 1;
7225   }
7226
7227   if (anEnableFlag)
7228   {
7229     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7230     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7231                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7232                                      new OCC_TextureEnv(theArgVec[2]);
7233
7234     if (theArgNb == 11)
7235     {
7236       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7237       aTexEnv->SetTextureParameters(
7238         aRepeatOpt.  IsEqual("repeat"),
7239         aModulateOpt.IsEqual("modulate"),
7240         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7241                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7242                                                                            Graphic3d_TOTF_TRILINEAR,
7243         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7244         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7245         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7246         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7247         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7248         );
7249     }
7250     aView->SetTextureEnv(aTexEnv);
7251   }
7252   else // Disabling environment mapping
7253   {
7254     Handle(Graphic3d_TextureEnv) aTexture;
7255     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7256   }
7257
7258   aView->Redraw();
7259   return 0;
7260 }
7261
7262 namespace
7263 {
7264   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7265
7266   //! Remove registered clipping plane from all views and objects.
7267   static void removePlane (MapOfPlanes& theRegPlanes,
7268                            const TCollection_AsciiString& theName)
7269   {
7270     Handle(Graphic3d_ClipPlane) aClipPlane;
7271     if (!theRegPlanes.Find (theName, aClipPlane))
7272     {
7273       std::cout << "Warning: no such plane.\n";
7274       return;
7275     }
7276
7277     theRegPlanes.UnBind (theName);
7278     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7279          anIObjIt.More(); anIObjIt.Next())
7280     {
7281       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7282       aPrs->RemoveClipPlane (aClipPlane);
7283     }
7284
7285     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
7286          aViewIt.More(); aViewIt.Next())
7287     {
7288       const Handle(V3d_View)& aView = aViewIt.Key2();
7289       aView->RemoveClipPlane(aClipPlane);
7290     }
7291
7292     ViewerTest::RedrawAllViews();
7293   }
7294 }
7295
7296 //===============================================================================================
7297 //function : VClipPlane
7298 //purpose  :
7299 //===============================================================================================
7300 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7301 {
7302   // use short-cut for created clip planes map of created (or "registered by name") clip planes
7303   static MapOfPlanes aRegPlanes;
7304
7305   if (theArgsNb < 2)
7306   {
7307     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
7308     {
7309       theDi << aPlaneIter.Key() << " ";
7310     }
7311     return 0;
7312   }
7313
7314   TCollection_AsciiString aCommand (theArgVec[1]);
7315   aCommand.LowerCase();
7316   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
7317   if (anActiveView.IsNull())
7318   {
7319     std::cout << "Error: no active view.\n";
7320     return 1;
7321   }
7322
7323   // print maximum number of planes for current viewer
7324   if (aCommand == "-maxplanes"
7325    || aCommand == "maxplanes")
7326   {
7327     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
7328           << " plane slots provided by driver.\n";
7329     return 0;
7330   }
7331
7332   // create / delete plane instance
7333   if (aCommand == "-create"
7334    || aCommand == "create"
7335    || aCommand == "-delete"
7336    || aCommand == "delete"
7337    || aCommand == "-clone"
7338    || aCommand == "clone")
7339   {
7340     if (theArgsNb < 3)
7341     {
7342       std::cout << "Syntax error: plane name is required.\n";
7343       return 1;
7344     }
7345
7346     Standard_Boolean toCreate = aCommand == "-create"
7347                              || aCommand == "create";
7348     Standard_Boolean toClone  = aCommand == "-clone"
7349                              || aCommand == "clone";
7350     Standard_Boolean toDelete = aCommand == "-delete"
7351                              || aCommand == "delete";
7352     TCollection_AsciiString aPlane (theArgVec[2]);
7353
7354     if (toCreate)
7355     {
7356       if (aRegPlanes.IsBound (aPlane))
7357       {
7358         std::cout << "Warning: existing plane has been overridden.\n";
7359         toDelete = true;
7360       }
7361       else
7362       {
7363         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7364         return 0;
7365       }
7366     }
7367     else if (toClone) // toClone
7368     {
7369       if (!aRegPlanes.IsBound (aPlane))
7370       {
7371         std::cout << "Error: no such plane.\n";
7372         return 1;
7373       }
7374       else if (theArgsNb < 4)
7375       {
7376         std::cout << "Syntax error: enter name for new plane.\n";
7377         return 1;
7378       }
7379
7380       TCollection_AsciiString aClone (theArgVec[3]);
7381       if (aRegPlanes.IsBound (aClone))
7382       {
7383         std::cout << "Error: plane name is in use.\n";
7384         return 1;
7385       }
7386
7387       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
7388
7389       aRegPlanes.Bind (aClone, aClipPlane->Clone());
7390       return 0;
7391     }
7392
7393     if (toDelete)
7394     {
7395       if (aPlane == "ALL"
7396        || aPlane == "all"
7397        || aPlane == "*")
7398       {
7399         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
7400         {
7401           aPlane = aPlaneIter.Key();
7402           removePlane (aRegPlanes, aPlane);
7403           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
7404         }
7405       }
7406       else
7407       {
7408         removePlane (aRegPlanes, aPlane);
7409       }
7410     }
7411
7412     if (toCreate)
7413     {
7414       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7415     }
7416     return 0;
7417   }
7418
7419   // set / unset plane command
7420   if (aCommand == "set"
7421    || aCommand == "unset")
7422   {
7423     if (theArgsNb < 5)
7424     {
7425       std::cout << "Syntax error: need more arguments.\n";
7426       return 1;
7427     }
7428
7429     // redirect to new syntax
7430     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
7431     anArgVec.SetValue (1, theArgVec[0]);
7432     anArgVec.SetValue (2, theArgVec[2]);
7433     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
7434     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
7435     {
7436       anArgVec.SetValue (anIt, theArgVec[anIt]);
7437     }
7438
7439     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
7440   }
7441
7442   // change plane command
7443   TCollection_AsciiString aPlaneName;
7444   Handle(Graphic3d_ClipPlane) aClipPlane;
7445   Standard_Integer anArgIter = 0;
7446   if (aCommand == "-change"
7447    || aCommand == "change")
7448   {
7449     // old syntax support
7450     if (theArgsNb < 3)
7451     {
7452       std::cout << "Syntax error: need more arguments.\n";
7453       return 1;
7454     }
7455
7456     anArgIter  = 3;
7457     aPlaneName = theArgVec[2];
7458     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
7459     {
7460       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
7461       return 1;
7462     }
7463   }
7464   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
7465   {
7466     anArgIter  = 2;
7467     aPlaneName = theArgVec[1];
7468   }
7469   else
7470   {
7471     anArgIter  = 2;
7472     aPlaneName = theArgVec[1];
7473     aClipPlane = new Graphic3d_ClipPlane();
7474     aRegPlanes.Bind (aPlaneName, aClipPlane);
7475     theDi << "Created new plane " << aPlaneName << ".\n";
7476   }
7477
7478   if (theArgsNb - anArgIter < 1)
7479   {
7480     std::cout << "Syntax error: need more arguments.\n";
7481     return 1;
7482   }
7483
7484   for (; anArgIter < theArgsNb; ++anArgIter)
7485   {
7486     const char**     aChangeArgs   = theArgVec + anArgIter;
7487     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
7488     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
7489     aChangeArg.LowerCase();
7490
7491     Standard_Boolean toEnable = Standard_True;
7492     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
7493     {
7494       aClipPlane->SetOn (toEnable);
7495     }
7496     else if (aChangeArg == "-equation"
7497           || aChangeArg == "equation")
7498     {
7499       if (aNbChangeArgs < 5)
7500       {
7501         std::cout << "Syntax error: need more arguments.\n";
7502         return 1;
7503       }
7504
7505       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
7506       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
7507       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
7508       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
7509       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
7510       anArgIter += 4;
7511     }
7512     else if (aChangeArg == "-capping"
7513           || aChangeArg == "capping")
7514     {
7515       if (aNbChangeArgs < 2)
7516       {
7517         std::cout << "Syntax error: need more arguments.\n";
7518         return 1;
7519       }
7520
7521       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7522       {
7523         aClipPlane->SetCapping (toEnable);
7524         anArgIter += 1;
7525       }
7526       else
7527       {
7528         // just skip otherwise (old syntax)
7529       }
7530     }
7531     else if (aChangeArg == "-useobjectmaterial"
7532           || aChangeArg == "-useobjectmat"
7533           || aChangeArg == "-useobjmat"
7534           || aChangeArg == "-useobjmaterial")
7535     {
7536       if (aNbChangeArgs < 2)
7537       {
7538         std::cout << "Syntax error: need more arguments.\n";
7539         return 1;
7540       }
7541
7542       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7543       {
7544         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
7545         anArgIter += 1;
7546       }
7547     }
7548     else if (aChangeArg == "-useobjecttexture"
7549           || aChangeArg == "-useobjecttex"
7550           || aChangeArg == "-useobjtexture"
7551           || aChangeArg == "-useobjtex")
7552     {
7553       if (aNbChangeArgs < 2)
7554       {
7555         std::cout << "Syntax error: need more arguments.\n";
7556         return 1;
7557       }
7558
7559       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7560       {
7561         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
7562         anArgIter += 1;
7563       }
7564     }
7565     else if (aChangeArg == "-useobjectshader"
7566           || aChangeArg == "-useobjshader")
7567     {
7568       if (aNbChangeArgs < 2)
7569       {
7570         std::cout << "Syntax error: need more arguments.\n";
7571         return 1;
7572       }
7573
7574       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7575       {
7576         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
7577         anArgIter += 1;
7578       }
7579     }
7580     else if (aChangeArg == "-color"
7581           || aChangeArg == "color")
7582     {
7583       Quantity_Color aColor;
7584       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
7585                                                            aChangeArgs + 1,
7586                                                            aColor);
7587       if (aNbParsed == 0)
7588       {
7589         std::cout << "Syntax error: need more arguments.\n";
7590         return 1;
7591       }
7592
7593       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
7594       aMat.SetAmbientColor (aColor);
7595       aMat.SetDiffuseColor (aColor);
7596       aClipPlane->SetCappingMaterial (aMat);
7597       anArgIter += aNbParsed;
7598     }
7599     else if (aChangeArg == "-texname"
7600           || aChangeArg == "texname")
7601     {
7602       if (aNbChangeArgs < 2)
7603       {
7604         std::cout << "Syntax error: need more arguments.\n";
7605         return 1;
7606       }
7607
7608       TCollection_AsciiString aTextureName (aChangeArgs[1]);
7609       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
7610       if (!aTexture->IsDone())
7611       {
7612         aClipPlane->SetCappingTexture (NULL);
7613       }
7614       else
7615       {
7616         aTexture->EnableModulate();
7617         aTexture->EnableRepeat();
7618         aClipPlane->SetCappingTexture (aTexture);
7619       }
7620       anArgIter += 1;
7621     }
7622     else if (aChangeArg == "-texscale"
7623           || aChangeArg == "texscale")
7624     {
7625       if (aClipPlane->CappingTexture().IsNull())
7626       {
7627         std::cout << "Error: no texture is set.\n";
7628         return 1;
7629       }
7630
7631       if (aNbChangeArgs < 3)
7632       {
7633         std::cout << "Syntax error: need more arguments.\n";
7634         return 1;
7635       }
7636
7637       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7638       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7639       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
7640       anArgIter += 2;
7641     }
7642     else if (aChangeArg == "-texorigin"
7643           || aChangeArg == "texorigin") // texture origin
7644     {
7645       if (aClipPlane->CappingTexture().IsNull())
7646       {
7647         std::cout << "Error: no texture is set.\n";
7648         return 1;
7649       }
7650
7651       if (aNbChangeArgs < 3)
7652       {
7653         std::cout << "Syntax error: need more arguments.\n";
7654         return 1;
7655       }
7656
7657       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7658       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7659
7660       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
7661       anArgIter += 2;
7662     }
7663     else if (aChangeArg == "-texrotate"
7664           || aChangeArg == "texrotate") // texture rotation
7665     {
7666       if (aClipPlane->CappingTexture().IsNull())
7667       {
7668         std::cout << "Error: no texture is set.\n";
7669         return 1;
7670       }
7671
7672       if (aNbChangeArgs < 2)
7673       {
7674         std::cout << "Syntax error: need more arguments.\n";
7675         return 1;
7676       }
7677
7678       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7679       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
7680       anArgIter += 1;
7681     }
7682     else if (aChangeArg == "-hatch"
7683           || aChangeArg == "hatch")
7684     {
7685       if (aNbChangeArgs < 2)
7686       {
7687         std::cout << "Syntax error: need more arguments.\n";
7688         return 1;
7689       }
7690
7691       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
7692       aHatchStr.LowerCase();
7693       if (aHatchStr == "on")
7694       {
7695         aClipPlane->SetCappingHatchOn();
7696       }
7697       else if (aHatchStr == "off")
7698       {
7699         aClipPlane->SetCappingHatchOff();
7700       }
7701       else
7702       {
7703         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
7704       }
7705       anArgIter += 1;
7706     }
7707     else if (aChangeArg == "-delete"
7708           || aChangeArg == "delete")
7709     {
7710       removePlane (aRegPlanes, aPlaneName);
7711       return 0;
7712     }
7713     else if (aChangeArg == "-set"
7714           || aChangeArg == "-unset")
7715     {
7716       // set / unset plane command
7717       Standard_Boolean toSet = aChangeArg == "-set";
7718       Standard_Integer anIt = 1;
7719       for (; anIt < aNbChangeArgs; ++anIt)
7720       {
7721         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
7722         if (anEntityName.IsEmpty()
7723          || anEntityName.Value (1) == '-')
7724         {
7725           break;
7726         }
7727         else if (ViewerTest_myViews.IsBound1 (anEntityName))
7728         {
7729           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
7730           if (toSet)
7731           {
7732             aView->AddClipPlane (aClipPlane);
7733           }
7734           else
7735           {
7736             aView->RemoveClipPlane (aClipPlane);
7737           }
7738           continue;
7739         }
7740         else if (GetMapOfAIS().IsBound2 (anEntityName))
7741         {
7742           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
7743           if (toSet)
7744           {
7745             aIObj->AddClipPlane (aClipPlane);
7746           }
7747           else
7748           {
7749             aIObj->RemoveClipPlane (aClipPlane);
7750           }
7751         }
7752         else
7753         {
7754           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
7755           return 1;
7756         }
7757       }
7758
7759       if (anIt == 1)
7760       {
7761         // apply to active view
7762         if (toSet)
7763         {
7764           anActiveView->AddClipPlane (aClipPlane);
7765         }
7766         else
7767         {
7768           anActiveView->RemoveClipPlane (aClipPlane);
7769         }
7770       }
7771       else
7772       {
7773         anArgIter = anArgIter + anIt - 1;
7774       }
7775     }
7776     else
7777     {
7778       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
7779       return 1;
7780     }
7781   }
7782
7783   ViewerTest::RedrawAllViews();
7784   return 0;
7785 }
7786
7787 //===============================================================================================
7788 //function : VZRange
7789 //purpose  :
7790 //===============================================================================================
7791 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7792 {
7793   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7794
7795   if (aCurrentView.IsNull())
7796   {
7797     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7798     return 1;
7799   }
7800
7801   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
7802
7803   if (theArgsNb < 2)
7804   {
7805     theDi << "ZNear: " << aCamera->ZNear() << "\n";
7806     theDi << "ZFar: " << aCamera->ZFar() << "\n";
7807     return 0;
7808   }
7809
7810   if (theArgsNb == 3)
7811   {
7812     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
7813     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
7814
7815     if (aNewZNear >= aNewZFar)
7816     {
7817       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
7818       return 1;
7819     }
7820
7821     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
7822     {
7823       std::cout << theArgVec[0] << ": invalid arguments: ";
7824       std::cout << "znear, zfar should be positive for perspective camera.\n";
7825       return 1;
7826     }
7827
7828     aCamera->SetZRange (aNewZNear, aNewZFar);
7829   }
7830   else
7831   {
7832     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7833     return 1;
7834   }
7835
7836   aCurrentView->Redraw();
7837
7838   return 0;
7839 }
7840
7841 //===============================================================================================
7842 //function : VAutoZFit
7843 //purpose  :
7844 //===============================================================================================
7845 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7846 {
7847   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7848
7849   if (aCurrentView.IsNull())
7850   {
7851     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7852     return 1;
7853   }
7854
7855   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
7856
7857   if (theArgsNb > 3)
7858   {
7859     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7860     return 1;
7861   }
7862
7863   if (theArgsNb < 2)
7864   {
7865     theDi << "Auto z-fit mode: \n"
7866           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
7867           << "Scale: " << aScale << "\n";
7868     return 0;
7869   }
7870
7871   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
7872
7873   if (theArgsNb >= 3)
7874   {
7875     aScale = Draw::Atoi (theArgVec[2]);
7876   }
7877
7878   aCurrentView->SetAutoZFitMode (isOn, aScale);
7879   aCurrentView->AutoZFit();
7880   aCurrentView->Redraw();
7881
7882   return 0;
7883 }
7884
7885 //! Auxiliary function to print projection type
7886 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
7887 {
7888   switch (theProjType)
7889   {
7890     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
7891     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
7892     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
7893     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
7894     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
7895   }
7896   return "UNKNOWN";
7897 }
7898
7899 //===============================================================================================
7900 //function : VCamera
7901 //purpose  :
7902 //===============================================================================================
7903 static int VCamera (Draw_Interpretor& theDI,
7904                     Standard_Integer  theArgsNb,
7905                     const char**      theArgVec)
7906 {
7907   Handle(V3d_View) aView = ViewerTest::CurrentView();
7908   if (aView.IsNull())
7909   {
7910     std::cout << "Error: no active view.\n";
7911     return 1;
7912   }
7913
7914   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7915   if (theArgsNb < 2)
7916   {
7917     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7918     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7919     theDI << "Distance:   " << aCamera->Distance() << "\n";
7920     theDI << "IOD:        " << aCamera->IOD() << "\n";
7921     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7922     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7923     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7924     return 0;
7925   }
7926
7927   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7928   {
7929     Standard_CString        anArg = theArgVec[anArgIter];
7930     TCollection_AsciiString anArgCase (anArg);
7931     anArgCase.LowerCase();
7932     if (anArgCase == "-proj"
7933      || anArgCase == "-projection"
7934      || anArgCase == "-projtype"
7935      || anArgCase == "-projectiontype")
7936     {
7937       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7938     }
7939     else if (anArgCase == "-ortho"
7940           || anArgCase == "-orthographic")
7941     {
7942       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
7943     }
7944     else if (anArgCase == "-persp"
7945           || anArgCase == "-perspective"
7946           || anArgCase == "-perspmono"
7947           || anArgCase == "-perspectivemono"
7948           || anArgCase == "-mono")
7949     {
7950       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7951     }
7952     else if (anArgCase == "-stereo"
7953           || anArgCase == "-stereoscopic"
7954           || anArgCase == "-perspstereo"
7955           || anArgCase == "-perspectivestereo")
7956     {
7957       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7958     }
7959     else if (anArgCase == "-left"
7960           || anArgCase == "-lefteye"
7961           || anArgCase == "-monoleft"
7962           || anArgCase == "-monolefteye"
7963           || anArgCase == "-perpsleft"
7964           || anArgCase == "-perpslefteye")
7965     {
7966       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
7967     }
7968     else if (anArgCase == "-right"
7969           || anArgCase == "-righteye"
7970           || anArgCase == "-monoright"
7971           || anArgCase == "-monorighteye"
7972           || anArgCase == "-perpsright")
7973     {
7974       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
7975     }
7976     else if (anArgCase == "-dist"
7977           || anArgCase == "-distance")
7978     {
7979       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7980       if (anArgValue != NULL
7981       && *anArgValue != '-')
7982       {
7983         ++anArgIter;
7984         aCamera->SetDistance (Draw::Atof (anArgValue));
7985         continue;
7986       }
7987       theDI << aCamera->Distance() << " ";
7988     }
7989     else if (anArgCase == "-iod")
7990     {
7991       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7992       if (anArgValue != NULL
7993       && *anArgValue != '-')
7994       {
7995         ++anArgIter;
7996         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
7997         continue;
7998       }
7999       theDI << aCamera->IOD() << " ";
8000     }
8001     else if (anArgCase == "-iodtype")
8002     {
8003       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8004       TCollection_AsciiString anValueCase (anArgValue);
8005       anValueCase.LowerCase();
8006       if (anValueCase == "abs"
8007        || anValueCase == "absolute")
8008       {
8009         ++anArgIter;
8010         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8011         continue;
8012       }
8013       else if (anValueCase == "rel"
8014             || anValueCase == "relative")
8015       {
8016         ++anArgIter;
8017         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8018         continue;
8019       }
8020       else if (*anArgValue != '-')
8021       {
8022         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8023         return 1;
8024       }
8025       switch (aCamera->GetIODType())
8026       {
8027         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8028         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8029       }
8030     }
8031     else if (anArgCase == "-zfocus")
8032     {
8033       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8034       if (anArgValue != NULL
8035       && *anArgValue != '-')
8036       {
8037         ++anArgIter;
8038         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8039         continue;
8040       }
8041       theDI << aCamera->ZFocus() << " ";
8042     }
8043     else if (anArgCase == "-zfocustype")
8044     {
8045       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8046       TCollection_AsciiString anValueCase (anArgValue);
8047       anValueCase.LowerCase();
8048       if (anValueCase == "abs"
8049        || anValueCase == "absolute")
8050       {
8051         ++anArgIter;
8052         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8053         continue;
8054       }
8055       else if (anValueCase == "rel"
8056             || anValueCase == "relative")
8057       {
8058         ++anArgIter;
8059         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8060         continue;
8061       }
8062       else if (*anArgValue != '-')
8063       {
8064         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8065         return 1;
8066       }
8067       switch (aCamera->ZFocusType())
8068       {
8069         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8070         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8071       }
8072     }
8073     else if (anArgCase == "-fov"
8074           || anArgCase == "-fovy")
8075     {
8076       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8077       if (anArgValue != NULL
8078       && *anArgValue != '-')
8079       {
8080         ++anArgIter;
8081         aCamera->SetFOVy (Draw::Atof (anArgValue));
8082         continue;
8083       }
8084       theDI << aCamera->FOVy() << " ";
8085     }
8086     else
8087     {
8088       std::cout << "Error: unknown argument '" << anArg << "'\n";
8089       return 1;
8090     }
8091   }
8092
8093   aView->AutoZFit();
8094   aView->Redraw();
8095
8096   return 0;
8097 }
8098
8099 //! Parse stereo output mode
8100 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8101                                          Graphic3d_StereoMode& theMode)
8102 {
8103   TCollection_AsciiString aFlag (theArg);
8104   aFlag.LowerCase();
8105   if (aFlag == "quadbuffer")
8106   {
8107     theMode = Graphic3d_StereoMode_QuadBuffer;
8108   }
8109   else if (aFlag == "anaglyph")
8110   {
8111     theMode = Graphic3d_StereoMode_Anaglyph;
8112   }
8113   else if (aFlag == "row"
8114         || aFlag == "rowinterlaced")
8115   {
8116     theMode = Graphic3d_StereoMode_RowInterlaced;
8117   }
8118   else if (aFlag == "col"
8119         || aFlag == "colinterlaced"
8120         || aFlag == "columninterlaced")
8121   {
8122     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8123   }
8124   else if (aFlag == "chess"
8125         || aFlag == "chessboard")
8126   {
8127     theMode = Graphic3d_StereoMode_ChessBoard;
8128   }
8129   else if (aFlag == "sbs"
8130         || aFlag == "sidebyside")
8131   {
8132     theMode = Graphic3d_StereoMode_SideBySide;
8133   }
8134   else if (aFlag == "ou"
8135         || aFlag == "overunder")
8136   {
8137     theMode = Graphic3d_StereoMode_OverUnder;
8138   }
8139   else if (aFlag == "pageflip"
8140         || aFlag == "softpageflip")
8141   {
8142     theMode = Graphic3d_StereoMode_SoftPageFlip;
8143   }
8144   else
8145   {
8146     return Standard_False;
8147   }
8148   return Standard_True;
8149 }
8150
8151 //! Parse anaglyph filter
8152 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8153                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8154 {
8155   TCollection_AsciiString aFlag (theArg);
8156   aFlag.LowerCase();
8157   if (aFlag == "redcyansimple")
8158   {
8159     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8160   }
8161   else if (aFlag == "redcyan"
8162         || aFlag == "redcyanoptimized")
8163   {
8164     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8165   }
8166   else if (aFlag == "yellowbluesimple")
8167   {
8168     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8169   }
8170   else if (aFlag == "yellowblue"
8171         || aFlag == "yellowblueoptimized")
8172   {
8173     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8174   }
8175   else if (aFlag == "greenmagenta"
8176         || aFlag == "greenmagentasimple")
8177   {
8178     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8179   }
8180   else
8181   {
8182     return Standard_False;
8183   }
8184   return Standard_True;
8185 }
8186
8187 //==============================================================================
8188 //function : VStereo
8189 //purpose  :
8190 //==============================================================================
8191
8192 static int VStereo (Draw_Interpretor& theDI,
8193                     Standard_Integer  theArgNb,
8194                     const char**      theArgVec)
8195 {
8196   Handle(V3d_View) aView = ViewerTest::CurrentView();
8197   if (theArgNb < 2)
8198   {
8199     if (aView.IsNull())
8200     {
8201       std::cout << "Error: no active viewer!\n";
8202       return 0;
8203     }
8204
8205     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8206     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8207     if (isActive)
8208     {
8209       TCollection_AsciiString aMode;
8210       switch (aView->RenderingParams().StereoMode)
8211       {
8212         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8213         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8214         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8215         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8216         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8217         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8218         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8219         case Graphic3d_StereoMode_Anaglyph  :
8220           aMode = "anaglyph";
8221           switch (aView->RenderingParams().AnaglyphFilter)
8222           {
8223             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8224             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8225             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8226             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8227             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8228             default: break;
8229           }
8230         default: break;
8231       }
8232       theDI << "Mode " << aMode << "\n";
8233     }
8234     return 0;
8235   }
8236
8237   Handle(Graphic3d_Camera) aCamera;
8238   Graphic3d_RenderingParams*   aParams   = NULL;
8239   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8240   if (!aView.IsNull())
8241   {
8242     aParams   = &aView->ChangeRenderingParams();
8243     aMode     = aParams->StereoMode;
8244     aCamera   = aView->Camera();
8245   }
8246
8247   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8248   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8249   {
8250     Standard_CString        anArg = theArgVec[anArgIter];
8251     TCollection_AsciiString aFlag (anArg);
8252     aFlag.LowerCase();
8253     if (anUpdateTool.parseRedrawMode (aFlag))
8254     {
8255       continue;
8256     }
8257     else if (aFlag == "0"
8258           || aFlag == "off")
8259     {
8260       if (++anArgIter < theArgNb)
8261       {
8262         std::cout << "Error: wrong number of arguments!\n";
8263         return 1;
8264       }
8265
8266       if (!aCamera.IsNull()
8267        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8268       {
8269         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8270       }
8271       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8272       return 0;
8273     }
8274     else if (aFlag == "1"
8275           || aFlag == "on")
8276     {
8277       if (++anArgIter < theArgNb)
8278       {
8279         std::cout << "Error: wrong number of arguments!\n";
8280         return 1;
8281       }
8282
8283       if (!aCamera.IsNull())
8284       {
8285         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8286       }
8287       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8288       return 0;
8289     }
8290     else if (aFlag == "-reverse"
8291           || aFlag == "-reversed"
8292           || aFlag == "-swap")
8293     {
8294       Standard_Boolean toEnable = Standard_True;
8295       if (++anArgIter < theArgNb
8296       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8297       {
8298         --anArgIter;
8299       }
8300       aParams->ToReverseStereo = toEnable;
8301     }
8302     else if (aFlag == "-noreverse"
8303           || aFlag == "-noswap")
8304     {
8305       Standard_Boolean toDisable = Standard_True;
8306       if (++anArgIter < theArgNb
8307       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
8308       {
8309         --anArgIter;
8310       }
8311       aParams->ToReverseStereo = !toDisable;
8312     }
8313     else if (aFlag == "-mode"
8314           || aFlag == "-stereomode")
8315     {
8316       if (++anArgIter >= theArgNb
8317       || !parseStereoMode (theArgVec[anArgIter], aMode))
8318       {
8319         std::cout << "Error: syntax error at '" << anArg << "'\n";
8320         return 1;
8321       }
8322
8323       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8324       {
8325         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8326       }
8327     }
8328     else if (aFlag == "-anaglyph"
8329           || aFlag == "-anaglyphfilter")
8330     {
8331       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8332       if (++anArgIter >= theArgNb
8333       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
8334       {
8335         std::cout << "Error: syntax error at '" << anArg << "'\n";
8336         return 1;
8337       }
8338
8339       aMode = Graphic3d_StereoMode_Anaglyph;
8340       aParams->AnaglyphFilter = aFilter;
8341     }
8342     else if (parseStereoMode (anArg, aMode)) // short syntax
8343     {
8344       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8345       {
8346         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8347       }
8348     }
8349     else
8350     {
8351       std::cout << "Error: syntax error at '" << anArg << "'\n";
8352       return 1;
8353     }
8354   }
8355
8356   if (!aView.IsNull())
8357   {
8358     aParams->StereoMode = aMode;
8359     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8360   }
8361   return 0;
8362 }
8363
8364 //===============================================================================================
8365 //function : VDefaults
8366 //purpose  :
8367 //===============================================================================================
8368 static int VDefaults (Draw_Interpretor& theDi,
8369                       Standard_Integer  theArgsNb,
8370                       const char**      theArgVec)
8371 {
8372   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
8373   if (aCtx.IsNull())
8374   {
8375     std::cerr << "No active viewer!\n";
8376     return 1;
8377   }
8378
8379   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
8380   if (theArgsNb < 2)
8381   {
8382     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
8383     {
8384       theDi << "DeflType:           relative\n"
8385             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
8386     }
8387     else
8388     {
8389       theDi << "DeflType:           absolute\n"
8390             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
8391     }
8392     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
8393     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
8394     return 0;
8395   }
8396
8397   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8398   {
8399     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8400     anArg.UpperCase();
8401     if (anArg == "-ABSDEFL"
8402      || anArg == "-ABSOLUTEDEFLECTION"
8403      || anArg == "-DEFL"
8404      || anArg == "-DEFLECTION")
8405     {
8406       if (++anArgIter >= theArgsNb)
8407       {
8408         std::cout << "Error: wrong syntax at " << anArg << "\n";
8409         return 1;
8410       }
8411       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
8412       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
8413     }
8414     else if (anArg == "-RELDEFL"
8415           || anArg == "-RELATIVEDEFLECTION"
8416           || anArg == "-DEVCOEFF"
8417           || anArg == "-DEVIATIONCOEFF"
8418           || anArg == "-DEVIATIONCOEFFICIENT")
8419     {
8420       if (++anArgIter >= theArgsNb)
8421       {
8422         std::cout << "Error: wrong syntax at " << anArg << "\n";
8423         return 1;
8424       }
8425       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
8426       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
8427     }
8428     else if (anArg == "-ANGDEFL"
8429           || anArg == "-ANGULARDEFL"
8430           || anArg == "-ANGULARDEFLECTION")
8431     {
8432       if (++anArgIter >= theArgsNb)
8433       {
8434         std::cout << "Error: wrong syntax at " << anArg << "\n";
8435         return 1;
8436       }
8437       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
8438       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
8439     }
8440     else if (anArg == "-AUTOTR"
8441           || anArg == "-AUTOTRIANG"
8442           || anArg == "-AUTOTRIANGULATION")
8443     {
8444       if (++anArgIter >= theArgsNb)
8445       {
8446         std::cout << "Error: wrong syntax at " << anArg << "\n";
8447         return 1;
8448       }
8449       TCollection_AsciiString aValue (theArgVec[anArgIter]);
8450       aValue.LowerCase();
8451       if (aValue == "on"
8452        || aValue == "1")
8453       {
8454         aDefParams->SetAutoTriangulation (Standard_True);
8455       }
8456       else if (aValue == "off"
8457             || aValue == "0")
8458       {
8459         aDefParams->SetAutoTriangulation (Standard_False);
8460       }
8461     }
8462     else
8463     {
8464       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
8465     }
8466   }
8467
8468   return 0;
8469 }
8470
8471 //! Auxiliary method
8472 inline void addLight (const Handle(V3d_Light)& theLightNew,
8473                       const Standard_Boolean   theIsGlobal)
8474 {
8475   if (theLightNew.IsNull())
8476   {
8477     return;
8478   }
8479
8480   if (theIsGlobal)
8481   {
8482     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
8483   }
8484   else
8485   {
8486     ViewerTest::CurrentView()->SetLightOn (theLightNew);
8487   }
8488 }
8489
8490 //! Auxiliary method
8491 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
8492 {
8493   TCollection_AsciiString anArgNextCase (theArgNext);
8494   anArgNextCase.UpperCase();
8495   if (anArgNextCase.Length() > 5
8496    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
8497   {
8498     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
8499   }
8500   else
8501   {
8502     return theArgNext.IntegerValue();
8503   }
8504 }
8505
8506 //===============================================================================================
8507 //function : VLight
8508 //purpose  :
8509 //===============================================================================================
8510 static int VLight (Draw_Interpretor& theDi,
8511                    Standard_Integer  theArgsNb,
8512                    const char**      theArgVec)
8513 {
8514   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8515   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8516   if (aView.IsNull()
8517    || aViewer.IsNull())
8518   {
8519     std::cerr << "No active viewer!\n";
8520     return 1;
8521   }
8522
8523   Standard_Real        anXYZ[3];
8524   Quantity_Coefficient anAtten[2];
8525   if (theArgsNb < 2)
8526   {
8527     // print lights info
8528     Standard_Integer aLightId = 0;
8529     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
8530     {
8531       Handle(V3d_Light) aLight = aLightIter.Value();
8532       const Quantity_Color aColor = aLight->Color();
8533       theDi << "Light" << aLightId << "\n";
8534       switch (aLight->Type())
8535       {
8536         case V3d_AMBIENT:
8537         {
8538           theDi << "  Type:       Ambient\n";
8539           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8540           break;
8541         }
8542         case V3d_DIRECTIONAL:
8543         {
8544           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
8545           theDi << "  Type:       Directional\n";
8546           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8547           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8548           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8549           if (!aLightDir.IsNull())
8550           {
8551             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8552             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8553             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8554             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8555           }
8556           break;
8557         }
8558         case V3d_POSITIONAL:
8559         {
8560           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
8561           theDi << "  Type:       Positional\n";
8562           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8563           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8564           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8565           if (!aLightPos.IsNull())
8566           {
8567             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8568             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8569             aLightPos->Attenuation (anAtten[0], anAtten[1]);
8570             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8571           }
8572           break;
8573         }
8574         case V3d_SPOT:
8575         {
8576           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
8577           theDi << "  Type:       Spot\n";
8578           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8579           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8580           if (!aLightSpot.IsNull())
8581           {
8582             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8583             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8584             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8585             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8586             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8587             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8588             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
8589             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
8590           }
8591           break;
8592         }
8593         default:
8594         {
8595           theDi << "  Type:       UNKNOWN\n";
8596           break;
8597         }
8598       }
8599       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
8600     }
8601   }
8602
8603   Handle(V3d_Light) aLightNew;
8604   Handle(V3d_Light) aLightOld;
8605   Standard_Boolean  isGlobal = Standard_True;
8606   Standard_Boolean  toCreate = Standard_False;
8607   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8608   {
8609     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
8610     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
8611     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
8612     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
8613     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
8614
8615     TCollection_AsciiString aName, aValue;
8616     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
8617     TCollection_AsciiString anArgCase (anArg);
8618     anArgCase.UpperCase();
8619     if (anArgCase.IsEqual ("NEW")
8620      || anArgCase.IsEqual ("ADD")
8621      || anArgCase.IsEqual ("CREATE"))
8622     {
8623       toCreate = Standard_True;
8624     }
8625     else if (anArgCase.IsEqual ("GLOB")
8626           || anArgCase.IsEqual ("GLOBAL"))
8627     {
8628       isGlobal = Standard_True;
8629     }
8630     else if (anArgCase.IsEqual ("LOC")
8631           || anArgCase.IsEqual ("LOCAL"))
8632     {
8633       isGlobal = Standard_False;
8634     }
8635     else if (anArgCase.IsEqual ("DEF")
8636           || anArgCase.IsEqual ("DEFAULTS"))
8637     {
8638       toCreate = Standard_False;
8639       aViewer->SetDefaultLights();
8640     }
8641     else if (anArgCase.IsEqual ("CLR")
8642           || anArgCase.IsEqual ("CLEAR"))
8643     {
8644       toCreate = Standard_False;
8645       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
8646       {
8647         Handle(V3d_Light) aLight = aLightIter.Value();
8648         aViewer->DelLight (aLight);
8649         aLightIter = aView->ActiveLightIterator();
8650       }
8651     }
8652     else if (anArgCase.IsEqual ("AMB")
8653           || anArgCase.IsEqual ("AMBIENT")
8654           || anArgCase.IsEqual ("AMBLIGHT"))
8655     {
8656       addLight (aLightNew, isGlobal);
8657       if (!toCreate)
8658       {
8659         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8660         return 1;
8661       }
8662       toCreate  = Standard_False;
8663       aLightNew = new V3d_AmbientLight (aViewer);
8664     }
8665     else if (anArgCase.IsEqual ("DIRECTIONAL")
8666           || anArgCase.IsEqual ("DIRLIGHT"))
8667     {
8668       addLight (aLightNew, isGlobal);
8669       if (!toCreate)
8670       {
8671         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8672         return 1;
8673       }
8674       toCreate  = Standard_False;
8675       aLightNew = new V3d_DirectionalLight (aViewer);
8676     }
8677     else if (anArgCase.IsEqual ("SPOT")
8678           || anArgCase.IsEqual ("SPOTLIGHT"))
8679     {
8680       addLight (aLightNew, isGlobal);
8681       if (!toCreate)
8682       {
8683         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8684         return 1;
8685       }
8686       toCreate  = Standard_False;
8687       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
8688     }
8689     else if (anArgCase.IsEqual ("POSLIGHT")
8690           || anArgCase.IsEqual ("POSITIONAL"))
8691     {
8692       addLight (aLightNew, isGlobal);
8693       if (!toCreate)
8694       {
8695         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8696         return 1;
8697       }
8698       toCreate  = Standard_False;
8699       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
8700     }
8701     else if (anArgCase.IsEqual ("CHANGE"))
8702     {
8703       addLight (aLightNew, isGlobal);
8704       aLightNew.Nullify();
8705       if (++anArgIt >= theArgsNb)
8706       {
8707         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8708         return 1;
8709       }
8710
8711       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
8712       Standard_Integer aLightIt = 0;
8713       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8714       {
8715         if (aLightIt == aLightId)
8716         {
8717           aLightOld = aLightIter.Value();
8718           break;
8719         }
8720       }
8721
8722       if (aLightOld.IsNull())
8723       {
8724         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
8725         return 1;
8726       }
8727     }
8728     else if (anArgCase.IsEqual ("DEL")
8729           || anArgCase.IsEqual ("DELETE"))
8730     {
8731       Handle(V3d_Light) aLightDel;
8732       if (++anArgIt >= theArgsNb)
8733       {
8734         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8735         return 1;
8736       }
8737
8738       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8739       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
8740       Standard_Integer aLightIt = 0;
8741       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8742       {
8743         aLightDel = aLightIter.Value();
8744         if (aLightIt == aLightDelId)
8745         {
8746           break;
8747         }
8748       }
8749       if (!aLightDel.IsNull())
8750       {
8751         aViewer->DelLight (aLightDel);
8752       }
8753     }
8754     else if (anArgCase.IsEqual ("COLOR")
8755           || anArgCase.IsEqual ("COLOUR"))
8756     {
8757       if (++anArgIt >= theArgsNb)
8758       {
8759         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8760         return 1;
8761       }
8762
8763       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8764       anArgNext.UpperCase();
8765       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
8766       if (!aLightCurr.IsNull())
8767       {
8768         aLightCurr->SetColor (aColor);
8769       }
8770     }
8771     else if (anArgCase.IsEqual ("POS")
8772           || anArgCase.IsEqual ("POSITION"))
8773     {
8774       if ((anArgIt + 3) >= theArgsNb)
8775       {
8776         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8777         return 1;
8778       }
8779
8780       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8781       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8782       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8783       if (!aLightDir.IsNull())
8784       {
8785         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8786       }
8787       else if (!aLightPos.IsNull())
8788       {
8789         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8790       }
8791       else if (!aLightSpot.IsNull())
8792       {
8793         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8794       }
8795       else
8796       {
8797         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8798         return 1;
8799       }
8800     }
8801     else if (anArgCase.IsEqual ("DIR")
8802           || anArgCase.IsEqual ("DIRECTION"))
8803     {
8804       if ((anArgIt + 3) >= theArgsNb)
8805       {
8806         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8807         return 1;
8808       }
8809
8810       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8811       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8812       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8813       if (!aLightDir.IsNull())
8814       {
8815         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8816       }
8817       else if (!aLightSpot.IsNull())
8818       {
8819         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8820       }
8821       else
8822       {
8823         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8824         return 1;
8825       }
8826     }
8827     else if (anArgCase.IsEqual ("SM")
8828           || anArgCase.IsEqual ("SMOOTHNESS"))
8829     {
8830       if (++anArgIt >= theArgsNb)
8831       {
8832         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8833         return 1;
8834       }
8835
8836       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
8837
8838       if (fabs (aSmoothness) < Precision::Confusion())
8839       {
8840         aLightCurr->SetIntensity (1.f);
8841       }
8842       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
8843       {
8844         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
8845       }
8846       else
8847       {
8848         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
8849         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
8850       }
8851
8852       if (!aLightPos.IsNull())
8853       {
8854         aLightPos->SetSmoothRadius (aSmoothness);
8855       }
8856       else if (!aLightDir.IsNull())
8857       {
8858         aLightDir->SetSmoothAngle (aSmoothness);
8859       }
8860     }
8861     else if (anArgCase.IsEqual ("INT")
8862           || anArgCase.IsEqual ("INTENSITY"))
8863     {
8864       if (++anArgIt >= theArgsNb)
8865       {
8866         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8867         return 1;
8868       }
8869
8870       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
8871
8872       if (!aLightCurr.IsNull())
8873       {
8874         aLightCurr->SetIntensity (aIntensity);
8875       }
8876     }
8877     else if (anArgCase.IsEqual ("ANG")
8878           || anArgCase.IsEqual ("ANGLE"))
8879     {
8880       if (++anArgIt >= theArgsNb)
8881       {
8882         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8883         return 1;
8884       }
8885
8886       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
8887
8888       if (!aLightSpot.IsNull())
8889       {
8890         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
8891       }
8892     }
8893     else if (anArgCase.IsEqual ("CONSTATTEN")
8894           || anArgCase.IsEqual ("CONSTATTENUATION"))
8895     {
8896       if (++anArgIt >= theArgsNb)
8897       {
8898         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8899         return 1;
8900       }
8901
8902       if (!aLightPos.IsNull())
8903       {
8904         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8905         anAtten[0] = Atof (theArgVec[anArgIt]);
8906         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8907       }
8908       else if (!aLightSpot.IsNull())
8909       {
8910         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8911         anAtten[0] = Atof (theArgVec[anArgIt]);
8912         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8913       }
8914       else
8915       {
8916         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8917         return 1;
8918       }
8919     }
8920     else if (anArgCase.IsEqual ("LINATTEN")
8921           || anArgCase.IsEqual ("LINEARATTEN")
8922           || anArgCase.IsEqual ("LINEARATTENUATION"))
8923     {
8924       if (++anArgIt >= theArgsNb)
8925       {
8926         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8927         return 1;
8928       }
8929
8930       if (!aLightPos.IsNull())
8931       {
8932         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8933         anAtten[1] = Atof (theArgVec[anArgIt]);
8934         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8935       }
8936       else if (!aLightSpot.IsNull())
8937       {
8938         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8939         anAtten[1] = Atof (theArgVec[anArgIt]);
8940         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8941       }
8942       else
8943       {
8944         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8945         return 1;
8946       }
8947     }
8948     else if (anArgCase.IsEqual ("EXP")
8949           || anArgCase.IsEqual ("EXPONENT")
8950           || anArgCase.IsEqual ("SPOTEXP")
8951           || anArgCase.IsEqual ("SPOTEXPONENT"))
8952     {
8953       if (++anArgIt >= theArgsNb)
8954       {
8955         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8956         return 1;
8957       }
8958
8959       if (!aLightSpot.IsNull())
8960       {
8961         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
8962       }
8963       else
8964       {
8965         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8966         return 1;
8967       }
8968     }
8969     else if (anArgCase.IsEqual ("HEAD")
8970           || anArgCase.IsEqual ("HEADLIGHT"))
8971     {
8972       if (++anArgIt >= theArgsNb)
8973       {
8974         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8975         return 1;
8976       }
8977
8978       if (aLightAmb.IsNull()
8979        && !aLightCurr.IsNull())
8980       {
8981         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
8982       }
8983       else
8984       {
8985         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8986         return 1;
8987       }
8988     }
8989     else
8990     {
8991       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
8992     }
8993   }
8994
8995   addLight (aLightNew, isGlobal);
8996   aViewer->UpdateLights();
8997
8998   return 0;
8999 }
9000
9001 //=======================================================================
9002 //function : VRenderParams
9003 //purpose  : Enables/disables rendering features
9004 //=======================================================================
9005
9006 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9007                                        Standard_Integer  theArgNb,
9008                                        const char**      theArgVec)
9009 {
9010   Handle(V3d_View) aView = ViewerTest::CurrentView();
9011   if (aView.IsNull())
9012   {
9013     std::cerr << "Error: no active viewer!\n";
9014     return 1;
9015   }
9016
9017   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9018   TCollection_AsciiString aCmdName (theArgVec[0]);
9019   aCmdName.LowerCase();
9020   if (aCmdName == "vraytrace")
9021   {
9022     if (theArgNb == 1)
9023     {
9024       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9025       return 0;
9026     }
9027     else if (theArgNb == 2)
9028     {
9029       TCollection_AsciiString aValue (theArgVec[1]);
9030       aValue.LowerCase();
9031       if (aValue == "on"
9032        || aValue == "1")
9033       {
9034         aParams.Method = Graphic3d_RM_RAYTRACING;
9035         aView->Redraw();
9036         return 0;
9037       }
9038       else if (aValue == "off"
9039             || aValue == "0")
9040       {
9041         aParams.Method = Graphic3d_RM_RASTERIZATION;
9042         aView->Redraw();
9043         return 0;
9044       }
9045       else
9046       {
9047         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9048         return 1;
9049       }
9050     }
9051     else
9052     {
9053       std::cout << "Error: wrong number of arguments\n";
9054       return 1;
9055     }
9056   }
9057
9058   if (theArgNb < 2)
9059   {
9060     theDI << "renderMode:  ";
9061     switch (aParams.Method)
9062     {
9063       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9064       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9065     }
9066     theDI << "\n";
9067     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9068     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9069     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9070     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9071     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9072     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9073     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9074     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9075     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9076     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9077     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9078     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
9079     theDI << "shadingModel: ";
9080     switch (aView->ShadingModel())
9081     {
9082       case V3d_COLOR:   theDI << "color";   break;
9083       case V3d_FLAT:    theDI << "flat";    break;
9084       case V3d_GOURAUD: theDI << "gouraud"; break;
9085       case V3d_PHONG:   theDI << "phong";   break;
9086     }
9087     theDI << "\n";
9088     return 0;
9089   }
9090
9091   Standard_Boolean toPrint = Standard_False;
9092   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9093   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9094   {
9095     Standard_CString        anArg (theArgVec[anArgIter]);
9096     TCollection_AsciiString aFlag (anArg);
9097     aFlag.LowerCase();
9098     if (anUpdateTool.parseRedrawMode (aFlag))
9099     {
9100       continue;
9101     }
9102     else if (aFlag == "-echo"
9103           || aFlag == "-print")
9104     {
9105       toPrint = Standard_True;
9106       anUpdateTool.Invalidate();
9107     }
9108     else if (aFlag == "-mode"
9109           || aFlag == "-rendermode"
9110           || aFlag == "-render_mode")
9111     {
9112       if (toPrint)
9113       {
9114         switch (aParams.Method)
9115         {
9116           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9117           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9118         }
9119         continue;
9120       }
9121       else
9122       {
9123         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9124         return 1;
9125       }
9126     }
9127     else if (aFlag == "-ray"
9128           || aFlag == "-raytrace")
9129     {
9130       if (toPrint)
9131       {
9132         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9133         continue;
9134       }
9135
9136       aParams.Method = Graphic3d_RM_RAYTRACING;
9137     }
9138     else if (aFlag == "-rast"
9139           || aFlag == "-raster"
9140           || aFlag == "-rasterization")
9141     {
9142       if (toPrint)
9143       {
9144         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9145         continue;
9146       }
9147
9148       aParams.Method = Graphic3d_RM_RASTERIZATION;
9149     }
9150     else if (aFlag == "-msaa")
9151     {
9152       if (toPrint)
9153       {
9154         theDI << aParams.NbMsaaSamples << " ";
9155         continue;
9156       }
9157       else if (++anArgIter >= theArgNb)
9158       {
9159         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9160         return 1;
9161       }
9162
9163       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9164       if (aNbSamples < 0)
9165       {
9166         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9167         return 1;
9168       }
9169       else
9170       {
9171         aParams.NbMsaaSamples = aNbSamples;
9172       }
9173     }
9174     else if (aFlag == "-raydepth"
9175           || aFlag == "-ray_depth")
9176     {
9177       if (toPrint)
9178       {
9179         theDI << aParams.RaytracingDepth << " ";
9180         continue;
9181       }
9182       else if (++anArgIter >= theArgNb)
9183       {
9184         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9185         return 1;
9186       }
9187
9188       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9189
9190       // We allow RaytracingDepth be more than 10 in case of GI enabled
9191       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9192       {
9193         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9194         return 1;
9195       }
9196       else
9197       {
9198         aParams.RaytracingDepth = aDepth;
9199       }
9200     }
9201     else if (aFlag == "-shad"
9202           || aFlag == "-shadows")
9203     {
9204       if (toPrint)
9205       {
9206         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
9207         continue;
9208       }
9209
9210       Standard_Boolean toEnable = Standard_True;
9211       if (++anArgIter < theArgNb
9212       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9213       {
9214         --anArgIter;
9215       }
9216       aParams.IsShadowEnabled = toEnable;
9217     }
9218     else if (aFlag == "-refl"
9219           || aFlag == "-reflections")
9220     {
9221       if (toPrint)
9222       {
9223         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
9224         continue;
9225       }
9226
9227       Standard_Boolean toEnable = Standard_True;
9228       if (++anArgIter < theArgNb
9229       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9230       {
9231         --anArgIter;
9232       }
9233       aParams.IsReflectionEnabled = toEnable;
9234     }
9235     else if (aFlag == "-fsaa")
9236     {
9237       if (toPrint)
9238       {
9239         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
9240         continue;
9241       }
9242
9243       Standard_Boolean toEnable = Standard_True;
9244       if (++anArgIter < theArgNb
9245       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9246       {
9247         --anArgIter;
9248       }
9249       aParams.IsAntialiasingEnabled = toEnable;
9250     }
9251     else if (aFlag == "-gleam")
9252     {
9253       if (toPrint)
9254       {
9255         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
9256         continue;
9257       }
9258
9259       Standard_Boolean toEnable = Standard_True;
9260       if (++anArgIter < theArgNb
9261       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9262       {
9263         --anArgIter;
9264       }
9265       aParams.IsTransparentShadowEnabled = toEnable;
9266     }
9267     else if (aFlag == "-gi")
9268     {
9269       if (toPrint)
9270       {
9271         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
9272         continue;
9273       }
9274
9275       Standard_Boolean toEnable = Standard_True;
9276       if (++anArgIter < theArgNb
9277       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9278       {
9279         --anArgIter;
9280       }
9281       aParams.IsGlobalIlluminationEnabled = toEnable;
9282       if (!toEnable)
9283       {
9284         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
9285       }
9286     }
9287     else if (aFlag == "-blockedrng"
9288           || aFlag == "-brng")
9289     {
9290       if (toPrint)
9291       {
9292         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
9293         continue;
9294       }
9295
9296       Standard_Boolean toEnable = Standard_True;
9297       if (++anArgIter < theArgNb
9298         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9299       {
9300         --anArgIter;
9301       }
9302       aParams.CoherentPathTracingMode = toEnable;
9303     }
9304     else if (aFlag == "-maxrad")
9305     {
9306       if (toPrint)
9307       {
9308         theDI << aParams.RadianceClampingValue << " ";
9309         continue;
9310       }
9311       else if (++anArgIter >= theArgNb)
9312       {
9313         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9314         return 1;
9315       }
9316
9317       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
9318       if (!aMaxRadStr.IsRealValue())
9319       {
9320         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9321         return 1;
9322       }
9323
9324       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
9325       if (aMaxRadiance <= 0.0)
9326       {
9327         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
9328         return 1;
9329       }
9330       else
9331       {
9332         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
9333       }
9334     }
9335     else if (aFlag == "-iss")
9336     {
9337       if (toPrint)
9338       {
9339         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
9340         continue;
9341       }
9342
9343       Standard_Boolean toEnable = Standard_True;
9344       if (++anArgIter < theArgNb
9345         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9346       {
9347         --anArgIter;
9348       }
9349       aParams.AdaptiveScreenSampling = toEnable;
9350     }
9351     else if (aFlag == "-issd")
9352     {
9353       if (toPrint)
9354       {
9355         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
9356         continue;
9357       }
9358
9359       Standard_Boolean toEnable = Standard_True;
9360       if (++anArgIter < theArgNb
9361         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9362       {
9363         --anArgIter;
9364       }
9365       aParams.ShowSamplingTiles = toEnable;
9366     }
9367     else if (aFlag == "-env")
9368     {
9369       if (toPrint)
9370       {
9371         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
9372         continue;
9373       }
9374
9375       Standard_Boolean toEnable = Standard_True;
9376       if (++anArgIter < theArgNb
9377         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9378       {
9379         --anArgIter;
9380       }
9381       aParams.UseEnvironmentMapBackground = toEnable;
9382     }
9383     else if (aFlag == "-twoside")
9384     {
9385       if (toPrint)
9386       {
9387         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
9388         continue;
9389       }
9390
9391       Standard_Boolean toEnable = Standard_True;
9392       if (++anArgIter < theArgNb
9393         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9394       {
9395         --anArgIter;
9396       }
9397       aParams.TwoSidedBsdfModels = toEnable;
9398     }
9399     else if (aFlag == "-shademodel"
9400           || aFlag == "-shadingmodel"
9401           || aFlag == "-shading")
9402     {
9403       if (toPrint)
9404       {
9405         switch (aView->ShadingModel())
9406         {
9407           case V3d_COLOR:   theDI << "color ";   break;
9408           case V3d_FLAT:    theDI << "flat ";    break;
9409           case V3d_GOURAUD: theDI << "gouraud "; break;
9410           case V3d_PHONG:   theDI << "phong ";   break;
9411         }
9412         continue;
9413       }
9414
9415       if (++anArgIter >= theArgNb)
9416       {
9417         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9418       }
9419
9420       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9421       aMode.LowerCase();
9422       if (aMode == "color"
9423        || aMode == "none")
9424       {
9425         aView->SetShadingModel (V3d_COLOR);
9426       }
9427       else if (aMode == "flat"
9428             || aMode == "facet")
9429       {
9430         aView->SetShadingModel (V3d_FLAT);
9431       }
9432       else if (aMode == "gouraud"
9433             || aMode == "vertex"
9434             || aMode == "vert")
9435       {
9436         aView->SetShadingModel (V3d_GOURAUD);
9437       }
9438       else if (aMode == "phong"
9439             || aMode == "fragment"
9440             || aMode == "frag"
9441             || aMode == "pixel")
9442       {
9443         aView->SetShadingModel (V3d_PHONG);
9444       }
9445       else
9446       {
9447         std::cout << "Error: unknown shading model '" << aMode << "'\n";
9448         return 1;
9449       }
9450     }
9451     else if (aFlag == "-resolution")
9452     {
9453       if (++anArgIter >= theArgNb)
9454       {
9455         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9456         return 1;
9457       }
9458
9459       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
9460       if (aResolution.IsIntegerValue())
9461       {
9462         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
9463       }
9464       else
9465       {
9466         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9467         return 1;
9468       }
9469     }
9470     else if (aFlag == "-rebuildglsl"
9471           || aFlag == "-rebuild")
9472     {
9473       if (toPrint)
9474       {
9475         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
9476         continue;
9477       }
9478
9479       Standard_Boolean toEnable = Standard_True;
9480       if (++anArgIter < theArgNb
9481           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9482       {
9483         --anArgIter;
9484       }
9485       aParams.RebuildRayTracingShaders = toEnable;
9486     }
9487     else
9488     {
9489       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
9490       return 1;
9491     }
9492   }
9493
9494   return 0;
9495 }
9496
9497 //=======================================================================
9498 //function : VProgressiveMode
9499 //purpose  :
9500 //=======================================================================
9501 #if defined(_WIN32)
9502 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
9503                                           Standard_Integer  /*theNbArgs*/,
9504                                           const char**      /*theArgs*/)
9505 {
9506   Handle(V3d_View) aView = ViewerTest::CurrentView();
9507   if (aView.IsNull())
9508   {
9509     std::cerr << "Error: no active viewer!\n";
9510     return 1;
9511   }
9512
9513   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
9514
9515   for (;;)
9516   {
9517     aView->Redraw();
9518
9519     Standard_Boolean toExit = Standard_False;
9520
9521     MSG aMsg;
9522     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
9523     {
9524       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
9525       {
9526         toExit = Standard_True;
9527       }
9528
9529       TranslateMessage (&aMsg);
9530       DispatchMessageW (&aMsg);
9531     }
9532
9533     if (toExit)
9534     {
9535       break;
9536     }
9537   }
9538
9539   return 0;
9540 }
9541 #endif
9542
9543 //=======================================================================
9544 //function : VFrustumCulling
9545 //purpose  : enables/disables view volume's culling.
9546 //=======================================================================
9547 static int VFrustumCulling (Draw_Interpretor& theDI,
9548                             Standard_Integer  theArgNb,
9549                             const char**      theArgVec)
9550 {
9551   Handle(V3d_View) aView = ViewerTest::CurrentView();
9552   if (aView.IsNull())
9553   {
9554     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
9555     return 1;
9556   }
9557
9558   if (theArgNb < 2)
9559   {
9560     theDI << (aView->IsCullingEnabled() ? "on" : "off");
9561     return 0;
9562   }
9563   else if (theArgNb != 2)
9564   {
9565     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
9566     return 1;
9567   }
9568
9569   TCollection_AsciiString aModeStr (theArgVec[1]);
9570   aModeStr.LowerCase();
9571   Standard_Boolean toEnable = 0;
9572   if (aModeStr == "on")
9573   {
9574     toEnable = 1;
9575   }
9576   else if (aModeStr == "off")
9577   {
9578     toEnable = 0;
9579   }
9580   else
9581   {
9582     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9583   }
9584
9585   aView->SetFrustumCulling (toEnable);
9586   aView->Redraw();
9587   return 0;
9588 }
9589
9590 //=======================================================================
9591 //function : VHighlightSelected
9592 //purpose  : 
9593 //=======================================================================
9594 static int VHighlightSelected (Draw_Interpretor& theDI,
9595                                Standard_Integer  theArgNb,
9596                                const char**      theArgVec)
9597 {
9598   if (ViewerTest::GetAISContext().IsNull())
9599   {
9600     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
9601     return 1;
9602   }
9603
9604   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9605
9606   if (theArgNb < 2)
9607   {
9608     theDI << (aContext->ToHilightSelected() ? "on" : "off");
9609     return 0;
9610   }
9611
9612   if (theArgNb != 2)
9613   {
9614     std::cout  << theArgVec[0] << " error : wrong number of parameters."
9615           << "Type 'help" << theArgVec[0] << "' for more information.";
9616     return 1;
9617   }
9618
9619   // Parse parameter
9620   TCollection_AsciiString aMode (theArgVec[1]);
9621   aMode.LowerCase();
9622   Standard_Boolean toEnable = Standard_False;
9623   if (aMode.IsEqual ("on"))
9624   {
9625     toEnable = Standard_True;
9626   }
9627   else if (aMode.IsEqual ("off"))
9628   {
9629     toEnable = Standard_False;
9630   }
9631   else
9632   {
9633     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9634   }
9635
9636   if (toEnable != aContext->ToHilightSelected())
9637   {
9638     aContext->SetToHilightSelected (toEnable);
9639
9640     // Move cursor to null position and  back to process updating of detection
9641     // and highlighting of selected object immediatly.
9642     Standard_Integer aPixX = 0;
9643     Standard_Integer aPixY = 0;
9644     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
9645
9646     anEventManager->GetCurrentPosition (aPixX, aPixY);
9647     anEventManager->MoveTo (0, 0);
9648     anEventManager->MoveTo (aPixX, aPixY);
9649   }
9650
9651   return 0;
9652 }
9653
9654 //=======================================================================
9655 //function : VXRotate
9656 //purpose  :
9657 //=======================================================================
9658 static Standard_Integer VXRotate (Draw_Interpretor& di,
9659                                    Standard_Integer argc,
9660                                    const char ** argv)
9661 {
9662   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9663   if (aContext.IsNull())
9664   {
9665     di << argv[0] << "ERROR : use 'vinit' command before \n";
9666     return 1;
9667   }
9668   
9669   if (argc != 3)
9670   {
9671     di << "ERROR : Usage : " << argv[0] << " name angle\n";
9672     return 1;
9673   }
9674
9675   TCollection_AsciiString aName (argv[1]);
9676   Standard_Real anAngle = Draw::Atof (argv[2]);
9677
9678   // find object
9679   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
9680   Handle(AIS_InteractiveObject) anIObj;
9681   if (!aMap.IsBound2 (aName) )
9682   {
9683     di << "Use 'vdisplay' before\n";
9684     return 1;
9685   }
9686   else
9687   {
9688     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
9689
9690     gp_Trsf aTransform;
9691     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
9692     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
9693
9694     aContext->SetLocation (anIObj, aTransform);
9695     aContext->UpdateCurrentViewer();
9696   }
9697
9698   return 0;
9699 }
9700
9701 //===============================================================================================
9702 //class   : ViewerTest_AISManipulator
9703 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
9704 //===============================================================================================
9705 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9706
9707 class ViewerTest_AISManipulator : public AIS_Manipulator
9708 {
9709 public:
9710
9711   ViewerTest_AISManipulator() : AIS_Manipulator()
9712   {
9713     GetMapOfAISManipulators().Add (this);
9714   }
9715
9716   virtual ~ViewerTest_AISManipulator()
9717   {
9718     GetMapOfAISManipulators().Remove (this);
9719   }
9720
9721   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9722 };
9723
9724 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9725 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9726
9727 //===============================================================================================
9728 //function : VManipulator
9729 //purpose  :
9730 //===============================================================================================
9731 static int VManipulator (Draw_Interpretor& theDi,
9732                          Standard_Integer  theArgsNb,
9733                          const char**      theArgVec)
9734 {
9735   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9736   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9737   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
9738   if (aView.IsNull()
9739    || aViewer.IsNull())
9740   {
9741     std::cerr << "No active viewer!\n";
9742     return 1;
9743   }
9744
9745   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
9746   Standard_Integer anArgIter = 1;
9747   for (; anArgIter < theArgsNb; ++anArgIter)
9748   {
9749     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
9750   }
9751
9752   ViewerTest_CmdParser aCmd;
9753   aCmd.AddDescription ("Manages manipulator for interactive objects:");
9754   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
9755   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
9756   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
9757   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
9758   aCmd.AddOption ("detach",         "...       - detach manipulator");
9759
9760   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
9761   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
9762   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
9763
9764   aCmd.AddOption ("move",   "... x y z - move object");
9765   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
9766   aCmd.AddOption ("scale",  "... factor - scale object");
9767
9768   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
9769   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
9770   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
9771   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
9772   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
9773   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
9774   aCmd.AddOption ("size",              "... size - set size of manipulator");
9775   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
9776
9777   aCmd.Parse (theArgsNb, theArgVec);
9778
9779   if (aCmd.HasOption ("help"))
9780   {
9781     theDi.PrintHelp (theArgVec[0]);
9782     return 0;
9783   }
9784
9785   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
9786
9787   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
9788
9789   if (aName.IsEmpty())
9790   {
9791     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
9792     return 1;
9793   }
9794
9795   // ----------------------------------
9796   // detach existing manipulator object
9797   // ----------------------------------
9798
9799   if (aCmd.HasOption ("detach"))
9800   {
9801     if (!aMapAIS.IsBound2 (aName))
9802     {
9803       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
9804       return 1;
9805     }
9806
9807     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9808     if (aManipulator.IsNull())
9809     {
9810       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9811       return 1;
9812     }
9813
9814     aManipulator->Detach();
9815     aMapAIS.UnBind2 (aName);
9816     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
9817
9818     return 0;
9819   }
9820
9821   // -----------------------------------------------
9822   // find or create manipulator if it does not exist
9823   // -----------------------------------------------
9824
9825   Handle(AIS_Manipulator) aManipulator;
9826   if (!aMapAIS.IsBound2 (aName))
9827   {
9828     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
9829
9830     aManipulator = new ViewerTest_AISManipulator();
9831     aMapAIS.Bind (aManipulator, aName);
9832   }
9833   else
9834   {
9835     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9836     if (aManipulator.IsNull())
9837     {
9838       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9839       return 1;
9840     }
9841   }
9842
9843   // -----------------------------------------
9844   // change properties of manipulator instance
9845   // -----------------------------------------
9846
9847   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
9848   {
9849     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
9850   }
9851   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
9852   {
9853     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
9854   }
9855   if (aCmd.HasOption ("followRotation", 1, Standard_True))
9856   {
9857     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
9858   }
9859   if (aCmd.HasOption ("gap", 1, Standard_True))
9860   {
9861     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
9862   }
9863   if (aCmd.HasOption ("part", 3, Standard_True))
9864   {
9865     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
9866     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
9867     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
9868     if (aMode < 1 || aMode > 3)
9869     {
9870       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
9871       return 1;
9872     }
9873
9874     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
9875   }
9876   if (aCmd.HasOption ("pos", 3, Standard_True))
9877   {
9878     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
9879     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
9880     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
9881
9882     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
9883   }
9884   if (aCmd.HasOption ("size", 1, Standard_True))
9885   {
9886     aManipulator->SetSize (aCmd.ArgFloat ("size"));
9887   }
9888   if (aCmd.HasOption ("zoomable", 1, Standard_True))
9889   {
9890     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
9891
9892     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
9893     {
9894       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
9895       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
9896     }
9897   }
9898
9899   // ---------------------------------------------------
9900   // attach, detach or access manipulator from an object
9901   // ---------------------------------------------------
9902
9903   if (aCmd.HasOption ("attach"))
9904   {
9905     // Find an object and attach manipulator to it
9906     if (!aCmd.HasOption ("attach", 1, Standard_True))
9907     {
9908       return 1;
9909     }
9910
9911     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
9912     if (!aMapAIS.IsBound2 (anObjName))
9913     {
9914       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
9915       return 1;
9916     }
9917
9918     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
9919     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
9920     for (; anIt.More(); anIt.Next())
9921     {
9922       if (anIt.Value()->IsAttached()
9923        && anIt.Value()->Object() == anObject)
9924       {
9925         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
9926         return 1;
9927       }
9928     }
9929
9930     AIS_Manipulator::OptionsForAttach anOptions;
9931     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
9932     {
9933       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
9934     }
9935     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
9936     {
9937       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
9938     }
9939     if (aCmd.HasOption ("enableModes", 1, Standard_True))
9940     {
9941       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
9942     }
9943
9944     aManipulator->Attach (anObject, anOptions);
9945   }
9946
9947   // --------------------------------------
9948   // apply transformation using manipulator
9949   // --------------------------------------
9950
9951   if (aCmd.HasOption ("startTransform", 2, Standard_True))
9952   {
9953     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
9954   }
9955   if (aCmd.HasOption ("transform", 2, Standard_True))
9956   {
9957     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
9958   }
9959   if (aCmd.HasOption ("stopTransform"))
9960   {
9961     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
9962
9963     aManipulator->StopTransform (toApply);
9964   }
9965
9966   gp_Trsf aT;
9967   if (aCmd.HasOption ("move", 3, Standard_True))
9968   {
9969     aT.SetTranslationPart (aCmd.ArgVec ("move"));
9970   }
9971   if (aCmd.HasOption ("rotate", 7, Standard_True))
9972   {
9973     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
9974   }
9975   if (aCmd.HasOption ("scale", 1))
9976   {
9977     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
9978   }
9979
9980   if (aT.Form() != gp_Identity)
9981   {
9982     aManipulator->Transform (aT);
9983   }
9984
9985   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
9986
9987   return 0;
9988 }
9989
9990 //===============================================================================================
9991 //function : VSelectionProperties
9992 //purpose  :
9993 //===============================================================================================
9994 static int VSelectionProperties (Draw_Interpretor& theDi,
9995                                  Standard_Integer  theArgsNb,
9996                                  const char**      theArgVec)
9997 {
9998   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9999   if (aCtx.IsNull())
10000   {
10001     std::cerr << "No active viewer!\n";
10002     return 1;
10003   }
10004
10005   Standard_Boolean toPrint  = theArgsNb == 1;
10006   Standard_Boolean toRedraw = Standard_False;
10007   Standard_Integer anArgIter = 1;
10008   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
10009   if (anArgIter < theArgsNb)
10010   {
10011     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
10012     anArgFirst.LowerCase();
10013     ++anArgIter;
10014     if (anArgFirst == "dynhighlight"
10015      || anArgFirst == "dynhilight"
10016      || anArgFirst == "dynamichighlight"
10017      || anArgFirst == "dynamichilight")
10018     {
10019       aType = Prs3d_TypeOfHighlight_Dynamic;
10020     }
10021     else if (anArgFirst == "localdynhighlight"
10022           || anArgFirst == "localdynhilight"
10023           || anArgFirst == "localdynamichighlight"
10024           || anArgFirst == "localdynamichilight")
10025     {
10026       aType = Prs3d_TypeOfHighlight_LocalDynamic;
10027     }
10028     else if (anArgFirst == "selhighlight"
10029           || anArgFirst == "selhilight"
10030           || anArgFirst == "selectedhighlight"
10031           || anArgFirst == "selectedhilight")
10032     {
10033       aType = Prs3d_TypeOfHighlight_Selected;
10034     }
10035     else if (anArgFirst == "localselhighlight"
10036           || anArgFirst == "localselhilight"
10037           || anArgFirst == "localselectedhighlight"
10038           || anArgFirst == "localselectedhilight")
10039     {
10040       aType = Prs3d_TypeOfHighlight_LocalSelected;
10041     }
10042     else
10043     {
10044       --anArgIter;
10045     }
10046   }
10047   for (; anArgIter < theArgsNb; ++anArgIter)
10048   {
10049     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10050     anArg.LowerCase();
10051     if (anArg == "-help")
10052     {
10053       theDi.PrintHelp (theArgVec[0]);
10054       return 0;
10055     }
10056     else if (anArg == "-print")
10057     {
10058       toPrint = Standard_True;
10059     }
10060     else if (anArg == "-autoactivate")
10061     {
10062       Standard_Boolean toEnable = Standard_True;
10063       if (anArgIter + 1 < theArgsNb
10064        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
10065       {
10066         ++anArgIter;
10067       }
10068       aCtx->SetAutoActivateSelection (toEnable);
10069     }
10070     else if (anArg == "-pixtol"
10071           && anArgIter + 1 < theArgsNb)
10072     {
10073       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
10074     }
10075     else if ((anArg == "-mode"
10076            || anArg == "-dispmode")
10077           && anArgIter + 1 < theArgsNb)
10078     {
10079       if (aType == Prs3d_TypeOfHighlight_None)
10080       {
10081         std::cout << "Syntax error: type of highlighting is undefined\n";
10082         return 1;
10083       }
10084
10085       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
10086       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10087       aStyle->SetDisplayMode (aDispMode);
10088       toRedraw = Standard_True;
10089     }
10090     else if (anArg == "-layer"
10091           && anArgIter + 1 < theArgsNb)
10092     {
10093       if (aType == Prs3d_TypeOfHighlight_None)
10094       {
10095         std::cout << "Syntax error: type of highlighting is undefined\n";
10096         return 1;
10097       }
10098
10099       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
10100       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
10101       {
10102         TColStd_SequenceOfInteger aLayers;
10103         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
10104         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
10105         {
10106           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
10107           return 1;
10108         }
10109       }
10110
10111       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10112       aStyle->SetZLayer (aNewLayer);
10113       toRedraw = Standard_True;
10114     }
10115     else if (anArg == "-hicolor"
10116           || anArg == "-selcolor"
10117           || anArg == "-color")
10118     {
10119       if (anArg.StartsWith ("-hi"))
10120       {
10121         aType = Prs3d_TypeOfHighlight_Dynamic;
10122       }
10123       else if (anArg.StartsWith ("-sel"))
10124       {
10125         aType = Prs3d_TypeOfHighlight_Selected;
10126       }
10127       else if (aType == Prs3d_TypeOfHighlight_None)
10128       {
10129         std::cout << "Syntax error: type of highlighting is undefined\n";
10130         return 1;
10131       }
10132
10133       Quantity_Color aColor;
10134       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
10135                                                            theArgVec + anArgIter + 1,
10136                                                            aColor);
10137       if (aNbParsed == 0)
10138       {
10139         std::cout << "Syntax error: need more arguments.\n";
10140         return 1;
10141       }
10142       anArgIter += aNbParsed;
10143
10144       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10145       aStyle->SetColor (aColor);
10146       toRedraw = Standard_True;
10147     }
10148     else if ((anArg == "-transp"
10149            || anArg == "-transparency"
10150            || anArg == "-hitransp"
10151            || anArg == "-seltransp"
10152            || anArg == "-hitransplocal"
10153            || anArg == "-seltransplocal")
10154           && anArgIter + 1 < theArgsNb)
10155     {
10156       if (anArg.StartsWith ("-hi"))
10157       {
10158         aType = Prs3d_TypeOfHighlight_Dynamic;
10159       }
10160       else if (anArg.StartsWith ("-sel"))
10161       {
10162         aType = Prs3d_TypeOfHighlight_Selected;
10163       }
10164       else if (aType == Prs3d_TypeOfHighlight_None)
10165       {
10166         std::cout << "Syntax error: type of highlighting is undefined\n";
10167         return 1;
10168       }
10169
10170       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
10171       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10172       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
10173       toRedraw = Standard_True;
10174     }
10175     else if ((anArg == "-mat"
10176            || anArg == "-material")
10177           && anArgIter + 1 < theArgsNb)
10178     {
10179       if (aType == Prs3d_TypeOfHighlight_None)
10180       {
10181         std::cout << "Syntax error: type of highlighting is undefined\n";
10182         return 1;
10183       }
10184
10185       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10186       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
10187       if (aMatName != Graphic3d_NOM_DEFAULT)
10188       {
10189         ++anArgIter;
10190         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
10191         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
10192         Graphic3d_MaterialAspect aMat (aMatName);
10193         aMat.SetColor (aStyle->Color());
10194         aMat.SetTransparency (aStyle->Transparency());
10195         anAspect->SetFrontMaterial (aMat);
10196         anAspect->SetInteriorColor (aStyle->Color());
10197         aStyle->SetBasicFillAreaAspect (anAspect);
10198       }
10199       else
10200       {
10201         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
10202       }
10203       toRedraw = Standard_True;
10204     }
10205     else
10206     {
10207       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
10208     }
10209   }
10210
10211   if (toPrint)
10212   {
10213     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
10214     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
10215     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
10216     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
10217     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
10218     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
10219     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
10220     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
10221     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
10222     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
10223     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
10224     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
10225   }
10226
10227   if (aCtx->NbSelected() != 0 && toRedraw)
10228   {
10229     aCtx->HilightSelected (Standard_True);
10230   }
10231
10232   return 0;
10233 }
10234
10235 //===============================================================================================
10236 //function : VDumpSelectionImage
10237 //purpose  :
10238 //===============================================================================================
10239 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
10240                                 Standard_Integer  theArgsNb,
10241                                 const char**      theArgVec)
10242 {
10243   if (theArgsNb < 2)
10244   {
10245     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
10246     return 1;
10247   }
10248
10249   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
10250   if (aContext.IsNull())
10251   {
10252     std::cout << "Error: no active view.\n";
10253     return 1;
10254   }
10255
10256   TCollection_AsciiString aFile;
10257   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10258   Image_PixMap::ImgFormat anImgFormat = Image_PixMap::ImgBGR;
10259   Standard_Integer aPickedIndex = 1;
10260   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10261   {
10262     TCollection_AsciiString aParam (theArgVec[anArgIter]);
10263     aParam.LowerCase();
10264     if (aParam == "-type")
10265     {
10266       if (++anArgIter >= theArgsNb)
10267       {
10268         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
10269         return 1;
10270       }
10271
10272       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10273       aValue.LowerCase();
10274       if (aValue == "depth"
10275        || aValue == "normdepth"
10276        || aValue == "normalizeddepth")
10277       {
10278         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10279         anImgFormat = Image_PixMap::ImgGrayF;
10280       }
10281       if (aValue == "depthinverted"
10282        || aValue == "normdepthinverted"
10283        || aValue == "normalizeddepthinverted"
10284        || aValue == "inverted")
10285       {
10286         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
10287         anImgFormat = Image_PixMap::ImgGrayF;
10288       }
10289       else if (aValue == "unnormdepth"
10290             || aValue == "unnormalizeddepth")
10291       {
10292         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
10293         anImgFormat = Image_PixMap::ImgGrayF;
10294       }
10295       else if (aValue == "objectcolor"
10296             || aValue == "object"
10297             || aValue == "color")
10298       {
10299         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
10300       }
10301       else if (aValue == "entitycolor"
10302             || aValue == "entity")
10303       {
10304         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
10305       }
10306       else if (aValue == "ownercolor"
10307             || aValue == "owner")
10308       {
10309         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
10310       }
10311       else if (aValue == "selectionmodecolor"
10312             || aValue == "selectionmode"
10313             || aValue == "selmodecolor"
10314             || aValue == "selmode")
10315       {
10316         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
10317       }
10318     }
10319     else if (aParam == "-picked"
10320           || aParam == "-pickeddepth"
10321           || aParam == "-pickedindex")
10322     {
10323       if (++anArgIter >= theArgsNb)
10324       {
10325         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
10326         return 1;
10327       }
10328
10329       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
10330     }
10331     else if (aFile.IsEmpty())
10332     {
10333       aFile = theArgVec[anArgIter];
10334     }
10335     else
10336     {
10337       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
10338       return 1;
10339     }
10340   }
10341   if (aFile.IsEmpty())
10342   {
10343     std::cout << "Syntax error: image file name is missing.\n";
10344     return 1;
10345   }
10346
10347   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
10348   Standard_Integer aWidth = 0, aHeight = 0;
10349   aView->Window()->Size (aWidth, aHeight);
10350
10351   Image_AlienPixMap aPixMap;
10352   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
10353   {
10354     std::cout << "Error: can't allocate image.\n";
10355     return 1;
10356   }
10357   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
10358   {
10359     std::cout << "Error: can't generate selection image.\n";
10360     return 1;
10361   }
10362   if (!aPixMap.Save (aFile))
10363   {
10364     std::cout << "Error: can't save selection image.\n";
10365     return 0;
10366   }
10367   return 0;
10368 }
10369
10370 //=======================================================================
10371 //function : ViewerCommands
10372 //purpose  :
10373 //=======================================================================
10374
10375 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
10376 {
10377
10378   const char *group = "ZeViewer";
10379   theCommands.Add("vinit",
10380 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10381     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10382 #else
10383     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10384 #endif
10385     " - Creates new View window with specified name view_name.\n"
10386     "By default the new view is created in the viewer and in"
10387     " graphic driver shared with active view.\n"
10388     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
10389     "If driverName isn't specified the driver will be shared with active view.\n"
10390     "If viewerName isn't specified the viewer will be shared with active view.\n"
10391 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10392     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
10393     "is used in creation of graphic driver\n"
10394 #endif
10395     " - l, t: pixel position of left top corner of the window\n"
10396     " - w,h: width and heigth of window respectively.\n"
10397     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
10398     __FILE__,VInit,group);
10399   theCommands.Add("vclose" ,
10400     "[view_id [keep_context=0|1]]\n"
10401     "or vclose ALL - to remove all created views\n"
10402     " - removes view(viewer window) defined by its view_id.\n"
10403     " - keep_context: by default 0; if 1 and the last view is deleted"
10404     " the current context is not removed.",
10405     __FILE__,VClose,group);
10406   theCommands.Add("vactivate" ,
10407     "view_id"
10408     " - activates view(viewer window) defined by its view_id",
10409     __FILE__,VActivate,group);
10410   theCommands.Add("vviewlist",
10411     "vviewlist [format={tree, long}]"
10412     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
10413     " - format: format of result output, if tree the output is a tree view;"
10414     "otherwise it's a list of full view names. By default format = tree",
10415     __FILE__,VViewList,group);
10416   theCommands.Add("vhelp" ,
10417     "vhelp            : display help on the viewer commands",
10418     __FILE__,VHelp,group);
10419   theCommands.Add("vtop" ,
10420     "vtop or <T>      : Top view. Orientation +X+Y" ,
10421     __FILE__,VTop,group);
10422   theCommands.Add("vbottom" ,
10423     "vbottom          : Bottom view. Orientation +X-Y" ,
10424     __FILE__,VBottom,group);
10425   theCommands.Add("vleft" ,
10426     "vleft            : Left view. Orientation -Y+Z" ,
10427     __FILE__,VLeft,group);
10428   theCommands.Add("vright" ,
10429     "vright           : Right view. Orientation +Y+Z" ,
10430     __FILE__,VRight,group);
10431   theCommands.Add("vaxo" ,
10432     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
10433     __FILE__,VAxo,group);
10434   theCommands.Add("vfront" ,
10435     "vfront           : Front view. Orientation +X+Z" ,
10436     __FILE__,VFront,group);
10437   theCommands.Add("vback" ,
10438     "vback            : Back view. Orientation -X+Z" ,
10439     __FILE__,VBack,group);
10440   theCommands.Add("vpick" ,
10441     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
10442     VPick,group);
10443   theCommands.Add("vfit",
10444     "vfit or <F> [-selected] [-noupdate]"
10445     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
10446     __FILE__,VFit,group);
10447   theCommands.Add ("vfitarea",
10448     "vfitarea x1 y1 x2 y2"
10449     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
10450     "\n\t\t: Fit view to show area located between two points"
10451     "\n\t\t: given in world 2D or 3D corrdinates.",
10452     __FILE__, VFitArea, group);
10453   theCommands.Add ("vzfit", "vzfit [scale]\n"
10454     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
10455     "   \"scale\" - specifies factor to scale computed z range.\n",
10456     __FILE__, VZFit, group);
10457   theCommands.Add("vrepaint",
10458     "vrepaint        : vrepaint, force redraw",
10459     __FILE__,VRepaint,group);
10460   theCommands.Add("vclear",
10461     "vclear          : vclear"
10462     "\n\t\t: remove all the object from the viewer",
10463     __FILE__,VClear,group);
10464   theCommands.Add("vsetbg",
10465     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
10466     __FILE__,VSetBg,group);
10467   theCommands.Add("vsetbgmode",
10468     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
10469     __FILE__,VSetBgMode,group);
10470   theCommands.Add("vsetgradientbg",
10471     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
10472     __FILE__,VSetGradientBg,group);
10473   theCommands.Add("vsetgrbgmode",
10474     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
10475     __FILE__,VSetGradientBgMode,group);
10476   theCommands.Add("vsetcolorbg",
10477     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
10478     __FILE__,VSetColorBg,group);
10479   theCommands.Add("vsetdefaultbg",
10480     "vsetdefaultbg r g b\n"
10481     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
10482     "\n\t\t: Set default viewer background fill color (flat/gradient).",
10483     __FILE__,VSetDefaultBg,group);
10484   theCommands.Add("vscale",
10485     "vscale          : vscale X Y Z",
10486     __FILE__,VScale,group);
10487   theCommands.Add("vzbufftrihedron",
10488             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
10489     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
10490     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
10491     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
10492     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
10493     "\n\t\t: Displays a trihedron",
10494     __FILE__,VZBuffTrihedron,group);
10495   theCommands.Add("vrotate",
10496     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
10497     "\n                : Option -mouseStart starts rotation according to the mouse position"
10498     "\n                : Option -mouseMove continues rotation with angle computed"
10499     "\n                : from last and new mouse position."
10500     "\n                : vrotate AX AY AZ [X Y Z]",
10501     __FILE__,VRotate,group);
10502   theCommands.Add("vzoom",
10503     "vzoom           : vzoom coef",
10504     __FILE__,VZoom,group);
10505   theCommands.Add("vpan",
10506     "vpan            : vpan dx dy",
10507     __FILE__,VPan,group);
10508   theCommands.Add("vexport",
10509     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
10510     " : exports the view to a vector file of a given format"
10511     " : notice that EMF format requires patched gl2ps",
10512     __FILE__,VExport,group);
10513   theCommands.Add("vcolorscale",
10514     "vcolorscale name [-noupdate|-update] [-demo]"
10515     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
10516     "\n\t\t:       [-font HeightFont=20]"
10517     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
10518     "\n\t\t:       [-smoothTransition {on|off}=off]"
10519     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
10520     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
10521     "\n\t\t:       [-textpos {left|right|center|none}=right]"
10522     "\n\t\t:       [-labelAtBorder {on|off}=on]"
10523     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
10524     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
10525     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
10526     "\n\t\t:       [-xy Left=0 Bottom=0]"
10527     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
10528     "\n\t\t:  -colors   - set colors for all intervals"
10529     "\n\t\t:  -color    - set color for specific interval"
10530     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
10531     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
10532     "\n\t\t:              at border means the value inbetween neighbor intervals,"
10533     "\n\t\t:              at center means the center value within current interval"
10534     "\n\t\t:  -labels   - set labels for all intervals"
10535     "\n\t\t:  -freeLabels - same as -labels but does not require"
10536     "\n\t\t:              matching the number of intervals"
10537     "\n\t\t:  -label    - set label for specific interval"
10538     "\n\t\t:  -title    - set title"
10539     "\n\t\t:  -reversed - setup smooth color transition between intervals"
10540     "\n\t\t:  -smoothTransition - swap colorscale direction"
10541     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
10542     __FILE__, VColorScale, group);
10543   theCommands.Add("vgraduatedtrihedron",
10544     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
10545     "\t[-namefont Name] [-valuesfont Name]\n"
10546     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
10547     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
10548     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
10549     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
10550     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
10551     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
10552     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
10553     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
10554     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
10555     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
10556     " - Displays or erases graduated trihedron"
10557     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
10558     " - namefont - font of axes names. Default: Arial\n"
10559     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
10560     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
10561     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
10562     " - valuesfont - font of axes values. Default: Arial\n"
10563     " - xcolor, ycolor, zcolor - color of axis and values\n"
10564     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
10565     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
10566     __FILE__,VGraduatedTrihedron,group);
10567   theCommands.Add("vtile" ,
10568             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
10569     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
10570     "\n\t\t:  -totalSize the size of virtual bigger viewport"
10571     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
10572     "\n\t\t:  -lowerLeft tile offset as lower left corner"
10573     "\n\t\t:  -upperLeft tile offset as upper left corner",
10574     __FILE__, VTile, group);
10575   theCommands.Add("vzlayer",
10576               "vzlayer [layerId]"
10577       "\n\t\t:         [-add|-delete|-get|-settings]"
10578       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
10579       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
10580       "\n\t\t: ZLayer list management:"
10581       "\n\t\t:   -add      add new z layer to viewer and print its id"
10582       "\n\t\t:   -delete   delete z layer"
10583       "\n\t\t:   -get      print sequence of z layers"
10584       "\n\t\t:   -settings print status of z layer settings"
10585       "\n\t\t:   -disable  disables given setting"
10586       "\n\t\t:   -enable   enables  given setting",
10587     __FILE__,VZLayer,group);
10588   theCommands.Add("vlayerline",
10589     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
10590     __FILE__,VLayerLine,group);
10591   theCommands.Add ("vgrid",
10592     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
10593     " : Mode - rectangular or circular"
10594     " : Type - lines or points",
10595     __FILE__, VGrid, group);
10596   theCommands.Add ("vpriviledgedplane",
10597     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
10598     "\n\t\t:   Ox, Oy, Oz - plane origin"
10599     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
10600     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
10601     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
10602     __FILE__, VPriviledgedPlane, group);
10603   theCommands.Add ("vconvert",
10604     "vconvert v [Mode={window|view}]"
10605     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
10606     "\n\t\t: vconvert x y z [Mode={window|grid}]"
10607     "\n\t\t:   window - convert to window coordinates, pixels"
10608     "\n\t\t:   view   - convert to view projection plane"
10609     "\n\t\t:   grid   - convert to model coordinates, given on grid"
10610     "\n\t\t:   ray    - convert projection ray to model coordiantes"
10611     "\n\t\t: - vconvert v window : convert view to window;"
10612     "\n\t\t: - vconvert v view   : convert window to view;"
10613     "\n\t\t: - vconvert x y window : convert view to window;"
10614     "\n\t\t: - vconvert x y view : convert window to view;"
10615     "\n\t\t: - vconvert x y : convert window to model;"
10616     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
10617     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
10618     "\n\t\t: - vconvert x y z window : convert model to window;"
10619     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
10620     "\n\t\t: Converts the given coordinates to window/view/model space.",
10621     __FILE__, VConvert, group);
10622   theCommands.Add ("vfps",
10623     "vfps [framesNb=100] : estimate average frame rate for active view",
10624     __FILE__, VFps, group);
10625   theCommands.Add ("vgldebug",
10626             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
10627     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
10628     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
10629     "\n\t\t: Debug context can be requested only on Windows"
10630     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
10631     "\n\t\t:  -sync     - request synchronized debug GL context"
10632     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
10633     "\n\t\t:              which are suppressed by default,"
10634     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
10635     "\n\t\t:              which are suppressed by default",
10636     __FILE__, VGlDebug, group);
10637   theCommands.Add ("vvbo",
10638     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
10639     __FILE__, VVbo, group);
10640   theCommands.Add ("vstereo",
10641             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
10642     "\n\t\t:         [-anaglyph Filter]"
10643     "\n\t\t: Control stereo output mode. Available modes for -mode:"
10644     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
10645     "\n\t\t:                     requires driver support."
10646     "\n\t\t:                     Should be called BEFORE vinit!"
10647     "\n\t\t:  anaglyph         - Anaglyph glasses"
10648     "\n\t\t:  rowInterlaced    - row-interlaced display"
10649     "\n\t\t:  columnInterlaced - column-interlaced display"
10650     "\n\t\t:  chessBoard       - chess-board output"
10651     "\n\t\t:  sideBySide       - horizontal pair"
10652     "\n\t\t:  overUnder        - vertical   pair"
10653     "\n\t\t: Available Anaglyph filters for -anaglyph:"
10654     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
10655     "\n\t\t:  greenMagentaSimple",
10656     __FILE__, VStereo, group);
10657   theCommands.Add ("vcaps",
10658             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
10659     "\n\t\t:       [-compatibleProfile {0|1}]"
10660     "\n\t\t:       [-vsync {0|1}]"
10661     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
10662     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
10663     "\n\t\t: Modify particular graphic driver options:"
10664     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
10665     "\n\t\t:             built-in GLSL programs"
10666     "\n\t\t:            (requires compatible profile)"
10667     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
10668     "\n\t\t:             arrays to GPU memory)"
10669     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
10670     "\n\t\t:  vsync    - switch VSync on or off"
10671     "\n\t\t: Context creation options:"
10672     "\n\t\t:  softMode          - software OpenGL implementation"
10673     "\n\t\t:  compatibleProfile - backward-compatible profile"
10674     "\n\t\t:  quadbuffer        - QuadBuffer"
10675     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
10676     "\n\t\t: rendering paths producing the same visual result when"
10677     "\n\t\t: possible."
10678     "\n\t\t: Command is intended for testing old hardware compatibility.",
10679     __FILE__, VCaps, group);
10680   theCommands.Add ("vmemgpu",
10681     "vmemgpu [f]: print system-dependent GPU memory information if available;"
10682     " with f option returns free memory in bytes",
10683     __FILE__, VMemGpu, group);
10684   theCommands.Add ("vreadpixel",
10685     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
10686     " : Read pixel value for active view",
10687     __FILE__, VReadPixel, group);
10688   theCommands.Add("diffimage",
10689     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
10690     __FILE__, VDiffImage, group);
10691   theCommands.Add ("vselect",
10692     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
10693     "- emulates different types of selection:\n"
10694     "- 1) single click selection\n"
10695     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
10696     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
10697     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
10698     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
10699     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
10700     " (partial inclusion - overlap - is not allowed by default)\n"
10701     "- 5) any of these selections with shift button pressed",
10702     __FILE__, VSelect, group);
10703   theCommands.Add ("vmoveto",
10704     "vmoveto x y"
10705     "- emulates cursor movement to pixel postion (x,y)",
10706     __FILE__, VMoveTo, group);
10707   theCommands.Add ("vviewparams",
10708               "vviewparams [-args] [-scale [s]]"
10709       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
10710       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
10711       "\n\t\t: Manage current view parameters or prints all"
10712       "\n\t\t: current values when called without argument."
10713       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
10714       "\n\t\t:   -eye  [x y z] prints or sets eye location"
10715       "\n\t\t:   -at   [x y z] prints or sets center of look"
10716       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
10717       "\n\t\t:   -proj [x y z] prints or sets direction of look"
10718       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
10719       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
10720       "\n\t\t:                 or changes the size of its maximum dimension"
10721       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
10722     __FILE__, VViewParams, group);
10723
10724   theCommands.Add("vanimation", "Alias for vanim",
10725     __FILE__, VAnimation, group);
10726
10727   theCommands.Add("vanim",
10728             "List existing animations:"
10729     "\n\t\t:  vanim"
10730     "\n\t\t: Animation playback:"
10731     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
10732     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
10733     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
10734     "\n\t\t:   -freeLook skip camera animations"
10735     "\n\t\t:   -lockLoop disable any interactions"
10736     "\n\t\t:"
10737     "\n\t\t: Animation definition:"
10738     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
10739     "\n\t\t:        [start TimeSec] [duration TimeSec]"
10740     "\n\t\t:"
10741     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
10742     "\n\t\t: specifies nested animations."
10743     "\n\t\t: There is no syntax to explicitly add new animation,"
10744     "\n\t\t: and all non-existing animations within the name will be"
10745     "\n\t\t: implicitly created on first use (including parents)."
10746     "\n\t\t:"
10747     "\n\t\t: Each animation might define the SINGLE action (see below),"
10748     "\n\t\t: like camera transition, object transformation or custom callback."
10749     "\n\t\t: Child animations can be used for defining concurrent actions."
10750     "\n\t\t:"
10751     "\n\t\t: Camera animation:"
10752     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
10753     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
10754     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
10755     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
10756     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
10757     "\n\t\t:   -atX    camera Center positions pair"
10758     "\n\t\t:   -upX    camera Up directions pair"
10759     "\n\t\t:   -scaleX camera Scale factors pair"
10760     "\n\t\t: Object animation:"
10761     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
10762     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
10763     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
10764     "\n\t\t:   -locX   object Location points pair (translation)"
10765     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
10766     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
10767     "\n\t\t: Custom callback:"
10768     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
10769     "\n\t\t:   %Pts        overall animation presentation timestamp"
10770     "\n\t\t:   %LocalPts   local animation timestamp"
10771     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
10772     __FILE__, VAnimation, group);
10773
10774   theCommands.Add("vchangeselected",
10775     "vchangeselected shape"
10776     "- adds to shape to selection or remove one from it",
10777                 __FILE__, VChangeSelected, group);
10778   theCommands.Add ("vnbselected",
10779     "vnbselected"
10780     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
10781   theCommands.Add ("vcamera",
10782               "vcamera [-ortho] [-projtype]"
10783       "\n\t\t:         [-persp]"
10784       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
10785       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
10786       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
10787       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
10788       "\n\t\t: Manage camera parameters."
10789       "\n\t\t: Prints current value when option called without argument."
10790       "\n\t\t: Orthographic camera:"
10791       "\n\t\t:   -ortho      activate orthographic projection"
10792       "\n\t\t: Perspective camera:"
10793       "\n\t\t:   -persp      activate perspective  projection (mono)"
10794       "\n\t\t:   -fovy       field of view in y axis, in degrees"
10795       "\n\t\t:   -distance   distance of eye from camera center"
10796       "\n\t\t: Stereoscopic camera:"
10797       "\n\t\t:   -stereo     perspective  projection (stereo)"
10798       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
10799       "\n\t\t:   -rightEye   perspective  projection (right eye)"
10800       "\n\t\t:   -iod        intraocular distance value"
10801       "\n\t\t:   -iodType    distance type, absolute or relative"
10802       "\n\t\t:   -zfocus     stereographic focus value"
10803       "\n\t\t:   -zfocusType focus type, absolute or relative",
10804     __FILE__, VCamera, group);
10805   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
10806     "- vautozfit [on={1|0}] [scale]\n"
10807     "    Prints or changes parameters of automatic z-fit mode:\n"
10808     "   \"on\" - turns automatic z-fit on or off\n"
10809     "   \"scale\" - specifies factor to scale computed z range.\n",
10810     __FILE__, VAutoZFit, group);
10811   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
10812     "   vzrange                - without parameters shows current values\n"
10813     "   vzrange [znear] [zfar] - applies provided values to view",
10814     __FILE__,VZRange, group);
10815   theCommands.Add ("vpurgedisplay",
10816     "vpurgedisplay"
10817     "- removes structures which don't belong to objects displayed in neutral point",
10818     __FILE__, VPurgeDisplay, group);
10819   theCommands.Add("vsetviewsize",
10820     "vsetviewsize size",
10821     __FILE__,VSetViewSize,group);
10822   theCommands.Add("vmoveview",
10823     "vmoveview Dx Dy Dz [Start = 1|0]",
10824     __FILE__,VMoveView,group);
10825   theCommands.Add("vtranslateview",
10826     "vtranslateview Dx Dy Dz [Start = 1|0)]",
10827     __FILE__,VTranslateView,group);
10828   theCommands.Add("vturnview",
10829     "vturnview Ax Ay Az [Start = 1|0]",
10830     __FILE__,VTurnView,group);
10831   theCommands.Add("vtextureenv",
10832     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
10833     "or user-defined file and optionally applying texture mapping parameters\n"
10834     "                  Usage:\n"
10835     "                  vtextureenv off - disables environment mapping\n"
10836     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
10837     "                              std_texture = (0..7)\n"
10838     "                              rep         = {clamp|repeat}\n"
10839     "                              mod         = {decal|modulate}\n"
10840     "                              flt         = {nearest|bilinear|trilinear}\n"
10841     "                              ss, st      - scale factors for s and t texture coordinates\n"
10842     "                              ts, tt      - translation for s and t texture coordinates\n"
10843     "                              rot         - texture rotation angle in degrees",
10844     __FILE__, VTextureEnv, group);
10845   theCommands.Add("vhlr" ,
10846     "is_enabled={on|off} [show_hidden={1|0}]"
10847     " - Hidden line removal algorithm:"
10848     " - is_enabled: if is on HLR algorithm is applied\n"
10849     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
10850     __FILE__,VHLR,group);
10851   theCommands.Add("vhlrtype" ,
10852     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
10853     " - Changes the type of HLR algorithm using for shapes."
10854     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
10855     "   if equals to polyalgo, polygonal HLR algorithm is applied."
10856     "If shapes are not given HLR algoithm of given type is applied"
10857     " to all shapes in the view\n",
10858     __FILE__,VHLRType,group);
10859   theCommands.Add("vclipplane",
10860               "vclipplane planeName [{0|1}]"
10861       "\n\t\t:   [-equation A B C D]"
10862       "\n\t\t:   [-set|-unset [objects|views]]"
10863       "\n\t\t:   [-maxPlanes]"
10864       "\n\t\t:   [-capping {0|1}]"
10865       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
10866       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
10867       "\n\t\t:       [-texRotate Angle]"
10868       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
10869       "\n\t\t:       [-useObjShader {0|1}]"
10870       "\n\t\t: Clipping planes management:"
10871       "\n\t\t:   -maxPlanes   print plane limit for view"
10872       "\n\t\t:   -delete      delete plane with given name"
10873       "\n\t\t:   {off|on|0|1} turn clipping on/off"
10874       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
10875       "\n\t\t:                applied to active View when list is omitted"
10876       "\n\t\t:   -equation A B C D change plane equation"
10877       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
10878       "\n\t\t: Capping options:"
10879       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
10880       "\n\t\t:   -color R G B          set capping color"
10881       "\n\t\t:   -texName Texture      set capping texture"
10882       "\n\t\t:   -texScale SX SY       set capping tex scale"
10883       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
10884       "\n\t\t:   -texRotate Angle      set capping tex rotation"
10885       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
10886       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
10887       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
10888       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
10889       __FILE__, VClipPlane, group);
10890   theCommands.Add("vdefaults",
10891                "vdefaults [-absDefl value]"
10892        "\n\t\t:           [-devCoeff value]"
10893        "\n\t\t:           [-angDefl value]"
10894        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
10895     , __FILE__, VDefaults, group);
10896   theCommands.Add("vlight",
10897     "tool to manage light sources, without arguments shows list of lights."
10898     "\n    Main commands: "
10899     "\n      'clear' to clear lights"
10900     "\n      '{def}aults' to load deafault lights"
10901     "\n      'add' (or 'new') <type> to add any light source"
10902     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
10903     "\n      'change' <lightId> to edit light source with specified lightId"
10904     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
10905     "\n        {pos}ition X Y Z"
10906     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
10907     "\n        color colorName"
10908     "\n        {head}light 0|1"
10909     "\n        {sm}oothness value"
10910     "\n        {int}ensity value"
10911     "\n        {constAtten}uation value"
10912     "\n        {linearAtten}uation value"
10913     "\n        angle angleDeg"
10914     "\n        {spotexp}onent value"
10915     "\n        local|global"
10916     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
10917     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
10918     __FILE__, VLight, group);
10919   theCommands.Add("vraytrace",
10920             "vraytrace [0|1]"
10921     "\n\t\t: Turns on/off ray-tracing renderer."
10922     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
10923     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
10924     __FILE__, VRenderParams, group);
10925   theCommands.Add("vrenderparams",
10926     "\n    Manages rendering parameters: "
10927     "\n      '-raster'               Disables GPU ray-tracing"
10928     "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
10929     "\n      '-rayTrace'             Enables  GPU ray-tracing"
10930     "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
10931     "\n      '-shadows      on|off'  Enables/disables shadows rendering"
10932     "\n      '-reflections  on|off'  Enables/disables specular reflections"
10933     "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
10934     "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
10935     "\n      '-gi           on|off'  Enables/disables global illumination effects"
10936     "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
10937     "\n      '-env          on|off'  Enables/disables environment map background"
10938     "\n      '-twoside      on|off'  Enables/disables two-sided BSDF models (PT mode)"
10939     "\n      '-iss          on|off'  Enables/disables adaptive screen sampling (PT mode)"
10940     "\n      '-issd         on|off'  Shows screen sampling distribution in ISS mode"
10941     "\n      '-maxrad       > 0.0'   Value used for clamping radiance estimation (PT mode)"
10942     "\n      '-rebuildGlsl  on|off'  Rebuild Ray-Tracing GLSL programs (for debugging)"
10943     "\n      '-shadingModel model'   Controls shading model from enumeration"
10944     "\n                              color, flat, gouraud, phong"
10945     "\n      '-resolution   value'   Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
10946     "\n    Unlike vcaps, these parameters dramatically change visual properties."
10947     "\n    Command is intended to control presentation quality depending on"
10948     "\n    hardware capabilities and performance.",
10949     __FILE__, VRenderParams, group);
10950   theCommands.Add("vfrustumculling",
10951     "vfrustumculling [toEnable]: enables/disables objects clipping",
10952     __FILE__,VFrustumCulling,group);
10953   theCommands.Add("vhighlightselected",
10954     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
10955     "Without arguments it shows if highlighting of selected objects is enabled now.",
10956     __FILE__,VHighlightSelected,group);
10957   theCommands.Add ("vplace",
10958             "vplace dx dy"
10959     "\n\t\t: Places the point (in pixels) at the center of the window",
10960     __FILE__, VPlace, group);
10961   theCommands.Add("vxrotate",
10962     "vxrotate",
10963     __FILE__,VXRotate,group);
10964
10965     theCommands.Add("vmanipulator",
10966       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
10967       "\n    tool to create and manage AIS manipulators."
10968       "\n    Options: "
10969       "\n      '-attach AISObject'                 attach manipulator to AISObject"
10970       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
10971       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
10972       "\n      '-enableModes    {0|1}'             enable modes when attaching"
10973       "\n      '-detach'                           detach manipulator"
10974       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
10975       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
10976       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
10977       "\n      '-move x y z'                     - move attached object"
10978       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
10979       "\n      '-scale factor'                   - scale attached object"
10980       "\n      '-autoActivate      {0|1}'        - set activation on detection"
10981       "\n      '-followTranslation {0|1}'        - set following translation transform"
10982       "\n      '-followRotation    {0|1}'        - set following rotation transform"
10983       "\n      '-gap value'                      - set gap between sub-parts"
10984       "\n      '-part axis mode    {0|1}'        - set visual part"
10985       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
10986       "\n      '-size value'                     - set size of manipulator"
10987       "\n      '-zoomable {0|1}'                 - set zoom persistence",
10988     __FILE__, VManipulator, group);
10989
10990   theCommands.Add("vselprops",
10991     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
10992     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
10993     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
10994     "\n    -pixTol    value        : sets up pixel tolerance"
10995     "\n    -dispMode  dispMode     : sets display mode for highlighting"
10996     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
10997     "\n    -color     {name|r g b} : sets highlight color"
10998     "\n    -transp    value        : sets transparency coefficient for highlight"
10999     "\n    -material  material     : sets highlight material"
11000     "\n    -print                  : prints current state of all mentioned parameters",
11001     __FILE__, VSelectionProperties, group);
11002
11003   theCommands.Add ("vseldump",
11004                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
11005                    "\n\t\t: Generate an image based on detection results:"
11006                    "\n\t\t:   depth       normalized depth values"
11007                    "\n\t\t:   unnormDepth unnormalized depth values"
11008                    "\n\t\t:   object      color of detected object"
11009                    "\n\t\t:   owner       color of detected owner"
11010                    "\n\t\t:   selMode     color of selection mode"
11011                    "\n\t\t:   entity      color of etected entity",
11012                    __FILE__, VDumpSelectionImage, group);
11013
11014 #if defined(_WIN32)
11015   theCommands.Add("vprogressive",
11016     "vprogressive",
11017     __FILE__, VProgressiveMode, group);
11018 #endif
11019 }