0028215: Visualization - define EMPTY type line for consistenct with Interior Style
[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(MMgt_TShared)& ViewerTest::WClass()
251 {
252   static Handle(MMgt_TShared) 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       ::LoadCursor (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   SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
455     theTitle);
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);
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);
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);
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();
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();
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 DefWindowProc( 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( DefWindowProc( hwnd, Msg, wParam, lParam ));
2179     }
2180     return 0L;
2181 }
2182
2183
2184
2185
2186 //==============================================================================
2187 //function : ViewerMainLoop
2188 //purpose  : Get a Event on the view and dispatch it
2189 //==============================================================================
2190
2191
2192 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2193 {
2194   Ppick = (argc > 0)? 1 : 0;
2195   Pargc = argc;
2196   Pargv = argv;
2197
2198   if ( Ppick ) {
2199     MSG msg;
2200     msg.wParam = 1;
2201
2202     cout << "Start picking" << endl;
2203
2204     while ( Ppick == 1 ) {
2205       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2206       if (GetMessage(&msg, NULL, 0, 0) ) {
2207         TranslateMessage(&msg);
2208         DispatchMessage(&msg);
2209       }
2210     }
2211
2212     cout << "Picking done" << endl;
2213   }
2214
2215   return Ppick;
2216 }
2217
2218 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2219
2220 int min( int a, int b )
2221 {
2222   if( a<b )
2223     return a;
2224   else
2225     return b;
2226 }
2227
2228 int max( int a, int b )
2229 {
2230   if( a>b )
2231     return a;
2232   else
2233     return b;
2234 }
2235
2236 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2237
2238 {
2239   static XEvent aReport;
2240   Standard_Boolean pick = argc > 0;
2241   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2242   XNextEvent (aDisplay, &aReport);
2243
2244   // Handle event for the chosen display connection
2245   switch (aReport.type) {
2246       case ClientMessage:
2247         {
2248           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2249           {
2250             // Close the window
2251             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2252           }
2253         }
2254         return 0;
2255      case FocusIn:
2256       {
2257          // Activate inactive view
2258          Window aWindow = GetWindowHandle(VT_GetWindow());
2259          if(aWindow != aReport.xfocus.window)
2260          {
2261            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2262          }
2263       }
2264       break;
2265       case Expose:
2266         {
2267           VT_ProcessExpose();
2268         }
2269         break;
2270       case ConfigureNotify:
2271         {
2272           VT_ProcessConfigure();
2273         }
2274         break;
2275       case KeyPress:
2276         {
2277
2278           KeySym ks_ret ;
2279           char buf_ret[11] ;
2280           int ret_len ;
2281           XComposeStatus status_in_out;
2282
2283           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2284             (char *) buf_ret , 10 ,
2285             &ks_ret , &status_in_out ) ;
2286
2287
2288           buf_ret[ret_len] = '\0' ;
2289
2290           if (ret_len)
2291           {
2292             VT_ProcessKeyPress (buf_ret);
2293           }
2294         }
2295         break;
2296       case ButtonPress:
2297         {
2298           X_ButtonPress = aReport.xbutton.x;
2299           Y_ButtonPress = aReport.xbutton.y;
2300
2301           if (aReport.xbutton.button == Button1)
2302           {
2303             if (aReport.xbutton.state & ControlMask)
2304             {
2305               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2306             }
2307             else
2308             {
2309               IsDragged = Standard_True;
2310               DragFirst = Standard_True;
2311             }
2312           }
2313           else if (aReport.xbutton.button == Button3)
2314           {
2315             // Start rotation
2316             VT_ProcessButton3Press();
2317           }
2318         }
2319         break;
2320       case ButtonRelease:
2321         {
2322           if( IsDragged )
2323           {
2324             if( !DragFirst )
2325             {
2326               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2327               {
2328                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2329                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2330               }
2331             }
2332
2333             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2334             if( aContext.IsNull() )
2335             {
2336               cout << "The context is null. Please use vinit before createmesh" << endl;
2337               return 0;
2338             }
2339
2340             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2341             if( aReport.xbutton.button==1 )
2342               if( DragFirst )
2343                 if( ShiftPressed )
2344                 {
2345                   aContext->ShiftSelect();
2346                 }
2347                 else
2348                 {
2349                   aContext->Select();
2350                 }
2351               else
2352                 if( ShiftPressed )
2353                 {
2354                   aContext->ShiftSelect( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2355                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2356                     ViewerTest::CurrentView());
2357                 }
2358                 else
2359                 {
2360                   aContext->Select( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2361                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2362                     ViewerTest::CurrentView() );
2363                 }
2364             else
2365               VT_ProcessButton3Release();
2366
2367             IsDragged = Standard_False;
2368           }
2369           else
2370             VT_ProcessButton3Release();
2371         }
2372         break;
2373       case MotionNotify:
2374         {
2375           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2376           {
2377             break;
2378           }
2379           if( IsDragged )
2380           {
2381             if( !DragFirst )
2382             {
2383               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2384               {
2385                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2386               }
2387             }
2388
2389             X_Motion = aReport.xmotion.x;
2390             Y_Motion = aReport.xmotion.y;
2391             DragFirst = Standard_False;
2392
2393             Window aWindow = GetWindowHandle(VT_GetWindow());
2394             Window aRoot;
2395             int anX, anY;
2396             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2397             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2398             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2399             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2400             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2401           }
2402           else
2403           {
2404             X_Motion = aReport.xmotion.x;
2405             Y_Motion = aReport.xmotion.y;
2406
2407             // remove all the ButtonMotionMaskr
2408             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2409
2410             if ( aReport.xmotion.state & ControlMask ) {
2411               if ( aReport.xmotion.state & Button1Mask ) {
2412                 ProcessControlButton1Motion();
2413               }
2414               else if ( aReport.xmotion.state & Button2Mask ) {
2415                 VT_ProcessControlButton2Motion();
2416               }
2417               else if ( aReport.xmotion.state & Button3Mask ) {
2418                 VT_ProcessControlButton3Motion();
2419               }
2420             }
2421             else
2422             {
2423               VT_ProcessMotion();
2424             }
2425           }
2426         }
2427         break;
2428 }
2429 return pick;
2430 }
2431
2432 //==============================================================================
2433 //function : VProcessEvents
2434 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2435 //       event in the Viewer window
2436 //==============================================================================
2437
2438 static void VProcessEvents(ClientData,int)
2439 {
2440   NCollection_Vector<int> anEventNumbers;
2441   // Get number of messages from every display
2442   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2443        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2444   {
2445     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2446   }
2447     // Handle events for every display
2448   int anEventIter = 0;
2449   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2450        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2451   {
2452     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2453          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2454     {
2455       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2456       int anEventResult = ViewerMainLoop( 0, NULL);
2457       // If window is closed or context was not found finish current event processing loop
2458       if (!anEventResult)
2459         return;
2460     }
2461   }
2462
2463   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2464
2465 }
2466 #endif
2467
2468 //==============================================================================
2469 //function : OSWindowSetup
2470 //purpose  : Setup for the X11 window to be able to cath the event
2471 //==============================================================================
2472
2473
2474 static void OSWindowSetup()
2475 {
2476 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2477   // X11
2478
2479   Window  window   = VT_GetWindow()->XWindow();
2480   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2481   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2482   XSynchronize(aDisplay, 1);
2483
2484   // X11 : For keyboard on SUN
2485   XWMHints wmhints;
2486   wmhints.flags = InputHint;
2487   wmhints.input = 1;
2488
2489   XSetWMHints( aDisplay, window, &wmhints);
2490
2491   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2492     ButtonPressMask | ButtonReleaseMask |
2493     StructureNotifyMask |
2494     PointerMotionMask |
2495     Button1MotionMask | Button2MotionMask |
2496     Button3MotionMask | FocusChangeMask
2497     );
2498   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2499   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2500
2501   XSynchronize(aDisplay, 0);
2502
2503 #else
2504   // _WIN32
2505 #endif
2506
2507 }
2508
2509 //==============================================================================
2510 //function : VFit
2511 //purpose  :
2512 //==============================================================================
2513
2514 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2515 {
2516   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2517   if (aView.IsNull())
2518   {
2519     std::cout << "Error: no active viewer!\n";
2520     return 1;
2521   }
2522
2523   Standard_Boolean toFit = Standard_True;
2524   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2525   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2526   {
2527     TCollection_AsciiString anArg (theArgv[anArgIter]);
2528     anArg.LowerCase();
2529     if (anUpdateTool.parseRedrawMode (anArg))
2530     {
2531       continue;
2532     }
2533     else if (anArg == "-selected")
2534     {
2535       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2536       toFit = Standard_False;
2537     }
2538     else
2539     {
2540       std::cout << "Syntax error at '" << anArg << "'\n";
2541     }
2542   }
2543
2544   if (toFit)
2545   {
2546     aView->FitAll (0.01, Standard_False);
2547   }
2548   return 0;
2549 }
2550
2551 //=======================================================================
2552 //function : VFitArea
2553 //purpose  : Fit view to show area located between two points
2554 //         : given in world 2D or 3D coordinates.
2555 //=======================================================================
2556 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2557 {
2558   Handle(V3d_View) aView = ViewerTest::CurrentView();
2559   if (aView.IsNull())
2560   {
2561     std::cerr << theArgVec[0] << "Error: No active view.\n";
2562     return 1;
2563   }
2564
2565   // Parse arguments.
2566   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2567   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2568
2569   if (theArgNb == 5)
2570   {
2571     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2572     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2573     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2574     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2575   }
2576   else if (theArgNb == 7)
2577   {
2578     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2579     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2580     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2581     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2582     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2583     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2584   }
2585   else
2586   {
2587     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2588     theDI.PrintHelp(theArgVec[0]);
2589     return 1;
2590   }
2591
2592   // Convert model coordinates to view space
2593   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2594   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2595   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2596
2597   // Determine fit area
2598   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2599   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2600
2601   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2602
2603   if (aDiagonal < Precision::Confusion())
2604   {
2605     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2606     return 1;
2607   }
2608
2609   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2610   return 0;
2611 }
2612
2613 //==============================================================================
2614 //function : VZFit
2615 //purpose  : ZFitall, no DRAW arguments
2616 //Draw arg : No args
2617 //==============================================================================
2618 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2619 {
2620   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2621
2622   if (aCurrentView.IsNull())
2623   {
2624     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2625     return 1;
2626   }
2627
2628   if (theArgsNb == 1)
2629   {
2630     aCurrentView->ZFitAll();
2631     aCurrentView->Redraw();
2632     return 0;
2633   }
2634
2635   Standard_Real aScale = 1.0;
2636
2637   if (theArgsNb >= 2)
2638   {
2639     aScale = Draw::Atoi (theArgVec[1]);
2640   }
2641
2642   aCurrentView->ZFitAll (aScale);
2643   aCurrentView->Redraw();
2644
2645   return 0;
2646 }
2647
2648 //==============================================================================
2649 //function : VRepaint
2650 //purpose  :
2651 //==============================================================================
2652 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2653 {
2654   Handle(V3d_View) V = ViewerTest::CurrentView();
2655   if ( !V.IsNull() ) V->Redraw(); return 0;
2656 }
2657
2658 //==============================================================================
2659 //function : VClear
2660 //purpose  : Remove all the object from the viewer
2661 //Draw arg : No args
2662 //==============================================================================
2663
2664 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2665 {
2666   Handle(V3d_View) V = ViewerTest::CurrentView();
2667   if(!V.IsNull())
2668     ViewerTest::Clear();
2669   return 0;
2670 }
2671
2672 //==============================================================================
2673 //function : VPick
2674 //purpose  :
2675 //==============================================================================
2676
2677 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2678 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2679
2680 if ( argc < 4 ) {
2681   di << argv[0] << "Invalid number of arguments\n";
2682   return 1;
2683 }
2684
2685 while (ViewerMainLoop( argc, argv)) {
2686 }
2687
2688 return 0;
2689 }
2690
2691 //==============================================================================
2692 //function : VSetBg
2693 //purpose  : Load image as background
2694 //==============================================================================
2695
2696 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2697 {
2698   if (argc < 2 || argc > 3)
2699   {
2700     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2701     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2702     return 1;
2703   }
2704
2705   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2706   if(AISContext.IsNull())
2707   {
2708     di << "use 'vinit' command before " << argv[0] << "\n";
2709     return 1;
2710   }
2711
2712   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2713   if (argc == 3)
2714   {
2715     const char* szType = argv[2];
2716     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2717     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2718     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2719     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2720     else
2721     {
2722       di << "Wrong fill type : " << szType << "\n";
2723       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2724       return 1;
2725     }
2726   }
2727
2728   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2729   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2730
2731   return 0;
2732 }
2733
2734 //==============================================================================
2735 //function : VSetBgMode
2736 //purpose  : Change background image fill type
2737 //==============================================================================
2738
2739 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2740 {
2741   if (argc != 2)
2742   {
2743     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2744     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2745     return 1;
2746   }
2747
2748   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2749   if(AISContext.IsNull())
2750   {
2751     di << "use 'vinit' command before " << argv[0] << "\n";
2752     return 1;
2753   }
2754   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2755   const char* szType = argv[1];
2756   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2757   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2758   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2759   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2760   else
2761   {
2762     di << "Wrong fill type : " << szType << "\n";
2763     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2764     return 1;
2765   }
2766   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2767   V3dView->SetBgImageStyle(aFillType, Standard_True);
2768   return 0;
2769 }
2770
2771 //==============================================================================
2772 //function : VSetGradientBg
2773 //purpose  : Mount gradient background
2774 //==============================================================================
2775 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2776 {
2777   if (argc != 8 )
2778   {
2779     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2780     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2781     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2782     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2783     return 1;
2784   }
2785
2786   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2787   if(AISContext.IsNull())
2788   {
2789     di << "use 'vinit' command before " << argv[0] << "\n";
2790     return 1;
2791   }
2792   if (argc == 8)
2793   {
2794
2795     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2796     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2797     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2798     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2799
2800     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2801     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2802     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2803
2804     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2805     int aType = Draw::Atoi(argv[7]);
2806     if( aType < 0 || aType > 8 )
2807     {
2808       di << "Wrong fill type \n";
2809       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2810       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2811       return 1;
2812     }
2813
2814     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2815
2816     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2817     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2818   }
2819
2820   return 0;
2821 }
2822
2823 //==============================================================================
2824 //function : VSetGradientBgMode
2825 //purpose  : Change gradient background fill style
2826 //==============================================================================
2827 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2828 {
2829   if (argc != 2 )
2830   {
2831     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2832     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2833     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2834     return 1;
2835   }
2836
2837   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2838   if(AISContext.IsNull())
2839   {
2840     di << "use 'vinit' command before " << argv[0] << "\n";
2841     return 1;
2842   }
2843   if (argc == 2)
2844   {
2845     int aType = Draw::Atoi(argv[1]);
2846     if( aType < 0 || aType > 8 )
2847     {
2848       di << "Wrong fill type \n";
2849       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2850       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2851       return 1;
2852     }
2853
2854     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2855
2856     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2857     V3dView->SetBgGradientStyle( aMethod, 1 );
2858   }
2859
2860   return 0;
2861 }
2862
2863 //==============================================================================
2864 //function : VSetColorBg
2865 //purpose  : Set color background
2866 //==============================================================================
2867 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2868 {
2869   if (argc != 4 )
2870   {
2871     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2872     di << "R,G,B = [0..255]\n";
2873     return 1;
2874   }
2875
2876   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2877   if(AISContext.IsNull())
2878   {
2879     di << "use 'vinit' command before " << argv[0] << "\n";
2880     return 1;
2881   }
2882   if (argc == 4)
2883   {
2884
2885     Standard_Real R = Draw::Atof(argv[1])/255.;
2886     Standard_Real G = Draw::Atof(argv[2])/255.;
2887     Standard_Real B = Draw::Atof(argv[3])/255.;
2888     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2889
2890     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2891     V3dView->SetBackgroundColor( aColor );
2892     V3dView->Update();
2893   }
2894
2895   return 0;
2896 }
2897
2898 //==============================================================================
2899 //function : VSetDefaultBg
2900 //purpose  : Set default viewer background fill color
2901 //==============================================================================
2902 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2903 {
2904   if (theArgNb != 4
2905    && theArgNb != 8)
2906   {
2907     std::cout << "Error: wrong syntax! See usage:\n";
2908     theDI.PrintHelp (theArgVec[0]);
2909     return 1;
2910   }
2911
2912   ViewerTest_DefaultBackground.FillMethod =
2913     theArgNb == 4 ? Aspect_GFM_NONE
2914                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2915
2916   if (theArgNb == 4)
2917   {
2918     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2919     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2920     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2921     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2922   }
2923   else
2924   {
2925     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2926     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2927     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2928     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2929
2930     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2931     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2932     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2933     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2934   }
2935
2936   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2937        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2938   {
2939     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2940     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2941     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2942                                          ViewerTest_DefaultBackground.GradientColor2,
2943                                          ViewerTest_DefaultBackground.FillMethod);
2944   }
2945
2946   return 0;
2947 }
2948
2949 //==============================================================================
2950 //function : VScale
2951 //purpose  : View Scaling
2952 //==============================================================================
2953
2954 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2955 {
2956   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2957   if ( V3dView.IsNull() ) return 1;
2958
2959   if ( argc != 4 ) {
2960     di << argv[0] << "Invalid number of arguments\n";
2961     return 1;
2962   }
2963   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2964   return 0;
2965 }
2966 //==============================================================================
2967 //function : VZBuffTrihedron
2968 //purpose  :
2969 //==============================================================================
2970
2971 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2972                             Standard_Integer  theArgNb,
2973                             const char**      theArgVec)
2974 {
2975   Handle(V3d_View) aView = ViewerTest::CurrentView();
2976   if (aView.IsNull())
2977   {
2978     std::cout << "Error: no active viewer!\n";
2979     return 1;
2980   }
2981
2982   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2983
2984   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2985   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2986   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2987   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2988   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2989   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2990   Standard_Real                 aScale        = 0.1;
2991   Standard_Real                 aSizeRatio    = 0.8;
2992   Standard_Real                 anArrowDiam   = 0.05;
2993   Standard_Integer              aNbFacets     = 12;
2994   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2995   {
2996     Standard_CString        anArg = theArgVec[anArgIter];
2997     TCollection_AsciiString aFlag (anArg);
2998     aFlag.LowerCase();
2999     if (anUpdateTool.parseRedrawMode (aFlag))
3000     {
3001       continue;
3002     }
3003     else if (aFlag == "-on")
3004     {
3005       continue;
3006     }
3007     else if (aFlag == "-off")
3008     {
3009       aView->TriedronErase();
3010       return 0;
3011     }
3012     else if (aFlag == "-pos"
3013           || aFlag == "-position"
3014           || aFlag == "-corner")
3015     {
3016       if (++anArgIter >= theArgNb)
3017       {
3018         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3019         return 1;
3020       }
3021
3022       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3023       aPosName.LowerCase();
3024       if (aPosName == "center")
3025       {
3026         aPosition = Aspect_TOTP_CENTER;
3027       }
3028       else if (aPosName == "left_lower"
3029             || aPosName == "lower_left"
3030             || aPosName == "leftlower"
3031             || aPosName == "lowerleft")
3032       {
3033         aPosition = Aspect_TOTP_LEFT_LOWER;
3034       }
3035       else if (aPosName == "left_upper"
3036             || aPosName == "upper_left"
3037             || aPosName == "leftupper"
3038             || aPosName == "upperleft")
3039       {
3040         aPosition = Aspect_TOTP_LEFT_UPPER;
3041       }
3042       else if (aPosName == "right_lower"
3043             || aPosName == "lower_right"
3044             || aPosName == "rightlower"
3045             || aPosName == "lowerright")
3046       {
3047         aPosition = Aspect_TOTP_RIGHT_LOWER;
3048       }
3049       else if (aPosName == "right_upper"
3050             || aPosName == "upper_right"
3051             || aPosName == "rightupper"
3052             || aPosName == "upperright")
3053       {
3054         aPosition = Aspect_TOTP_RIGHT_UPPER;
3055       }
3056       else
3057       {
3058         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3059         return 1;
3060       }
3061     }
3062     else if (aFlag == "-type")
3063     {
3064       if (++anArgIter >= theArgNb)
3065       {
3066         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3067         return 1;
3068       }
3069
3070       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3071       aTypeName.LowerCase();
3072       if (aTypeName == "wireframe"
3073        || aTypeName == "wire")
3074       {
3075         aVisType = V3d_WIREFRAME;
3076       }
3077       else if (aTypeName == "zbuffer"
3078             || aTypeName == "shaded")
3079       {
3080         aVisType = V3d_ZBUFFER;
3081       }
3082       else
3083       {
3084         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3085       }
3086     }
3087     else if (aFlag == "-scale")
3088     {
3089       if (++anArgIter >= theArgNb)
3090       {
3091         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3092         return 1;
3093       }
3094
3095       aScale = Draw::Atof (theArgVec[anArgIter]);
3096     }
3097     else if (aFlag == "-size"
3098           || aFlag == "-sizeratio")
3099     {
3100       if (++anArgIter >= theArgNb)
3101       {
3102         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3103         return 1;
3104       }
3105
3106       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3107     }
3108     else if (aFlag == "-arrowdiam"
3109           || aFlag == "-arrowdiameter")
3110     {
3111       if (++anArgIter >= theArgNb)
3112       {
3113         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3114         return 1;
3115       }
3116
3117       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3118     }
3119     else if (aFlag == "-nbfacets")
3120     {
3121       if (++anArgIter >= theArgNb)
3122       {
3123         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3124         return 1;
3125       }
3126
3127       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3128     }
3129     else if (aFlag == "-colorlabel"
3130           || aFlag == "-colorlabels")
3131     {
3132       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3133                                                            theArgVec + anArgIter + 1,
3134                                                            aLabelsColor);
3135       if (aNbParsed == 0)
3136       {
3137         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3138         return 1;
3139       }
3140       anArgIter += aNbParsed;
3141     }
3142     else if (aFlag == "-colorarrowx")
3143     {
3144       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3145                                                            theArgVec + anArgIter + 1,
3146                                                            anArrowColorX);
3147       if (aNbParsed == 0)
3148       {
3149         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3150         return 1;
3151       }
3152       anArgIter += aNbParsed;
3153     }
3154     else if (aFlag == "-colorarrowy")
3155     {
3156       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3157                                                            theArgVec + anArgIter + 1,
3158                                                            anArrowColorY);
3159       if (aNbParsed == 0)
3160       {
3161         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3162         return 1;
3163       }
3164       anArgIter += aNbParsed;
3165     }
3166     else if (aFlag == "-colorarrowz")
3167     {
3168       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3169                                                            theArgVec + anArgIter + 1,
3170                                                            anArrowColorZ);
3171       if (aNbParsed == 0)
3172       {
3173         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3174         return 1;
3175       }
3176       anArgIter += aNbParsed;
3177     }
3178     else
3179     {
3180       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3181       return 1;
3182     }
3183   }
3184
3185   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3186                                aSizeRatio, anArrowDiam, aNbFacets);
3187   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3188   aView->ZFitAll();
3189   return 0;
3190 }
3191
3192 //==============================================================================
3193 //function : VRotate
3194 //purpose  : Camera Rotating
3195 //==============================================================================
3196
3197 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3198 {
3199   Handle(V3d_View) aView = ViewerTest::CurrentView();
3200   if (aView.IsNull())
3201   {
3202     std::cout << "No active view!\n";
3203     return 1;
3204   }
3205
3206   Standard_Boolean hasFlags = Standard_False;
3207   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3208   {
3209     Standard_CString        anArg (theArgVec[anArgIter]);
3210     TCollection_AsciiString aFlag (anArg);
3211     aFlag.LowerCase();
3212     if (aFlag == "-mousestart"
3213      || aFlag == "-mousefrom")
3214     {
3215       hasFlags = Standard_True;
3216       if (anArgIter + 2 >= theArgNb)
3217       {
3218         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3219         return 1;
3220       }
3221
3222       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3223       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3224       aView->StartRotation (anX, anY);
3225     }
3226     else if (aFlag == "-mousemove")
3227     {
3228       hasFlags = Standard_True;
3229       if (anArgIter + 2 >= theArgNb)
3230       {
3231         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3232         return 1;
3233       }
3234
3235       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3236       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3237       aView->Rotation (anX, anY);
3238     }
3239     else if (theArgNb != 4
3240           && theArgNb != 7)
3241     {
3242       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3243       return 1;
3244     }
3245   }
3246
3247   if (hasFlags)
3248   {
3249     return 0;
3250   }
3251   else if (theArgNb == 4)
3252   {
3253     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3254     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3255     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3256     aView->Rotate (anAX, anAY, anAZ);
3257     return 0;
3258   }
3259   else if (theArgNb == 7)
3260   {
3261     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3262     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3263     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3264
3265     Standard_Real anX = Draw::Atof (theArgVec[4]);
3266     Standard_Real anY = Draw::Atof (theArgVec[5]);
3267     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3268
3269     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3270     return 0;
3271   }
3272
3273   std::cout << "Error: Invalid number of arguments\n";
3274   return 1;
3275 }
3276
3277 //==============================================================================
3278 //function : VZoom
3279 //purpose  : View zoom in / out (relative to current zoom)
3280 //==============================================================================
3281
3282 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3283   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3284   if ( V3dView.IsNull() ) {
3285     return 1;
3286   }
3287
3288   if ( argc == 2 ) {
3289     Standard_Real coef = Draw::Atof(argv[1]);
3290     if ( coef <= 0.0 ) {
3291       di << argv[1] << "Invalid value\n";
3292       return 1;
3293     }
3294     V3dView->SetZoom( Draw::Atof(argv[1]) );
3295     return 0;
3296   } else {
3297     di << argv[0] << " Invalid number of arguments\n";
3298     return 1;
3299   }
3300 }
3301
3302 //==============================================================================
3303 //function : VPan
3304 //purpose  : View panning (in pixels)
3305 //==============================================================================
3306
3307 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3308   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3309   if ( V3dView.IsNull() ) return 1;
3310
3311   if ( argc == 3 ) {
3312     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3313     return 0;
3314   } else {
3315     di << argv[0] << " Invalid number of arguments\n";
3316     return 1;
3317   }
3318 }
3319
3320 //==============================================================================
3321 //function : VPlace
3322 //purpose  : Place the point (in pixels) at the center of the window
3323 //==============================================================================
3324 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3325 {
3326   Handle(V3d_View) aView = ViewerTest::CurrentView();
3327   if (aView.IsNull())
3328   {
3329     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3330     return 1;
3331   }
3332
3333   if (theArgNb != 3)
3334   {
3335     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3336     return 1;
3337   }
3338
3339   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3340
3341   return 0;
3342 }
3343
3344 //==============================================================================
3345 //function : VExport
3346 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3347 //==============================================================================
3348
3349 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3350 {
3351   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3352   if (V3dView.IsNull())
3353     return 1;
3354
3355   if (argc == 1)
3356   {
3357     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3358     return 1;
3359   }
3360
3361   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3362   TCollection_AsciiString aFormatStr;
3363
3364   TCollection_AsciiString aFileName (argv[1]);
3365   Standard_Integer aLen = aFileName.Length();
3366
3367   if (argc > 2)
3368   {
3369     aFormatStr = TCollection_AsciiString (argv[2]);
3370   }
3371   else if (aLen >= 4)
3372   {
3373     if (aFileName.Value (aLen - 2) == '.')
3374     {
3375       aFormatStr = aFileName.ToCString() + aLen - 2;
3376     }
3377     else if (aFileName.Value (aLen - 3) == '.')
3378     {
3379       aFormatStr = aFileName.ToCString() + aLen - 3;
3380     }
3381     else
3382     {
3383       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3384       return 1;
3385     }
3386   }
3387   else
3388   {
3389     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3390     return 1;
3391   }
3392
3393   aFormatStr.UpperCase();
3394   if (aFormatStr == "PS")
3395     anExpFormat = Graphic3d_EF_PostScript;
3396   else if (aFormatStr == "EPS")
3397     anExpFormat = Graphic3d_EF_EnhPostScript;
3398   else if (aFormatStr == "TEX")
3399     anExpFormat = Graphic3d_EF_TEX;
3400   else if (aFormatStr == "PDF")
3401     anExpFormat = Graphic3d_EF_PDF;
3402   else if (aFormatStr == "SVG")
3403     anExpFormat = Graphic3d_EF_SVG;
3404   else if (aFormatStr == "PGF")
3405     anExpFormat = Graphic3d_EF_PGF;
3406   else if (aFormatStr == "EMF")
3407     anExpFormat = Graphic3d_EF_EMF;
3408   else
3409   {
3410     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3411     return 1;
3412   }
3413
3414   try
3415   {
3416   Standard_DISABLE_DEPRECATION_WARNINGS
3417     if (!V3dView->Export (argv[1], anExpFormat))
3418   Standard_ENABLE_DEPRECATION_WARNINGS
3419     {
3420       di << "Error: export of image to " << aFormatStr << " failed!\n";
3421     }
3422   }
3423   catch (Standard_Failure)
3424   {
3425     di << "Error: export of image to " << aFormatStr << " failed";
3426     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
3427   }
3428   return 0;
3429 }
3430
3431 //==============================================================================
3432 //function : VColorScale
3433 //purpose  : representation color scale
3434 //==============================================================================
3435
3436 static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
3437                                     const TCollection_AsciiString& theGreen,
3438                                     const TCollection_AsciiString& theBlue,
3439                                                     Standard_Real& theRedValue,
3440                                                     Standard_Real& theGreenValue,
3441                                                     Standard_Real& theBlueValue)
3442 {
3443   if (!theRed.IsRealValue()
3444    || !theGreen.IsRealValue()
3445    || !theBlue.IsRealValue())
3446   {
3447     std::cout << "Error: RGB color values should be real!\n";
3448     return Standard_True;
3449   }
3450   theRedValue = theRed    .RealValue();
3451   theGreenValue = theGreen.RealValue();
3452   theBlueValue = theBlue  .RealValue();
3453   if (theRedValue < 0.0 || theRedValue > 1.0
3454    || theGreenValue < 0.0 || theGreenValue > 1.0
3455    || theBlueValue < 0.0 || theBlueValue > 1.0)
3456   {
3457     std::cout << "Error: RGB color values should be within range 0..1!\n";
3458     return Standard_True;
3459   }
3460   return Standard_False;
3461 }
3462
3463 static int VColorScale (Draw_Interpretor& theDI,
3464                         Standard_Integer  theArgNb,
3465                         const char**      theArgVec)
3466 {
3467   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3468   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3469   if (aContext.IsNull())
3470   {
3471     std::cout << "Error: no active view!\n";
3472     return 1;
3473   }
3474   if (theArgNb <= 1)
3475   {
3476     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3477     return 1;
3478   }
3479
3480   Handle(AIS_ColorScale) aCS;
3481   // find object
3482   Handle(AIS_InteractiveObject) anIObj;
3483   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3484   {
3485     aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3486     if (aCS.IsNull())
3487     {
3488       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3489       return 1;
3490     }
3491   }
3492   else
3493   {
3494     aCS = new AIS_ColorScale();
3495     GetMapOfAIS().Bind (aCS,theArgVec[1]);
3496   }
3497
3498   if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD)
3499   {
3500     aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3501   }
3502   if (aCS->TransformPersistence().IsNull()
3503    || aCS->TransformPersistence()->Mode() != Graphic3d_TMF_2d)
3504   {
3505     aContext->SetTransformPersistence (aCS, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3506   }
3507
3508   Standard_Real                   aMinRange    = aCS->GetMin();
3509   Standard_Real                   aMaxRange    = aCS->GetMax();
3510   Standard_Integer                aBreadth     = aCS->GetBreadth();
3511   Standard_Integer                aHeight      = aCS->GetHeight();
3512   Standard_Integer                aNbIntervals = aCS->GetNumberOfIntervals();
3513   Standard_Integer                aTextHeight  = aCS->GetTextHeight();
3514   Aspect_TypeOfColorScalePosition aLabPosition = aCS->GetLabelPosition();
3515   Standard_Integer                aPosX = aCS->GetXPosition();
3516   Standard_Integer                aPosY = aCS->GetYPosition();
3517
3518   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3519
3520   if (theArgNb <= 2)
3521   {
3522     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3523           << "Min range: " << aMinRange << "\n"
3524           << "Max range: " << aMaxRange << "\n"
3525           << "Number of intervals: " << aNbIntervals << "\n"
3526           << "Text height: " << aTextHeight << "\n"
3527           << "Color scale position: " << aPosX <<" "<< aPosY<< "\n"
3528           << "Color scale title: " << aCS->GetTitle() << "\n"
3529           << "Label position: ";
3530     switch (aLabPosition)
3531     {
3532       case Aspect_TOCSP_NONE:
3533         theDI << "None\n";
3534         break;
3535       case Aspect_TOCSP_LEFT:
3536         theDI << "Left\n";
3537         break;
3538       case Aspect_TOCSP_RIGHT:
3539         theDI << "Right\n";
3540         break;
3541       case Aspect_TOCSP_CENTER:
3542         theDI << "Center\n";
3543         break;
3544     }
3545     return 0;
3546   }
3547
3548   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3549   {
3550     Standard_CString        anArg = theArgVec[anArgIter];
3551     TCollection_AsciiString aFlag (anArg);
3552     aFlag.LowerCase();
3553     if (anUpdateTool.parseRedrawMode (aFlag))
3554     {
3555       continue;
3556     }
3557     else if (aFlag == "-range")
3558     {
3559       if (anArgIter + 3 >= theArgNb)
3560       {
3561         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3562         return 1;
3563       }
3564
3565       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3566       TCollection_AsciiString anArg2 (theArgVec[++anArgIter]);
3567       TCollection_AsciiString anArg3 (theArgVec[++anArgIter]);
3568       if (!anArg1.IsRealValue())
3569       {
3570         std::cout << "Error: the minRange value should be real!\n";
3571         return 1;
3572       }
3573       else if (!anArg2.IsRealValue())
3574       {
3575         std::cout << "Error: the maxRange value should be real!\n";
3576         return 1;
3577       }
3578       else if (!anArg3.IsIntegerValue())
3579       {
3580         std::cout << "Error: the number of intervals should be integer!\n";
3581         return 1;
3582       }
3583
3584       aMinRange    = anArg1.RealValue();
3585       aMaxRange    = anArg2.RealValue();
3586       aNbIntervals = anArg3.IntegerValue();
3587     }
3588     else if (aFlag == "-font")
3589     {
3590       if (anArgIter + 1 >= theArgNb)
3591       {
3592         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3593         return 1;
3594       }
3595       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3596       if (!aFontArg.IsIntegerValue())
3597       {
3598         std::cout << "Error: HeightFont value should be integer!\n";
3599         return 1;
3600       }
3601
3602       aTextHeight = aFontArg.IntegerValue();
3603       anArgIter += 1;
3604     }
3605     else if (aFlag == "-textpos")
3606     {
3607       if (anArgIter + 1 >= theArgNb)
3608       {
3609         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3610         return 1;
3611       }
3612       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3613       aTextPosArg.LowerCase();
3614       if (aTextPosArg == "none")
3615       {
3616         aLabPosition = Aspect_TOCSP_NONE;
3617       }
3618       else if (aTextPosArg == "left")
3619       {
3620         aLabPosition = Aspect_TOCSP_LEFT;
3621       }
3622       else if (aTextPosArg == "right")
3623       {
3624         aLabPosition = Aspect_TOCSP_RIGHT;
3625       }
3626       else if (aTextPosArg == "center")
3627       {
3628         aLabPosition = Aspect_TOCSP_CENTER;
3629       }
3630       else
3631       {
3632         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3633         return 1;
3634       }
3635     }
3636     else if (aFlag == "-logarithmic"
3637           || aFlag == "-log")
3638     {
3639       if (anArgIter + 1 >= theArgNb)
3640       {
3641         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3642         return 1;
3643       }
3644       Standard_Boolean IsLog;
3645       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3646       {
3647         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3648         return 1;
3649       }
3650       aCS->SetLogarithmic (IsLog);
3651     }
3652     else if (aFlag == "-xy")
3653     {
3654       if (anArgIter + 2 >= theArgNb)
3655       {
3656         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3657         return 1;
3658       }
3659
3660       TCollection_AsciiString aX (theArgVec[++anArgIter]);
3661       TCollection_AsciiString aY (theArgVec[++anArgIter]);
3662       if (!aX.IsIntegerValue()
3663        || !aY.IsIntegerValue())
3664       {
3665         std::cout << "Error: coordinates should be integer values!\n";
3666         return 1;
3667       }
3668
3669       aPosX = aX.IntegerValue();
3670       aPosY = aY.IntegerValue();
3671     }
3672     else if (aFlag == "-width"
3673           || aFlag == "-w")
3674     {
3675       if (anArgIter + 1 >= theArgNb)
3676       {
3677         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3678         return 1;
3679       }
3680
3681       TCollection_AsciiString aW (theArgVec[++anArgIter]);
3682       if (!aW.IsIntegerValue())
3683       {
3684         std::cout << "Error: a width should be an integer value!\n";
3685         return 1;
3686       }
3687
3688       aBreadth = aW.IntegerValue();
3689     }
3690     else if (aFlag == "-height"
3691           || aFlag == "-h")
3692     {
3693       if (anArgIter + 1 >= theArgNb)
3694       {
3695         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3696         return 1;
3697       }
3698
3699       TCollection_AsciiString aH (theArgVec[++anArgIter]);
3700       if (!aH.IsIntegerValue())
3701       {
3702         std::cout << "Error: a width should be an integer value!\n";
3703         return 1;
3704       }
3705
3706       aHeight = aH.IntegerValue();
3707     }
3708     else if (aFlag == "-color")
3709     {
3710       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3711       {
3712         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3713         return 1;
3714       }
3715
3716       Quantity_NameOfColor aColorName;
3717       if (anArgIter + 4 >= theArgNb)
3718       {
3719         if (anArgIter + 2 >= theArgNb)
3720         {
3721           std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3722           return 1;
3723         }
3724         else if (!Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3725         {
3726           std::cout << "Error: wrong color name: '" << theArgVec[anArgIter + 2] << "' !\n";
3727           return 1;
3728         }
3729       }
3730
3731       TCollection_AsciiString anInd (theArgVec[anArgIter + 1]);
3732       if (!anInd.IsIntegerValue())
3733       {
3734         std::cout << "Error: Index value should be integer!\n";
3735         return 1;
3736       }
3737
3738       Standard_Integer anIndex = anInd.IntegerValue();
3739       if (anIndex <= 0 || anIndex > aNbIntervals)
3740       {
3741         std::cout << "Error: Index value should be within range 1.." << aNbIntervals <<"!\n";
3742         return 1;
3743       }
3744
3745       if (Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3746       {
3747         aCS->SetIntervalColor (Quantity_Color (aColorName), anIndex);
3748         aCS->SetColorType (Aspect_TOCSD_USER);
3749         anArgIter += 2;
3750         continue;
3751       }
3752
3753       TCollection_AsciiString aRed   (theArgVec[anArgIter + 2]);
3754       TCollection_AsciiString aGreen (theArgVec[anArgIter + 3]);
3755       TCollection_AsciiString aBlue  (theArgVec[anArgIter + 4]);
3756       Standard_Real aRedValue,aGreenValue, aBlueValue;
3757       if(checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3758       {
3759         return 1;
3760       }
3761       aCS->SetIntervalColor (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB), anIndex);
3762       aCS->SetColorType (Aspect_TOCSD_USER);
3763       anArgIter += 4;
3764     }
3765     else if (aFlag == "-label")
3766     {
3767       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3768       {
3769         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3770         return 1;
3771       }
3772       else if (anArgIter + 2 >= theArgNb)
3773       {
3774         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3775         return 1;
3776       }
3777
3778       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3779       if (anIndex <= 0 || anIndex > aNbIntervals+1)
3780       {
3781         std::cout << "Error: Index value should be within range 1.." << aNbIntervals+1 <<"!\n";
3782         return 1;
3783       }
3784
3785       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3786       aCS->SetLabel     (aText, anIndex);
3787       aCS->SetLabelType (Aspect_TOCSD_USER);
3788       anArgIter += 2;
3789     }
3790     else if (aFlag == "-colors")
3791     {
3792       Aspect_SequenceOfColor aSeq;
3793       if (anArgIter + aNbIntervals + 1 > theArgNb)
3794       {
3795         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3796                   << aNbIntervals << " intervals\n";
3797         return 1;
3798       }
3799
3800       Standard_Integer aColorIter = anArgIter + 1;
3801       while (aColorIter < theArgNb)
3802       {
3803         if (theArgVec[aColorIter][0] == '-')
3804         {
3805           break;
3806         }
3807
3808         else if (theArgVec[aColorIter][0] >= 97
3809               && theArgVec[aColorIter][0] <= 122)
3810         {
3811           Quantity_NameOfColor aColorName;
3812           if (!Quantity_Color::ColorFromName (theArgVec[aColorIter], aColorName))
3813           {
3814             std::cout << "Error: wrong color name: " << theArgVec[aColorIter] << " !\n";
3815             return 1;
3816           }
3817           aSeq.Append (Quantity_Color (aColorName));
3818           aColorIter++;
3819           anArgIter++;
3820         }
3821         else
3822         {
3823           TCollection_AsciiString aRed   (theArgVec[aColorIter]);
3824           TCollection_AsciiString aGreen (theArgVec[aColorIter + 1]);
3825           TCollection_AsciiString aBlue  (theArgVec[aColorIter + 2]);
3826           Standard_Real aRedValue,aGreenValue, aBlueValue;
3827           if (checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3828           {
3829             return 1;
3830           }
3831           aSeq.Append (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB));
3832           aColorIter += 3;
3833           anArgIter += 3;
3834         }
3835       }
3836       if (aSeq.Length() < aNbIntervals)
3837       {
3838         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3839                   << aNbIntervals << " intervals\n";
3840         return 1;
3841       }
3842
3843       aCS->SetColors    (aSeq);
3844       aCS->SetColorType (Aspect_TOCSD_USER);
3845     }
3846     else if (aFlag == "-labels")
3847     {
3848       if (anArgIter + aNbIntervals + 1 >= theArgNb)
3849       {
3850         std::cout << "Error: not enough arguments! You should provide " << (aNbIntervals + 1)
3851                   << " text labels for " << aNbIntervals << " intervals.\n";
3852         return 1;
3853       }
3854
3855       TColStd_SequenceOfExtendedString aSeq;
3856       for (int aLabelIter = anArgIter + 1; aLabelIter <= anArgIter + aNbIntervals + 1; aLabelIter += 1)
3857       {
3858         aSeq.Append (TCollection_ExtendedString (theArgVec[aLabelIter]));
3859       }
3860       aCS->SetLabels (aSeq);
3861       aCS->SetLabelType (Aspect_TOCSD_USER);
3862       anArgIter += aSeq.Length();
3863     }
3864     else if (aFlag == "-title")
3865     {
3866       if (anArgIter + 1 >= theArgNb)
3867       {
3868         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3869         return 1;
3870       }
3871
3872       Standard_Boolean isTwoArgs = Standard_False;
3873       if (anArgIter + 2 < theArgNb)
3874       {
3875         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3876         aSecondArg.LowerCase();
3877         if (aSecondArg == "none")
3878         {
3879           aCS->SetTitlePosition (Aspect_TOCSP_NONE);
3880           isTwoArgs = Standard_True;
3881         }
3882         else if (aSecondArg == "left")
3883         {
3884           aCS->SetTitlePosition (Aspect_TOCSP_LEFT);
3885           isTwoArgs = Standard_True;
3886         }
3887         else if (aSecondArg == "right")
3888         {
3889           aCS->SetTitlePosition (Aspect_TOCSP_RIGHT);
3890           isTwoArgs = Standard_True;
3891         }
3892         else if (aSecondArg == "center")
3893         {
3894           aCS->SetTitlePosition (Aspect_TOCSP_CENTER);
3895           isTwoArgs = Standard_True;
3896         }
3897       }
3898
3899       aCS->SetTitle (theArgVec[anArgIter + 1]);
3900       if (isTwoArgs)
3901       {
3902         anArgIter += 1;
3903       }
3904       anArgIter += 1;
3905     }
3906     else if (aFlag == "-demoversion"
3907           || aFlag == "-demo")
3908     {
3909       aPosX        = 0;
3910       aPosY        = 0;
3911       aTextHeight  = 16;
3912       aMinRange    = 0.0;
3913       aMaxRange    = 100;
3914       aNbIntervals = 10;
3915       aBreadth     = 0;
3916       aHeight      = 0;
3917       aLabPosition = Aspect_TOCSP_RIGHT;
3918       aCS->SetColorType (Aspect_TOCSD_AUTO);
3919       aCS->SetLabelType (Aspect_TOCSD_AUTO);
3920     }
3921     else if (aFlag == "-findcolor")
3922     {
3923       if (anArgIter + 1 >= theArgNb)
3924       {
3925         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3926         return 1;
3927       }
3928
3929       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3930
3931       if (!anArg1.IsRealValue())
3932       {
3933         std::cout << "Error: the value should be real!\n";
3934         return 1;
3935       }
3936
3937       Quantity_Color aColor;
3938       aCS->FindColor (anArg1.RealValue(), aColor);
3939       theDI << Quantity_Color::StringName (aColor.Name());
3940       return 0;
3941     }
3942     else
3943     {
3944       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3945       return 1;
3946     }
3947   }
3948   if (!aBreadth || !aHeight)
3949   {
3950     Standard_Integer aWinWidth, aWinHeight;
3951     aView->Window()->Size (aWinWidth, aWinHeight);
3952     if (!aBreadth)
3953     {
3954       aBreadth = aWinWidth;
3955     }
3956     if (!aHeight)
3957     {
3958       aHeight = aWinHeight;
3959     }
3960   }
3961   aCS->SetSize              (aBreadth, aHeight);
3962   aCS->SetPosition          (aPosX, aPosY);
3963   aCS->SetTextHeight        (aTextHeight);
3964   aCS->SetRange             (aMinRange, aMaxRange);
3965   aCS->SetNumberOfIntervals (aNbIntervals);
3966   aCS->SetLabelPosition     (aLabPosition);
3967 //  aCS->SetColor             (aView->BackgroundColor().Invert());
3968   aCS->SetToUpdate();
3969   aContext->Display (aCS);
3970
3971   return 0;
3972 }
3973
3974 //==============================================================================
3975 //function : VGraduatedTrihedron
3976 //purpose  : Displays or hides a graduated trihedron
3977 //==============================================================================
3978 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
3979                                   Quantity_Color& theColor)
3980 {
3981   Quantity_NameOfColor aColorName;
3982   TCollection_AsciiString aVal = theValue;
3983   aVal.UpperCase();
3984   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
3985   {
3986     return Standard_False;
3987   }
3988   theColor = Quantity_Color (aColorName);
3989   return Standard_True;
3990 }
3991
3992 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
3993 {
3994   if (theArgNum < 2)
3995   {
3996     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
3997               << theArgs[0] <<"' for more information.\n";
3998     return 1;  //TCL_ERROR
3999   }
4000
4001   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4002   TCollection_AsciiString aParseKey;
4003   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4004   {
4005     TCollection_AsciiString anArg (theArgs [anArgIt]);
4006
4007     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4008     {
4009       aParseKey = anArg;
4010       aParseKey.Remove (1);
4011       aParseKey.LowerCase();
4012       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4013       continue;
4014     }
4015
4016     if (aParseKey.IsEmpty())
4017     {
4018       continue;
4019     }
4020
4021     aMapOfArgs(aParseKey)->Append (anArg);
4022   }
4023
4024   // Check parameters
4025   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4026        aMapIt.More(); aMapIt.Next())
4027   {
4028     const TCollection_AsciiString& aKey = aMapIt.Key();
4029     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4030
4031     // Bool key, without arguments
4032     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4033         && anArgs->IsEmpty())
4034     {
4035       continue;
4036     }
4037
4038     // One argument
4039     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4040           && anArgs->Length() == 1)
4041     {
4042       continue;
4043     }
4044
4045     // On/off arguments
4046     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4047         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4048         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4049         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4050         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4051     {
4052       continue;
4053     }
4054
4055     // One string argument
4056     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4057           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4058           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4059     {
4060       continue;
4061     }
4062
4063     // One integer argument
4064     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4065           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4066           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4067           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4068          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4069     {
4070       continue;
4071     }
4072
4073     // One real argument
4074     if ( aKey.IsEqual ("arrowlength")
4075          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4076     {
4077       continue;
4078     }
4079
4080     // Two string arguments
4081     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4082          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4083     {
4084       continue;
4085     }
4086
4087     TCollection_AsciiString aLowerKey;
4088     aLowerKey  = "-";
4089     aLowerKey += aKey;
4090     aLowerKey.LowerCase();
4091     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4092     std::cout << "Type help for more information.\n";
4093     return 1;
4094   }
4095
4096   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4097   if (anAISContext.IsNull())
4098   {
4099     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4100     return 1;
4101   }
4102
4103   Standard_Boolean toDisplay = Standard_True;
4104   Quantity_Color aColor;
4105   Graphic3d_GraduatedTrihedron aTrihedronData;
4106   // Process parameters
4107   Handle(TColStd_HSequenceOfAsciiString) aValues;
4108   if (aMapOfArgs.Find ("off", aValues))
4109   {
4110     toDisplay = Standard_False;
4111   }
4112
4113   // AXES NAMES
4114   if (aMapOfArgs.Find ("xname", aValues))
4115   {
4116     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4117   }
4118   if (aMapOfArgs.Find ("yname", aValues))
4119   {
4120     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4121   }
4122   if (aMapOfArgs.Find ("zname", aValues))
4123   {
4124     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4125   }
4126   if (aMapOfArgs.Find ("xdrawname", aValues))
4127   {
4128     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4129   }
4130   if (aMapOfArgs.Find ("ydrawname", aValues))
4131   {
4132     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4133   }
4134   if (aMapOfArgs.Find ("zdrawname", aValues))
4135   {
4136     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4137   }
4138   if (aMapOfArgs.Find ("xnameoffset", aValues))
4139   {
4140     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4141   }
4142   if (aMapOfArgs.Find ("ynameoffset", aValues))
4143   {
4144     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4145   }
4146   if (aMapOfArgs.Find ("znameoffset", aValues))
4147   {
4148     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4149   }
4150
4151   // COLORS
4152   if (aMapOfArgs.Find ("xnamecolor", aValues))
4153   {
4154     if (!GetColor (aValues->Value(1), aColor))
4155     {
4156       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4157       return 1;
4158     }
4159     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4160   }
4161   if (aMapOfArgs.Find ("ynamecolor", aValues))
4162   {
4163     if (!GetColor (aValues->Value(1), aColor))
4164     {
4165       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4166       return 1;
4167     }
4168     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4169   }
4170   if (aMapOfArgs.Find ("znamecolor", aValues))
4171   {
4172     if (!GetColor (aValues->Value(1), aColor))
4173     {
4174       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4175       return 1;
4176     }
4177     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4178   }
4179   if (aMapOfArgs.Find ("xcolor", aValues))
4180   {
4181     if (!GetColor (aValues->Value(1), aColor))
4182     {
4183       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4184       return 1;
4185     }
4186     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4187   }
4188   if (aMapOfArgs.Find ("ycolor", aValues))
4189   {
4190     if (!GetColor (aValues->Value(1), aColor))
4191     {
4192       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4193       return 1;
4194     }
4195     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4196   }
4197   if (aMapOfArgs.Find ("zcolor", aValues))
4198   {
4199     if (!GetColor (aValues->Value(1), aColor))
4200     {
4201       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4202       return 1;
4203     }
4204     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4205   }
4206
4207   // TICKMARKS
4208   if (aMapOfArgs.Find ("xticks", aValues))
4209   {
4210     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4211   }
4212   if (aMapOfArgs.Find ("yticks", aValues))
4213   {
4214     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4215   }
4216   if (aMapOfArgs.Find ("zticks", aValues))
4217   {
4218     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4219   }
4220   if (aMapOfArgs.Find ("xticklength", aValues))
4221   {
4222     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4223   }
4224   if (aMapOfArgs.Find ("yticklength", aValues))
4225   {
4226     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4227   }
4228   if (aMapOfArgs.Find ("zticklength", aValues))
4229   {
4230     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4231   }
4232   if (aMapOfArgs.Find ("xdrawticks", aValues))
4233   {
4234     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4235   }
4236   if (aMapOfArgs.Find ("ydrawticks", aValues))
4237   {
4238     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4239   }
4240   if (aMapOfArgs.Find ("zdrawticks", aValues))
4241   {
4242     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4243   }
4244
4245   // VALUES
4246   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4247   {
4248     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4249   }
4250   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4251   {
4252     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4253   }
4254   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4255   {
4256     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4257   }
4258   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4259   {
4260     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4261   }
4262   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4263   {
4264     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4265   }
4266   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4267   {
4268     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4269   }
4270
4271   // ARROWS
4272   if (aMapOfArgs.Find ("arrowlength", aValues))
4273   {
4274     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4275   }
4276
4277   // FONTS
4278   if (aMapOfArgs.Find ("namefont", aValues))
4279   {
4280     aTrihedronData.SetNamesFont (aValues->Value(1));
4281   }
4282   if (aMapOfArgs.Find ("valuesfont", aValues))
4283   {
4284     aTrihedronData.SetValuesFont (aValues->Value(1));
4285   }
4286
4287   if (aMapOfArgs.Find ("drawgrid", aValues))
4288   {
4289     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4290   }
4291   if (aMapOfArgs.Find ("drawaxes", aValues))
4292   {
4293     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4294   }
4295
4296   // The final step: display of erase trihedron
4297   if (toDisplay)
4298   {
4299     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4300   }
4301   else
4302   {
4303     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4304   }
4305
4306   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4307   ViewerTest::CurrentView()->Redraw();
4308
4309   return 0;
4310 }
4311
4312 //==============================================================================
4313 //function : VTile
4314 //purpose  :
4315 //==============================================================================
4316 static int VTile (Draw_Interpretor& theDI,
4317                   Standard_Integer  theArgNb,
4318                   const char**      theArgVec)
4319 {
4320   Handle(V3d_View) aView = ViewerTest::CurrentView();
4321   if (aView.IsNull())
4322   {
4323     std::cerr << "Error: no active viewer.\n";
4324     return 1;
4325   }
4326
4327   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4328   if (theArgNb < 2)
4329   {
4330     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4331           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4332           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4333     return 0;
4334   }
4335
4336   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4337   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4338   {
4339     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4340     anArg.LowerCase();
4341     if (anArg == "-lowerleft"
4342      || anArg == "-upperleft")
4343     {
4344       if (anArgIter + 3 < theArgNb)
4345       {
4346         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4347         return 1;
4348       }
4349       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4350       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4351       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4352     }
4353     else if (anArg == "-total"
4354           || anArg == "-totalsize"
4355           || anArg == "-viewsize")
4356     {
4357       if (anArgIter + 3 < theArgNb)
4358       {
4359         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4360         return 1;
4361       }
4362       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4363       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4364       if (aTile.TotalSize.x() < 1
4365        || aTile.TotalSize.y() < 1)
4366       {
4367         std::cerr << "Error: total size is incorrect.\n";
4368         return 1;
4369       }
4370     }
4371     else if (anArg == "-tilesize")
4372     {
4373       if (anArgIter + 3 < theArgNb)
4374       {
4375         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4376         return 1;
4377       }
4378
4379       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4380       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4381       if (aTile.TileSize.x() < 1
4382        || aTile.TileSize.y() < 1)
4383       {
4384         std::cerr << "Error: tile size is incorrect.\n";
4385         return 1;
4386       }
4387     }
4388     else if (anArg == "-unset")
4389     {
4390       aView->Camera()->SetTile (Graphic3d_CameraTile());
4391       aView->Redraw();
4392       return 0;
4393     }
4394   }
4395
4396   if (aTile.TileSize.x() < 1
4397    || aTile.TileSize.y() < 1)
4398   {
4399     std::cerr << "Error: tile size is undefined.\n";
4400     return 1;
4401   }
4402   else if (aTile.TotalSize.x() < 1
4403         || aTile.TotalSize.y() < 1)
4404   {
4405     std::cerr << "Error: total size is undefined.\n";
4406     return 1;
4407   }
4408
4409   aView->Camera()->SetTile (aTile);
4410   aView->Redraw();
4411   return 0;
4412 }
4413
4414 //! Format ZLayer ID.
4415 inline const char* formZLayerId (const Standard_Integer theLayerId)
4416 {
4417   switch (theLayerId)
4418   {
4419     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4420     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4421     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4422     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4423     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4424     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4425   }
4426   return "";
4427 }
4428
4429 //! Print the ZLayer information.
4430 inline void printZLayerInfo (Draw_Interpretor& theDI,
4431                              const Graphic3d_ZLayerSettings& theLayer)
4432 {
4433   if (!theLayer.Name().IsEmpty())
4434   {
4435     theDI << "  Name: " << theLayer.Name() << "\n";
4436   }
4437   if (theLayer.IsImmediate())
4438   {
4439     theDI << "  Immediate: TRUE\n";
4440   }
4441   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4442   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4443   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4444   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4445   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4446   {
4447     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4448   }
4449 }
4450
4451 //==============================================================================
4452 //function : VZLayer
4453 //purpose  : Test z layer operations for v3d viewer
4454 //==============================================================================
4455 static int VZLayer (Draw_Interpretor& theDI,
4456                     Standard_Integer  theArgNb,
4457                     const char**      theArgVec)
4458 {
4459   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4460   if (aContextAIS.IsNull())
4461   {
4462     std::cout << "No active viewer!\n";
4463     return 1;
4464   }
4465
4466   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4467   if (theArgNb < 2)
4468   {
4469     TColStd_SequenceOfInteger aLayers;
4470     aViewer->GetAllZLayers (aLayers);
4471     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4472     {
4473       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4474       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4475       printZLayerInfo (theDI, aSettings);
4476     }
4477     return 1;
4478   }
4479
4480   Standard_Integer anArgIter = 1;
4481   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4482   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4483   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4484   {
4485     ++anArgIter;
4486   }
4487
4488   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4489   if (aFirstArg.IsIntegerValue())
4490   {
4491     ++anArgIter;
4492     aLayerId = aFirstArg.IntegerValue();
4493   }
4494   else
4495   {
4496     aFirstArg.LowerCase();
4497     if (aFirstArg == "default"
4498      || aFirstArg == "def")
4499     {
4500       aLayerId = Graphic3d_ZLayerId_Default;
4501       ++anArgIter;
4502     }
4503     else if (aFirstArg == "top")
4504     {
4505       aLayerId = Graphic3d_ZLayerId_Top;
4506       ++anArgIter;
4507     }
4508     else if (aFirstArg == "topmost")
4509     {
4510       aLayerId = Graphic3d_ZLayerId_Topmost;
4511       ++anArgIter;
4512     }
4513     else if (aFirstArg == "overlay"
4514           || aFirstArg == "toposd")
4515     {
4516       aLayerId = Graphic3d_ZLayerId_TopOSD;
4517       ++anArgIter;
4518     }
4519     else if (aFirstArg == "underlay"
4520           || aFirstArg == "botosd")
4521     {
4522       aLayerId = Graphic3d_ZLayerId_BotOSD;
4523       ++anArgIter;
4524     }
4525     else
4526     {
4527       TColStd_SequenceOfInteger aLayers;
4528       aViewer->GetAllZLayers (aLayers);
4529       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4530       {
4531         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4532         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4533         {
4534           aLayerId = aLayeriter.Value();
4535           ++anArgIter;
4536           break;
4537         }
4538       }
4539     }
4540   }
4541
4542   for (; anArgIter < theArgNb; ++anArgIter)
4543   {
4544     // perform operation
4545     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4546     anArg.LowerCase();
4547     if (anUpdateTool.parseRedrawMode (anArg))
4548     {
4549       //
4550     }
4551     else if (anArg == "-add"
4552           || anArg == "add")
4553     {
4554       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4555       if (!aViewer->AddZLayer (aLayerId))
4556       {
4557         std::cout << "Error: can not add a new z layer!\n";
4558         return 0;
4559       }
4560
4561       theDI << aLayerId;
4562     }
4563     else if (anArg == "-del"
4564           || anArg == "-delete"
4565           || anArg == "del")
4566     {
4567       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4568       {
4569         if (++anArgIter >= theArgNb)
4570         {
4571           std::cout << "Syntax error: id of z layer to remove is missing\n";
4572           return 1;
4573         }
4574
4575         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4576       }
4577
4578       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4579        || aLayerId == Graphic3d_ZLayerId_Default
4580        || aLayerId == Graphic3d_ZLayerId_Top
4581        || aLayerId == Graphic3d_ZLayerId_Topmost
4582        || aLayerId == Graphic3d_ZLayerId_TopOSD
4583        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4584       {
4585         std::cout << "Syntax error: standard Z layer can not be removed\n";
4586         return 1;
4587       }
4588
4589       // move all object displayed in removing layer to default layer
4590       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4591            anObjIter.More(); anObjIter.Next())
4592       {
4593         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4594         if (aPrs.IsNull()
4595          || aPrs->ZLayer() != aLayerId)
4596         {
4597           continue;
4598         }
4599         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4600       }
4601
4602       if (!aViewer->RemoveZLayer (aLayerId))
4603       {
4604         std::cout << "Z layer can not be removed!\n";
4605       }
4606       else
4607       {
4608         theDI << aLayerId << " ";
4609       }
4610     }
4611     else if (anArg == "-get"
4612           || anArg == "get")
4613     {
4614       TColStd_SequenceOfInteger aLayers;
4615       aViewer->GetAllZLayers (aLayers);
4616       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4617       {
4618         theDI << aLayeriter.Value() << " ";
4619       }
4620
4621       theDI << "\n";
4622     }
4623     else if (anArg == "-name")
4624     {
4625       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4626       {
4627         std::cout << "Syntax error: id of Z layer is missing\n";
4628         return 1;
4629       }
4630
4631       if (++anArgIter >= theArgNb)
4632       {
4633         std::cout << "Syntax error: name is missing\n";
4634         return 1;
4635       }
4636
4637       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4638       aSettings.SetName (theArgVec[anArgIter]);
4639       aViewer->SetZLayerSettings (aLayerId, aSettings);
4640     }
4641     else if (anArg == "-origin")
4642     {
4643       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4644       {
4645         std::cout << "Syntax error: id of Z layer is missing\n";
4646         return 1;
4647       }
4648
4649       if (anArgIter + 2 >= theArgNb)
4650       {
4651         std::cout << "Syntax error: origin coordinates are missing\n";
4652         return 1;
4653       }
4654
4655       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4656       gp_XYZ anOrigin;
4657       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4658       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4659       anOrigin.SetZ (0.0);
4660       if (anArgIter + 3 < theArgNb)
4661       {
4662         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4663         anArgIter += 3;
4664       }
4665       else
4666       {
4667         anArgIter += 2;
4668       }
4669       aSettings.SetOrigin (anOrigin);
4670       aViewer->SetZLayerSettings (aLayerId, aSettings);
4671     }
4672     else if (anArg == "-settings"
4673           || anArg == "settings")
4674     {
4675       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4676       {
4677         if (++anArgIter >= theArgNb)
4678         {
4679           std::cout << "Syntax error: id of Z layer is missing\n";
4680           return 1;
4681         }
4682
4683         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4684       }
4685
4686       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4687       printZLayerInfo (theDI, aSettings);
4688     }
4689     else if (anArg == "-enable"
4690           || anArg == "enable"
4691           || anArg == "-disable"
4692           || anArg == "disable")
4693     {
4694       const Standard_Boolean toEnable = anArg == "-enable"
4695                                      || anArg == "enable";
4696       if (++anArgIter >= theArgNb)
4697       {
4698         std::cout << "Syntax error: option name is missing\n";
4699         return 1;
4700       }
4701
4702       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4703       aSubOp.LowerCase();
4704       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4705       {
4706         if (++anArgIter >= theArgNb)
4707         {
4708           std::cout << "Syntax error: id of Z layer is missing\n";
4709           return 1;
4710         }
4711
4712         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4713       }
4714
4715       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4716       if (aSubOp == "depthtest"
4717        || aSubOp == "test")
4718       {
4719         aSettings.SetEnableDepthTest (toEnable);
4720       }
4721       else if (aSubOp == "depthwrite"
4722             || aSubOp == "write")
4723       {
4724         aSettings.SetEnableDepthWrite (toEnable);
4725       }
4726       else if (aSubOp == "depthclear"
4727             || aSubOp == "clear")
4728       {
4729         aSettings.SetClearDepth (toEnable);
4730       }
4731       else if (aSubOp == "depthoffset"
4732             || aSubOp == "offset")
4733       {
4734         Graphic3d_PolygonOffset aParams;
4735         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4736         if (toEnable)
4737         {
4738           if (anArgIter + 2 >= theArgNb)
4739           {
4740             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4741             return 1;
4742           }
4743
4744           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4745           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4746         }
4747         aSettings.SetPolygonOffset (aParams);
4748       }
4749       else if (aSubOp == "positiveoffset"
4750             || aSubOp == "poffset")
4751       {
4752         if (toEnable)
4753         {
4754           aSettings.SetDepthOffsetPositive();
4755         }
4756         else
4757         {
4758           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4759         }
4760       }
4761       else if (aSubOp == "negativeoffset"
4762             || aSubOp == "noffset")
4763       {
4764         if (toEnable)
4765         {
4766           aSettings.SetDepthOffsetNegative();
4767         }
4768         else
4769         {
4770           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4771         }
4772       }
4773       else if (aSubOp == "textureenv")
4774       {
4775         aSettings.SetEnvironmentTexture (toEnable);
4776       }
4777
4778       aViewer->SetZLayerSettings (aLayerId, aSettings);
4779     }
4780     else
4781     {
4782       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4783       return 1;
4784     }
4785   }
4786
4787   return 0;
4788 }
4789
4790 // The interactive presentation of 2d layer item
4791 // for "vlayerline" command it provides a presentation of
4792 // line with user-defined linewidth, linetype and transparency.
4793 class V3d_LineItem : public AIS_InteractiveObject
4794 {
4795 public:
4796   // CASCADE RTTI
4797   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4798
4799   // constructor
4800   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4801                                Standard_Real X2, Standard_Real Y2,
4802                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4803                                Standard_Real theWidth    = 0.5,
4804                                Standard_Real theTransp   = 1.0);
4805
4806   private:
4807
4808   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4809                 const Handle(Prs3d_Presentation)& thePresentation,
4810                 const Standard_Integer theMode) Standard_OVERRIDE;
4811
4812   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4813                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4814   {}
4815
4816 private:
4817
4818   Standard_Real       myX1, myY1, myX2, myY2;
4819   Aspect_TypeOfLine   myType;
4820   Standard_Real       myWidth;
4821 };
4822
4823 // default constructor for line item
4824 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4825                            Standard_Real X2, Standard_Real Y2,
4826                            Aspect_TypeOfLine theType,
4827                            Standard_Real theWidth,
4828                            Standard_Real theTransp) :
4829   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4830   myType(theType), myWidth(theWidth)
4831 {
4832   SetTransparency (1-theTransp);
4833 }
4834
4835 // render line
4836 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4837                             const Handle(Prs3d_Presentation)& thePresentation,
4838                             const Standard_Integer /*theMode*/)
4839 {
4840   thePresentation->Clear();
4841   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4842   Standard_Integer aWidth, aHeight;
4843   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4844   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4845   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4846   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4847   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4848   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4849   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4850   aGroup->AddPrimitiveArray (aPrim);
4851 }
4852
4853 //=============================================================================
4854 //function : VLayerLine
4855 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4856 //         : linewidth, transparency coefficient
4857 //============================================================================
4858 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4859 {
4860   // get the active view
4861   Handle(V3d_View) aView = ViewerTest::CurrentView();
4862   if (aView.IsNull())
4863   {
4864     di << "Call vinit before!\n";
4865     return 1;
4866   }
4867   else if (argc < 5)
4868   {
4869     di << "Use: " << argv[0];
4870     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4871     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4872     di << "              0 - solid  \n";
4873     di << "              1 - dashed \n";
4874     di << "              2 - dot    \n";
4875     di << "              3 - dashdot\n";
4876     di << " transparency : { 0.0 - 1.0 } \n";
4877     di << "                  0.0 - transparent\n";
4878     di << "                  1.0 - visible    \n";
4879     return 1;
4880   }
4881
4882   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4883   // get the input params
4884   Standard_Real X1 = Draw::Atof(argv[1]);
4885   Standard_Real Y1 = Draw::Atof(argv[2]);
4886   Standard_Real X2 = Draw::Atof(argv[3]);
4887   Standard_Real Y2 = Draw::Atof(argv[4]);
4888
4889   Standard_Real aWidth = 0.5;
4890   Standard_Real aTransparency = 1.0;
4891
4892   // has width
4893   if (argc > 5)
4894     aWidth = Draw::Atof(argv[5]);
4895
4896   // select appropriate line type
4897   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
4898   if (argc > 6
4899   && !ViewerTest::ParseLineType (argv[6], aLineType))
4900   {
4901     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
4902     return 1;
4903   }
4904
4905   // has transparency
4906   if (argc > 7)
4907   {
4908     aTransparency = Draw::Atof(argv[7]);
4909     if (aTransparency < 0 || aTransparency > 1.0)
4910       aTransparency = 1.0;
4911   }
4912
4913   static Handle (V3d_LineItem) aLine;
4914   if (!aLine.IsNull())
4915   {
4916     aContext->Erase (aLine);
4917   }
4918   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4919                             aLineType, aWidth,
4920                             aTransparency);
4921
4922   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4923   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4924   aLine->SetToUpdate();
4925   aContext->Display (aLine, Standard_True);
4926
4927   return 0;
4928 }
4929
4930
4931 //==============================================================================
4932 //function : VGrid
4933 //purpose  :
4934 //==============================================================================
4935
4936 static int VGrid (Draw_Interpretor& /*theDI*/,
4937                   Standard_Integer  theArgNb,
4938                   const char**      theArgVec)
4939 {
4940   // get the active view
4941   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4942   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4943   if (aView.IsNull() || aViewer.IsNull())
4944   {
4945     std::cerr << "No active view. Please call vinit.\n";
4946     return 1;
4947   }
4948
4949   Aspect_GridType     aType = aViewer->GridType();
4950   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4951
4952   Standard_Integer anIter = 1;
4953   for (; anIter < theArgNb; ++anIter)
4954   {
4955     const char* aValue = theArgVec[anIter];
4956     if (*aValue == 'r')
4957     {
4958       aType = Aspect_GT_Rectangular;
4959     }
4960     else if (*aValue == 'c')
4961     {
4962       aType = Aspect_GT_Circular;
4963     }
4964     else if (*aValue == 'l')
4965     {
4966       aMode = Aspect_GDM_Lines;
4967     }
4968     else if (*aValue == 'p')
4969     {
4970       aMode = Aspect_GDM_Points;
4971     }
4972     else if (strcmp (aValue, "off" ) == 0)
4973     {
4974       aViewer->DeactivateGrid();
4975       return 0;
4976     }
4977     else
4978     {
4979       break;
4980     }
4981   }
4982
4983   Standard_Integer aTail = (theArgNb - anIter);
4984   if (aTail == 0)
4985   {
4986     aViewer->ActivateGrid (aType, aMode);
4987     return 0;
4988   }
4989   else if (aTail != 2 && aTail != 5)
4990   {
4991     std::cerr << "Incorrect arguments number! Usage:\n"
4992               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
4993     return 1;
4994   }
4995
4996   Quantity_Length anOriginX, anOriginY;
4997   Quantity_PlaneAngle aRotAngle;
4998   if (aType == Aspect_GT_Rectangular)
4999   {
5000     Quantity_Length aRStepX, aRStepY;
5001     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5002
5003     anOriginX = Draw::Atof (theArgVec[anIter++]);
5004     anOriginY = Draw::Atof (theArgVec[anIter++]);
5005     if (aTail == 5)
5006     {
5007       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5008       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5009       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5010     }
5011     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5012     aViewer->ActivateGrid (aType, aMode);
5013   }
5014   else if (aType == Aspect_GT_Circular)
5015   {
5016     Quantity_Length aRadiusStep;
5017     Standard_Integer aDivisionNumber;
5018     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5019
5020     anOriginX = Draw::Atof (theArgVec[anIter++]);
5021     anOriginY = Draw::Atof (theArgVec[anIter++]);
5022     if (aTail == 5)
5023     {
5024       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5025       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5026       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5027     }
5028
5029     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5030     aViewer->ActivateGrid (aType, aMode);
5031   }
5032
5033   return 0;
5034 }
5035
5036 //==============================================================================
5037 //function : VPriviledgedPlane
5038 //purpose  :
5039 //==============================================================================
5040
5041 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5042                               Standard_Integer  theArgNb,
5043                               const char**      theArgVec)
5044 {
5045   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5046   {
5047     std::cerr << "Error: wrong number of arguments! See usage:\n";
5048     theDI.PrintHelp (theArgVec[0]);
5049     return 1;
5050   }
5051
5052   // get the active viewer
5053   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5054   if (aViewer.IsNull())
5055   {
5056     std::cerr << "Error: no active viewer. Please call vinit.\n";
5057     return 1;
5058   }
5059
5060   if (theArgNb == 1)
5061   {
5062     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5063     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5064     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5065     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5066     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5067           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5068           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5069     return 0;
5070   }
5071
5072   Standard_Integer anArgIdx = 1;
5073   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5074   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5075   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5076   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5077   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5078   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5079
5080   gp_Ax3 aPriviledgedPlane;
5081   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5082   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5083   if (theArgNb > 7)
5084   {
5085     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5086     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5087     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5088     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5089     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5090   }
5091   else
5092   {
5093     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5094   }
5095
5096   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5097
5098   return 0;
5099 }
5100
5101 //==============================================================================
5102 //function : VConvert
5103 //purpose  :
5104 //==============================================================================
5105
5106 static int VConvert (Draw_Interpretor& theDI,
5107                      Standard_Integer  theArgNb,
5108                      const char**      theArgVec)
5109 {
5110   // get the active view
5111   Handle(V3d_View) aView = ViewerTest::CurrentView();
5112   if (aView.IsNull())
5113   {
5114     std::cerr << "Error: no active view. Please call vinit.\n";
5115     return 1;
5116   }
5117
5118   enum { Model, Ray, View, Window, Grid } aMode = Model;
5119
5120   // access coordinate arguments
5121   TColStd_SequenceOfReal aCoord;
5122   Standard_Integer anArgIdx = 1;
5123   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5124   {
5125     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5126     if (!anArg.IsRealValue())
5127     {
5128       break;
5129     }
5130     aCoord.Append (anArg.RealValue());
5131   }
5132
5133   // non-numeric argument too early
5134   if (aCoord.IsEmpty())
5135   {
5136     std::cerr << "Error: wrong number of arguments! See usage:\n";
5137     theDI.PrintHelp (theArgVec[0]);
5138     return 1;
5139   }
5140
5141   // collect all other arguments and options
5142   for (; anArgIdx < theArgNb; ++anArgIdx)
5143   {
5144     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5145     anArg.LowerCase();
5146     if      (anArg == "window") aMode = Window;
5147     else if (anArg == "view")   aMode = View;
5148     else if (anArg == "grid")   aMode = Grid;
5149     else if (anArg == "ray")    aMode = Ray;
5150     else
5151     {
5152       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5153       theDI.PrintHelp (theArgVec[0]);
5154       return 1;
5155     }
5156   }
5157
5158   // complete input checks
5159   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5160       (aCoord.Length() == 2 && theArgNb > 4) ||
5161       (aCoord.Length() == 3 && theArgNb > 5))
5162   {
5163     std::cerr << "Error: wrong number of arguments! See usage:\n";
5164     theDI.PrintHelp (theArgVec[0]);
5165     return 1;
5166   }
5167
5168   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5169   Standard_Integer aXYp[2] = {0, 0};
5170
5171   // convert one-dimensional coordinate
5172   if (aCoord.Length() == 1)
5173   {
5174     switch (aMode)
5175     {
5176       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
5177       case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
5178       default:
5179         std::cerr << "Error: wrong arguments! See usage:\n";
5180         theDI.PrintHelp (theArgVec[0]);
5181         return 1;
5182     }
5183   }
5184
5185   // convert 2D coordinates from projection or view reference space
5186   if (aCoord.Length() == 2)
5187   {
5188     switch (aMode)
5189     {
5190       case Model :
5191         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5192         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5193         return 0;
5194
5195       case View :
5196         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5197         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5198         return 0;
5199
5200       case Window :
5201         aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
5202         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5203         return 0;
5204
5205       case Grid :
5206         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5207         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5208         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5209         return 0;
5210
5211       case Ray :
5212         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5213                                 (Standard_Integer) aCoord (2),
5214                                 aXYZ[0], aXYZ[1], aXYZ[2],
5215                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5216         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5217         return 0;
5218
5219       default:
5220         std::cerr << "Error: wrong arguments! See usage:\n";
5221         theDI.PrintHelp (theArgVec[0]);
5222         return 1;
5223     }
5224   }
5225
5226   // convert 3D coordinates from view reference space
5227   else if (aCoord.Length() == 3)
5228   {
5229     switch (aMode)
5230     {
5231       case Window :
5232         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5233         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5234         return 0;
5235
5236       case Grid :
5237         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5238         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5239         return 0;
5240
5241       default:
5242         std::cerr << "Error: wrong arguments! See usage:\n";
5243         theDI.PrintHelp (theArgVec[0]);
5244         return 1;
5245     }
5246   }
5247
5248   return 0;
5249 }
5250
5251 //==============================================================================
5252 //function : VFps
5253 //purpose  :
5254 //==============================================================================
5255
5256 static int VFps (Draw_Interpretor& theDI,
5257                  Standard_Integer  theArgNb,
5258                  const char**      theArgVec)
5259 {
5260   // get the active view
5261   Handle(V3d_View) aView = ViewerTest::CurrentView();
5262   if (aView.IsNull())
5263   {
5264     std::cerr << "No active view. Please call vinit.\n";
5265     return 1;
5266   }
5267
5268   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5269   if (aFramesNb <= 0)
5270   {
5271     std::cerr << "Incorrect arguments!\n";
5272     return 1;
5273   }
5274
5275   // the time is meaningless for first call
5276   // due to async OpenGl rendering
5277   aView->Redraw();
5278
5279   // redraw view in loop to estimate average values
5280   OSD_Timer aTimer;
5281   aTimer.Start();
5282   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5283   {
5284     aView->Redraw();
5285   }
5286   aTimer.Stop();
5287   Standard_Real aCpu;
5288   const Standard_Real aTime = aTimer.ElapsedTime();
5289   aTimer.OSD_Chronometer::Show (aCpu);
5290
5291   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5292   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5293
5294   // return statistics
5295   theDI << "FPS: " << aFpsAver << "\n"
5296         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5297
5298   // compute additional statistics in ray-tracing mode
5299   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5300
5301   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5302   {
5303     Standard_Integer aSizeX;
5304     Standard_Integer aSizeY;
5305
5306     aView->Window()->Size (aSizeX, aSizeY);
5307
5308     // 1 shadow ray and 1 secondary ray pew each bounce
5309     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5310
5311     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5312   }
5313
5314   return 0;
5315 }
5316
5317 //==============================================================================
5318 //function : VGlDebug
5319 //purpose  :
5320 //==============================================================================
5321
5322 static int VGlDebug (Draw_Interpretor& theDI,
5323                      Standard_Integer  theArgNb,
5324                      const char**      theArgVec)
5325 {
5326   Handle(OpenGl_GraphicDriver) aDriver;
5327   Handle(V3d_View) aView = ViewerTest::CurrentView();
5328   if (!aView.IsNull())
5329   {
5330     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5331   }
5332   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5333   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5334
5335   if (theArgNb < 2)
5336   {
5337     TCollection_AsciiString aDebActive, aSyncActive;
5338     if (aCaps == NULL)
5339     {
5340       aCaps = aDefCaps;
5341     }
5342     else
5343     {
5344       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5345                                                                   "GL_ARB_debug_output");
5346       aDebActive = isActive ? " (active)" : " (inactive)";
5347       if (isActive)
5348       {
5349         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5350         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5351       }
5352     }
5353
5354     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5355           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5356           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5357           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5358     return 0;
5359   }
5360
5361   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5362   {
5363     Standard_CString        anArg     = theArgVec[anArgIter];
5364     TCollection_AsciiString anArgCase (anArg);
5365     anArgCase.LowerCase();
5366     Standard_Boolean toEnableDebug = Standard_True;
5367     if (anArgCase == "-glsl"
5368      || anArgCase == "-glslwarn"
5369      || anArgCase == "-glslwarns"
5370      || anArgCase == "-glslwarnings")
5371     {
5372       Standard_Boolean toShowWarns = Standard_True;
5373       if (++anArgIter < theArgNb
5374       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5375       {
5376         --anArgIter;
5377       }
5378       aDefCaps->glslWarnings = toShowWarns;
5379       if (aCaps != NULL)
5380       {
5381         aCaps->glslWarnings = toShowWarns;
5382       }
5383     }
5384     else if (anArgCase == "-extra"
5385           || anArgCase == "-extramsg"
5386           || anArgCase == "-extramessages")
5387     {
5388       Standard_Boolean toShow = Standard_True;
5389       if (++anArgIter < theArgNb
5390       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5391       {
5392         --anArgIter;
5393       }
5394       aDefCaps->suppressExtraMsg = !toShow;
5395       if (aCaps != NULL)
5396       {
5397         aCaps->suppressExtraMsg = !toShow;
5398       }
5399     }
5400     else if (anArgCase == "-noextra"
5401           || anArgCase == "-noextramsg"
5402           || anArgCase == "-noextramessages")
5403     {
5404       Standard_Boolean toSuppress = Standard_True;
5405       if (++anArgIter < theArgNb
5406       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5407       {
5408         --anArgIter;
5409       }
5410       aDefCaps->suppressExtraMsg = toSuppress;
5411       if (aCaps != NULL)
5412       {
5413         aCaps->suppressExtraMsg = toSuppress;
5414       }
5415     }
5416     else if (anArgCase == "-sync")
5417     {
5418       Standard_Boolean toSync = Standard_True;
5419       if (++anArgIter < theArgNb
5420       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5421       {
5422         --anArgIter;
5423       }
5424       aDefCaps->contextSyncDebug = toSync;
5425       if (toSync)
5426       {
5427         aDefCaps->contextDebug = Standard_True;
5428       }
5429     }
5430     else if (anArgCase == "-debug")
5431     {
5432       if (++anArgIter < theArgNb
5433       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5434       {
5435         --anArgIter;
5436       }
5437       aDefCaps->contextDebug = toEnableDebug;
5438     }
5439     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5440           && (anArgIter + 1 == theArgNb))
5441     {
5442       // simple alias to turn on almost everything
5443       aDefCaps->contextDebug     = toEnableDebug;
5444       aDefCaps->contextSyncDebug = toEnableDebug;
5445       aDefCaps->glslWarnings     = toEnableDebug;
5446     }
5447     else
5448     {
5449       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5450       return 1;
5451     }
5452   }
5453
5454   return 0;
5455 }
5456
5457 //==============================================================================
5458 //function : VVbo
5459 //purpose  :
5460 //==============================================================================
5461
5462 static int VVbo (Draw_Interpretor& theDI,
5463                  Standard_Integer  theArgNb,
5464                  const char**      theArgVec)
5465 {
5466   const Standard_Boolean toSet    = (theArgNb > 1);
5467   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5468   if (toSet)
5469   {
5470     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5471   }
5472
5473   // get the context
5474   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5475   if (aContextAIS.IsNull())
5476   {
5477     if (!toSet)
5478     {
5479       std::cerr << "No active view!\n";
5480     }
5481     return 1;
5482   }
5483   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5484   if (!aDriver.IsNull())
5485   {
5486     if (!toSet)
5487     {
5488       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5489     }
5490     else
5491     {
5492       aDriver->ChangeOptions().vboDisable = toUseVbo;
5493     }
5494   }
5495
5496   return 0;
5497 }
5498
5499 //==============================================================================
5500 //function : VCaps
5501 //purpose  :
5502 //==============================================================================
5503
5504 static int VCaps (Draw_Interpretor& theDI,
5505                   Standard_Integer  theArgNb,
5506                   const char**      theArgVec)
5507 {
5508   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5509   Handle(OpenGl_GraphicDriver)   aDriver;
5510   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5511   if (!aContext.IsNull())
5512   {
5513     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5514     aCaps   = &aDriver->ChangeOptions();
5515   }
5516
5517   if (theArgNb < 2)
5518   {
5519     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5520     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5521     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5522     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5523     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5524     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5525     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5526     return 0;
5527   }
5528
5529   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5530   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5531   {
5532     Standard_CString        anArg     = theArgVec[anArgIter];
5533     TCollection_AsciiString anArgCase (anArg);
5534     anArgCase.LowerCase();
5535     if (anUpdateTool.parseRedrawMode (anArg))
5536     {
5537       continue;
5538     }
5539     else if (anArgCase == "-vsync"
5540           || anArgCase == "-swapinterval")
5541     {
5542       Standard_Boolean toEnable = Standard_True;
5543       if (++anArgIter < theArgNb
5544       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5545       {
5546         --anArgIter;
5547       }
5548       aCaps->swapInterval = toEnable;
5549     }
5550     else if (anArgCase == "-ffp")
5551     {
5552       Standard_Boolean toEnable = Standard_True;
5553       if (++anArgIter < theArgNb
5554       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5555       {
5556         --anArgIter;
5557       }
5558       aCaps->ffpEnable = toEnable;
5559     }
5560     else if (anArgCase == "-vbo")
5561     {
5562       Standard_Boolean toEnable = Standard_True;
5563       if (++anArgIter < theArgNb
5564       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5565       {
5566         --anArgIter;
5567       }
5568       aCaps->vboDisable = !toEnable;
5569     }
5570     else if (anArgCase == "-sprite"
5571           || anArgCase == "-sprites")
5572     {
5573       Standard_Boolean toEnable = Standard_True;
5574       if (++anArgIter < theArgNb
5575       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5576       {
5577         --anArgIter;
5578       }
5579       aCaps->pntSpritesDisable = !toEnable;
5580     }
5581     else if (anArgCase == "-softmode")
5582     {
5583       Standard_Boolean toEnable = Standard_True;
5584       if (++anArgIter < theArgNb
5585       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5586       {
5587         --anArgIter;
5588       }
5589       aCaps->contextNoAccel = toEnable;
5590     }
5591     else if (anArgCase == "-accel"
5592           || anArgCase == "-acceleration")
5593     {
5594       Standard_Boolean toEnable = Standard_True;
5595       if (++anArgIter < theArgNb
5596       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5597       {
5598         --anArgIter;
5599       }
5600       aCaps->contextNoAccel = !toEnable;
5601     }
5602     else if (anArgCase == "-compat"
5603           || anArgCase == "-compatprofile"
5604           || anArgCase == "-compatible"
5605           || anArgCase == "-compatibleprofile")
5606     {
5607       Standard_Boolean toEnable = Standard_True;
5608       if (++anArgIter < theArgNb
5609       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5610       {
5611         --anArgIter;
5612       }
5613       aCaps->contextCompatible = toEnable;
5614       if (!aCaps->contextCompatible)
5615       {
5616         aCaps->ffpEnable = Standard_False;
5617       }
5618     }
5619     else if (anArgCase == "-core"
5620           || anArgCase == "-coreprofile")
5621     {
5622       Standard_Boolean toEnable = Standard_True;
5623       if (++anArgIter < theArgNb
5624       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5625       {
5626         --anArgIter;
5627       }
5628       aCaps->contextCompatible = !toEnable;
5629       if (!aCaps->contextCompatible)
5630       {
5631         aCaps->ffpEnable = Standard_False;
5632       }
5633     }
5634     else if (anArgCase == "-stereo"
5635           || anArgCase == "-quadbuffer")
5636     {
5637       Standard_Boolean toEnable = Standard_True;
5638       if (++anArgIter < theArgNb
5639       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5640       {
5641         --anArgIter;
5642       }
5643       aCaps->contextStereo = toEnable;
5644     }
5645     else
5646     {
5647       std::cout << "Error: unknown argument '" << anArg << "'\n";
5648       return 1;
5649     }
5650   }
5651   if (aCaps != &ViewerTest_myDefaultCaps)
5652   {
5653     ViewerTest_myDefaultCaps = *aCaps;
5654   }
5655   return 0;
5656 }
5657
5658 //==============================================================================
5659 //function : VMemGpu
5660 //purpose  :
5661 //==============================================================================
5662
5663 static int VMemGpu (Draw_Interpretor& theDI,
5664                     Standard_Integer  theArgNb,
5665                     const char**      theArgVec)
5666 {
5667   // get the context
5668   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5669   if (aContextAIS.IsNull())
5670   {
5671     std::cerr << "No active view. Please call vinit.\n";
5672     return 1;
5673   }
5674
5675   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5676   if (aDriver.IsNull())
5677   {
5678     std::cerr << "Graphic driver not available.\n";
5679     return 1;
5680   }
5681
5682   Standard_Size aFreeBytes = 0;
5683   TCollection_AsciiString anInfo;
5684   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5685   {
5686     std::cerr << "Information not available.\n";
5687     return 1;
5688   }
5689
5690   if (theArgNb > 1 && *theArgVec[1] == 'f')
5691   {
5692     theDI << Standard_Real (aFreeBytes);
5693   }
5694   else
5695   {
5696     theDI << anInfo;
5697   }
5698
5699   return 0;
5700 }
5701
5702 // ==============================================================================
5703 // function : VReadPixel
5704 // purpose  :
5705 // ==============================================================================
5706 static int VReadPixel (Draw_Interpretor& theDI,
5707                        Standard_Integer  theArgNb,
5708                        const char**      theArgVec)
5709 {
5710   // get the active view
5711   Handle(V3d_View) aView = ViewerTest::CurrentView();
5712   if (aView.IsNull())
5713   {
5714     std::cerr << "No active view. Please call vinit.\n";
5715     return 1;
5716   }
5717   else if (theArgNb < 3)
5718   {
5719     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5720     return 1;
5721   }
5722
5723   Image_PixMap::ImgFormat aFormat     = Image_PixMap::ImgRGBA;
5724   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
5725
5726   Standard_Integer aWidth, aHeight;
5727   aView->Window()->Size (aWidth, aHeight);
5728   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5729   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5730   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5731   {
5732     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5733     return 1;
5734   }
5735
5736   Standard_Boolean toShowName = Standard_False;
5737   Standard_Boolean toShowHls  = Standard_False;
5738   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5739   {
5740     const char* aParam = theArgVec[anIter];
5741     if ( strcasecmp( aParam, "rgb" ) == 0 )
5742     {
5743       aFormat     = Image_PixMap::ImgRGB;
5744       aBufferType = Graphic3d_BT_RGB;
5745     }
5746     else if ( strcasecmp( aParam, "hls" ) == 0 )
5747     {
5748       aFormat     = Image_PixMap::ImgRGB;
5749       aBufferType = Graphic3d_BT_RGB;
5750       toShowHls   = Standard_True;
5751     }
5752     else if ( strcasecmp( aParam, "rgbf" ) == 0 )
5753     {
5754       aFormat     = Image_PixMap::ImgRGBF;
5755       aBufferType = Graphic3d_BT_RGB;
5756     }
5757     else if ( strcasecmp( aParam, "rgba" ) == 0 )
5758     {
5759       aFormat     = Image_PixMap::ImgRGBA;
5760       aBufferType = Graphic3d_BT_RGBA;
5761     }
5762     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
5763     {
5764       aFormat     = Image_PixMap::ImgRGBAF;
5765       aBufferType = Graphic3d_BT_RGBA;
5766     }
5767     else if ( strcasecmp( aParam, "depth" ) == 0 )
5768     {
5769       aFormat     = Image_PixMap::ImgGrayF;
5770       aBufferType = Graphic3d_BT_Depth;
5771     }
5772     else if ( strcasecmp( aParam, "name" ) == 0 )
5773     {
5774       toShowName = Standard_True;
5775     }
5776   }
5777
5778   Image_PixMap anImage;
5779   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5780   {
5781     std::cerr << "Image allocation failed\n";
5782     return 1;
5783   }
5784   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5785   {
5786     std::cerr << "Image dump failed\n";
5787     return 1;
5788   }
5789
5790   Quantity_Parameter anAlpha;
5791   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5792   if (toShowName)
5793   {
5794     if (aBufferType == Graphic3d_BT_RGBA)
5795     {
5796       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5797     }
5798     else
5799     {
5800       theDI << Quantity_Color::StringName (aColor.Name());
5801     }
5802   }
5803   else
5804   {
5805     switch (aBufferType)
5806     {
5807       default:
5808       case Graphic3d_BT_RGB:
5809       {
5810         if (toShowHls)
5811         {
5812           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5813         }
5814         else
5815         {
5816           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5817         }
5818         break;
5819       }
5820       case Graphic3d_BT_RGBA:
5821       {
5822         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5823         break;
5824       }
5825       case Graphic3d_BT_Depth:
5826       {
5827         theDI << aColor.Red();
5828         break;
5829       }
5830     }
5831   }
5832
5833   return 0;
5834 }
5835
5836 //==============================================================================
5837 //function : VDiffImage
5838 //purpose  : The draw-command compares two images.
5839 //==============================================================================
5840
5841 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5842 {
5843   if (theArgNb < 6)
5844   {
5845     theDI << "Not enough arguments.\n";
5846     return 1;
5847   }
5848
5849   // image file names
5850   const char* anImgPathRef = theArgVec[1];
5851   const char* anImgPathNew = theArgVec[2];
5852
5853   // get string tolerance and check its validity
5854   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5855   if (aTolColor < 0.0)
5856     aTolColor = 0.0;
5857   if (aTolColor > 1.0)
5858     aTolColor = 1.0;
5859
5860   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5861   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5862
5863   // image file of difference
5864   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5865
5866   // compare the images
5867   Image_Diff aComparer;
5868   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5869   {
5870     return 1;
5871   }
5872
5873   aComparer.SetColorTolerance (aTolColor);
5874   aComparer.SetBorderFilterOn (isBorderFilterOn);
5875   Standard_Integer aDiffColorsNb = aComparer.Compare();
5876   theDI << aDiffColorsNb << "\n";
5877
5878   // save image of difference
5879   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5880   {
5881     aComparer.SaveDiffImage (aDiffImagePath);
5882   }
5883
5884   return 0;
5885 }
5886
5887 //=======================================================================
5888 //function : VSelect
5889 //purpose  : Emulates different types of selection by mouse:
5890 //           1) single click selection
5891 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5892 //           3) selection with polygon having corners at
5893 //           pixel positions (x1,y1),...,(xn,yn)
5894 //           4) any of these selections with shift button pressed
5895 //=======================================================================
5896 static Standard_Integer VSelect (Draw_Interpretor& di,
5897                                  Standard_Integer argc,
5898                                  const char ** argv)
5899 {
5900   if(argc < 3)
5901   {
5902     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5903     return 1;
5904   }
5905
5906   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5907   if(myAIScontext.IsNull())
5908   {
5909     di << "use 'vinit' command before " << argv[0] << "\n";
5910     return 1;
5911   }
5912
5913   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5914   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5915   TCollection_AsciiString anArg;
5916   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5917   anArg.LowerCase();
5918   if (anArg == "-allowoverlap")
5919   {
5920     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5921       : argc == 7;
5922     if (!isValidated)
5923     {
5924       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5925       return 1;
5926     }
5927
5928     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5929     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5930     aCoordsNb -= 2;
5931   }
5932
5933   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5934   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5935   if(aCoordsNb == 2)
5936   {
5937     if(isShiftSelection)
5938       aCurrentEventManager->ShiftSelect();
5939     else
5940       aCurrentEventManager->Select();
5941   }
5942   else if(aCoordsNb == 4)
5943   {
5944     if(isShiftSelection)
5945       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5946     else
5947       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5948   }
5949   else
5950   {
5951     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
5952
5953     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
5954       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
5955
5956     if(isShiftSelection)
5957       aCurrentEventManager->ShiftSelect(aPolyline);
5958     else
5959       aCurrentEventManager->Select(aPolyline);
5960   }
5961   return 0;
5962 }
5963
5964 //=======================================================================
5965 //function : VMoveTo
5966 //purpose  : Emulates cursor movement to defined pixel position
5967 //=======================================================================
5968 static Standard_Integer VMoveTo (Draw_Interpretor& di,
5969                                 Standard_Integer argc,
5970                                 const char ** argv)
5971 {
5972   if(argc != 3)
5973   {
5974     di << "Usage : " << argv[0] << " x y\n";
5975     return 1;
5976   }
5977
5978   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5979   if(aContext.IsNull())
5980   {
5981     di << "use 'vinit' command before " << argv[0] << "\n";
5982     return 1;
5983   }
5984   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
5985   return 0;
5986 }
5987
5988 namespace
5989 {
5990   //! Global map storing all animations registered in ViewerTest.
5991   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
5992
5993   //! The animation calling the Draw Harness command.
5994   class ViewerTest_AnimationProc : public AIS_Animation
5995   {
5996   public:
5997
5998     //! Main constructor.
5999     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6000                               Draw_Interpretor* theDI,
6001                               const TCollection_AsciiString& theCommand)
6002     : AIS_Animation (theAnimationName),
6003       myDrawInter(theDI),
6004       myCommand  (theCommand)
6005     {
6006       //
6007     }
6008
6009   protected:
6010
6011     //! Evaluate the command.
6012     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6013     {
6014       TCollection_AsciiString aCmd = myCommand;
6015       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6016       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6017       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6018       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6019       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6020       myDrawInter->Eval (aCmd.ToCString());
6021     }
6022
6023     //! Find the keyword in the command and replace it with value.
6024     //! @return the position of the keyword to pass value
6025     void replace (TCollection_AsciiString&       theCmd,
6026                   const TCollection_AsciiString& theKey,
6027                   const TCollection_AsciiString& theVal)
6028     {
6029       TCollection_AsciiString aCmd (theCmd);
6030       aCmd.LowerCase();
6031       const Standard_Integer aPos = aCmd.Search (theKey);
6032       if (aPos == -1)
6033       {
6034         return;
6035       }
6036
6037       TCollection_AsciiString aPart1, aPart2;
6038       Standard_Integer aPart1To = aPos - 1;
6039       if (aPart1To >= 1
6040        && aPart1To <= theCmd.Length())
6041       {
6042         aPart1 = theCmd.SubString (1, aPart1To);
6043       }
6044
6045       Standard_Integer aPart2From = aPos + theKey.Length();
6046       if (aPart2From >= 1
6047        && aPart2From <= theCmd.Length())
6048       {
6049         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6050       }
6051
6052       theCmd = aPart1 + theVal + aPart2;
6053     }
6054
6055   protected:
6056
6057     Draw_Interpretor*       myDrawInter;
6058     TCollection_AsciiString myCommand;
6059
6060   };
6061
6062   //! Replace the animation with the new one.
6063   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6064                                 Handle(AIS_Animation)&       theAnimation,
6065                                 const Handle(AIS_Animation)& theAnimationNew)
6066   {
6067     theAnimationNew->CopyFrom (theAnimation);
6068     if (!theParentAnimation.IsNull())
6069     {
6070       theParentAnimation->Replace (theAnimation, theAnimationNew);
6071     }
6072     else
6073     {
6074       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6075       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6076     }
6077     theAnimation = theAnimationNew;
6078   }
6079
6080   //! Parse the point.
6081   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6082   {
6083     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6084     if (!anXYZ[0].IsRealValue()
6085      || !anXYZ[1].IsRealValue()
6086      || !anXYZ[2].IsRealValue())
6087     {
6088       return Standard_False;
6089     }
6090
6091     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6092     return Standard_True;
6093   }
6094
6095   //! Parse the quaternion.
6096   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6097   {
6098     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6099     if (!anXYZW[0].IsRealValue()
6100      || !anXYZW[1].IsRealValue()
6101      || !anXYZW[2].IsRealValue()
6102      || !anXYZW[3].IsRealValue())
6103     {
6104       return Standard_False;
6105     }
6106
6107     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6108     return Standard_True;
6109   }
6110
6111 }
6112
6113 //=================================================================================================
6114 //function : VViewParams
6115 //purpose  : Gets or sets AIS View characteristics
6116 //=================================================================================================
6117 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6118 {
6119   Handle(V3d_View) aView = ViewerTest::CurrentView();
6120   if (aView.IsNull())
6121   {
6122     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6123     return 1;
6124   }
6125
6126   Standard_Boolean toSetProj     = Standard_False;
6127   Standard_Boolean toSetUp       = Standard_False;
6128   Standard_Boolean toSetAt       = Standard_False;
6129   Standard_Boolean toSetEye      = Standard_False;
6130   Standard_Boolean toSetScale    = Standard_False;
6131   Standard_Boolean toSetSize     = Standard_False;
6132   Standard_Boolean toSetCenter2d = Standard_False;
6133   Quantity_Factor  aViewScale = aView->Scale();
6134   Quantity_Length  aViewSize  = 1.0;
6135   Graphic3d_Vec2i  aCenter2d;
6136   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6137   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6138   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6139   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6140   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6141   if (theArgsNb == 1)
6142   {
6143     // print all of the available view parameters
6144     char aText[4096];
6145     Sprintf (aText,
6146              "Scale: %g\n"
6147              "Proj:  %12g %12g %12g\n"
6148              "Up:    %12g %12g %12g\n"
6149              "At:    %12g %12g %12g\n"
6150              "Eye:   %12g %12g %12g\n",
6151               aViewScale,
6152               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6153               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6154               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6155               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6156     theDi << aText;
6157     return 0;
6158   }
6159
6160   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6161   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6162   {
6163     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6164     anArg.LowerCase();
6165     if (anUpdateTool.parseRedrawMode (anArg))
6166     {
6167       continue;
6168     }
6169     else if (anArg == "-cmd"
6170           || anArg == "-command"
6171           || anArg == "-args")
6172     {
6173       char aText[4096];
6174       Sprintf (aText,
6175                "-scale %g "
6176                "-proj %g %g %g "
6177                "-up %g %g %g "
6178                "-at %g %g %g\n",
6179                 aViewScale,
6180                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6181                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6182                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6183       theDi << aText;
6184     }
6185     else if (anArg == "-scale"
6186           || anArg == "-size")
6187     {
6188       if (anArgIter + 1 < theArgsNb
6189        && *theArgVec[anArgIter + 1] != '-')
6190       {
6191         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6192         if (aValueArg.IsRealValue())
6193         {
6194           ++anArgIter;
6195           if (anArg == "-scale")
6196           {
6197             toSetScale = Standard_True;
6198             aViewScale = aValueArg.RealValue();
6199           }
6200           else if (anArg == "-size")
6201           {
6202             toSetSize = Standard_True;
6203             aViewSize = aValueArg.RealValue();
6204           }
6205           continue;
6206         }
6207       }
6208       if (anArg == "-scale")
6209       {
6210         theDi << "Scale: " << aView->Scale() << "\n";
6211       }
6212       else if (anArg == "-size")
6213       {
6214         Graphic3d_Vec2d aSizeXY;
6215         aView->Size (aSizeXY.x(), aSizeXY.y());
6216         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6217       }
6218     }
6219     else if (anArg == "-eye"
6220           || anArg == "-at"
6221           || anArg == "-up"
6222           || anArg == "-proj")
6223     {
6224       if (anArgIter + 3 < theArgsNb)
6225       {
6226         gp_XYZ anXYZ;
6227         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6228         {
6229           anArgIter += 3;
6230           if (anArg == "-eye")
6231           {
6232             toSetEye = Standard_True;
6233             aViewEye = anXYZ;
6234           }
6235           else if (anArg == "-at")
6236           {
6237             toSetAt = Standard_True;
6238             aViewAt = anXYZ;
6239           }
6240           else if (anArg == "-up")
6241           {
6242             toSetUp = Standard_True;
6243             aViewUp = anXYZ;
6244           }
6245           else if (anArg == "-proj")
6246           {
6247             toSetProj = Standard_True;
6248             aViewProj = anXYZ;
6249           }
6250           continue;
6251         }
6252       }
6253
6254       if (anArg == "-eye")
6255       {
6256         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6257       }
6258       else if (anArg == "-at")
6259       {
6260         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6261       }
6262       else if (anArg == "-up")
6263       {
6264         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6265       }
6266       else if (anArg == "-proj")
6267       {
6268         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6269       }
6270     }
6271     else if (anArg == "-center")
6272     {
6273       if (anArgIter + 2 < theArgsNb)
6274       {
6275         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6276         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6277         if (anX.IsIntegerValue()
6278          && anY.IsIntegerValue())
6279         {
6280           toSetCenter2d = Standard_True;
6281           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6282         }
6283       }
6284     }
6285     else
6286     {
6287       std::cout << "Syntax error at '" << anArg << "'\n";
6288       return 1;
6289     }
6290   }
6291
6292   // change view parameters in proper order
6293   if (toSetScale)
6294   {
6295     aView->SetScale (aViewScale);
6296   }
6297   if (toSetSize)
6298   {
6299     aView->SetSize (aViewSize);
6300   }
6301   if (toSetEye)
6302   {
6303     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6304   }
6305   if (toSetAt)
6306   {
6307     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6308   }
6309   if (toSetProj)
6310   {
6311     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6312   }
6313   if (toSetUp)
6314   {
6315     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6316   }
6317   if (toSetCenter2d)
6318   {
6319     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6320   }
6321
6322   return 0;
6323 }
6324
6325 //==============================================================================
6326 //function : VAnimation
6327 //purpose  :
6328 //==============================================================================
6329 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6330                                     Standard_Integer  theArgNb,
6331                                     const char**      theArgVec)
6332 {
6333   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6334   if (theArgNb < 2)
6335   {
6336     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6337          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6338     {
6339       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6340     }
6341     return 0;
6342   }
6343   if (aCtx.IsNull())
6344   {
6345     std::cout << "Error: no active view\n";
6346     return 1;
6347   }
6348
6349   Standard_Integer anArgIter = 1;
6350   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6351   if (aNameArg.IsEmpty())
6352   {
6353     std::cout << "Syntax error: animation name is not defined.\n";
6354     return 1;
6355   }
6356
6357   TCollection_AsciiString aNameArgLower = aNameArg;
6358   aNameArgLower.LowerCase();
6359   if (aNameArgLower == "-reset"
6360    || aNameArgLower == "-clear")
6361   {
6362     ViewerTest_AnimationTimelineMap.Clear();
6363     return 0;
6364   }
6365   else if (aNameArg.Value (1) == '-')
6366   {
6367     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6368     return 1;
6369   }
6370
6371   const char* aNameSplitter = "/";
6372   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6373   if (aSplitPos == -1)
6374   {
6375     aNameSplitter = ".";
6376     aSplitPos = aNameArg.Search (aNameSplitter);
6377   }
6378
6379   // find existing or create a new animation by specified name within syntax "parent.child".
6380   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6381   for (; !aNameArg.IsEmpty();)
6382   {
6383     TCollection_AsciiString aNameParent;
6384     if (aSplitPos != -1)
6385     {
6386       if (aSplitPos == aNameArg.Length())
6387       {
6388         std::cout << "Syntax error: animation name is not defined.\n";
6389         return 1;
6390       }
6391
6392       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6393       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6394
6395       aSplitPos = aNameArg.Search (aNameSplitter);
6396     }
6397     else
6398     {
6399       aNameParent = aNameArg;
6400       aNameArg.Clear();
6401     }
6402
6403     if (anAnimation.IsNull())
6404     {
6405       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6406       {
6407         anAnimation = new AIS_Animation (aNameParent);
6408         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6409       }
6410       aRootAnimation = anAnimation;
6411     }
6412     else
6413     {
6414       aParentAnimation = anAnimation;
6415       anAnimation = aParentAnimation->Find (aNameParent);
6416       if (anAnimation.IsNull())
6417       {
6418         anAnimation = new AIS_Animation (aNameParent);
6419         aParentAnimation->Add (anAnimation);
6420       }
6421     }
6422   }
6423
6424   if (anArgIter >= theArgNb)
6425   {
6426     // just print the list of children
6427     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
6428     {
6429       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
6430     }
6431     return 0;
6432   }
6433
6434   // animation parameters
6435   Standard_Boolean toPlay = Standard_False;
6436   Standard_Real aPlaySpeed     = 1.0;
6437   Standard_Real aPlayStartTime = anAnimation->StartPts();
6438   Standard_Real aPlayDuration  = anAnimation->Duration();
6439   Standard_Integer aFpsNum     = 0;
6440   Standard_Integer aFpsDen     = 1;
6441   Standard_Boolean isFreeCamera = Standard_False;
6442   Standard_Boolean isLockLoop   = Standard_False;
6443   Handle(V3d_View) aView = ViewerTest::CurrentView();
6444   for (; anArgIter < theArgNb; ++anArgIter)
6445   {
6446     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6447     anArg.LowerCase();
6448     // general options
6449     if (anArg == "-reset"
6450      || anArg == "-clear")
6451     {
6452       anAnimation->Clear();
6453     }
6454     else if (anArg == "-remove"
6455           || anArg == "-del"
6456           || anArg == "-delete")
6457     {
6458       if (!aParentAnimation.IsNull())
6459       {
6460         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
6461       }
6462       else
6463       {
6464         aParentAnimation->Remove (anAnimation);
6465       }
6466     }
6467     // playback options
6468     else if (anArg == "-play")
6469     {
6470       toPlay = Standard_True;
6471       if (++anArgIter < theArgNb)
6472       {
6473         if (*theArgVec[anArgIter] == '-')
6474         {
6475           --anArgIter;
6476           continue;
6477         }
6478         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
6479
6480         if (++anArgIter < theArgNb)
6481         {
6482           if (*theArgVec[anArgIter] == '-')
6483           {
6484             --anArgIter;
6485             continue;
6486           }
6487           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6488         }
6489       }
6490     }
6491     else if (anArg == "-resume")
6492     {
6493       toPlay = Standard_True;
6494       aPlayStartTime = anAnimation->ElapsedTime();
6495       if (++anArgIter < theArgNb)
6496       {
6497         if (*theArgVec[anArgIter] == '-')
6498         {
6499           --anArgIter;
6500           continue;
6501         }
6502
6503         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6504       }
6505     }
6506     else if (anArg == "-playspeed"
6507           || anArg == "-speed")
6508     {
6509       if (++anArgIter >= theArgNb)
6510       {
6511         std::cout << "Syntax error at " << anArg << ".\n";
6512         return 1;
6513       }
6514       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
6515     }
6516     else if (anArg == "-lock"
6517           || anArg == "-lockloop"
6518           || anArg == "-playlockloop")
6519     {
6520       isLockLoop = Standard_True;
6521     }
6522     else if (anArg == "-freecamera"
6523           || anArg == "-playfreecamera"
6524           || anArg == "-freelook")
6525     {
6526       isFreeCamera = Standard_True;
6527     }
6528     else if (anArg == "-fps")
6529     {
6530       if (++anArgIter >= theArgNb)
6531       {
6532         std::cout << "Syntax error at " << anArg << ".\n";
6533         return 1;
6534       }
6535
6536       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
6537       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
6538       if (aSplitIndex == 0)
6539       {
6540         aFpsNum = aFpsArg.IntegerValue();
6541       }
6542       else
6543       {
6544         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
6545         aFpsArg.Split (aFpsArg.Length() - 1);
6546         const TCollection_AsciiString aNumStr = aFpsArg;
6547         aFpsNum = aNumStr.IntegerValue();
6548         aFpsDen = aDenStr.IntegerValue();
6549         if (aFpsDen < 1)
6550         {
6551           std::cout << "Syntax error at " << anArg << ".\n";
6552           return 1;
6553         }
6554       }
6555     }
6556     // animation definition options
6557     else if (anArg == "-start"
6558           || anArg == "-starttime"
6559           || anArg == "-startpts")
6560     {
6561       if (++anArgIter >= theArgNb)
6562       {
6563         std::cout << "Syntax error at " << anArg << ".\n";
6564         return 1;
6565       }
6566
6567       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
6568       aRootAnimation->UpdateTotalDuration();
6569     }
6570     else if (anArg == "-end"
6571           || anArg == "-endtime"
6572           || anArg == "-endpts")
6573     {
6574       if (++anArgIter >= theArgNb)
6575       {
6576         std::cout << "Syntax error at " << anArg << ".\n";
6577         return 1;
6578       }
6579
6580       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
6581       aRootAnimation->UpdateTotalDuration();
6582     }
6583     else if (anArg == "-dur"
6584           || anArg == "-duration")
6585     {
6586       if (++anArgIter >= theArgNb)
6587       {
6588         std::cout << "Syntax error at " << anArg << ".\n";
6589         return 1;
6590       }
6591
6592       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
6593       aRootAnimation->UpdateTotalDuration();
6594     }
6595     else if (anArg == "-command"
6596           || anArg == "-cmd"
6597           || anArg == "-invoke"
6598           || anArg == "-eval"
6599           || anArg == "-proc")
6600     {
6601       if (++anArgIter >= theArgNb)
6602       {
6603         std::cout << "Syntax error at " << anArg << ".\n";
6604         return 1;
6605       }
6606
6607       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
6608       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
6609     }
6610     else if (anArg == "-objecttrsf"
6611           || anArg == "-objectransformation"
6612           || anArg == "-objtransformation"
6613           || anArg == "-objtrsf"
6614           || anArg == "-object"
6615           || anArg == "-obj")
6616     {
6617       if (++anArgIter >= theArgNb)
6618       {
6619         std::cout << "Syntax error at " << anArg << ".\n";
6620         return 1;
6621       }
6622
6623       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
6624       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
6625       if (!aMapOfAIS.IsBound2 (anObjName))
6626       {
6627         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
6628         return 1;
6629       }
6630
6631       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
6632       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
6633       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
6634       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
6635       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
6636       Standard_Boolean isTrsfSet = Standard_False;
6637       Standard_Integer aTrsfArgIter = anArgIter + 1;
6638       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
6639       {
6640         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
6641         aTrsfArg.LowerCase();
6642         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
6643         if (aTrsfArg.StartsWith ("-rotation")
6644          || aTrsfArg.StartsWith ("-rot"))
6645         {
6646           isTrsfSet = Standard_True;
6647           if (aTrsfArgIter + 4 >= theArgNb
6648           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
6649           {
6650             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6651             return 1;
6652           }
6653           aTrsfArgIter += 4;
6654         }
6655         else if (aTrsfArg.StartsWith ("-location")
6656               || aTrsfArg.StartsWith ("-loc"))
6657         {
6658           isTrsfSet = Standard_True;
6659           if (aTrsfArgIter + 3 >= theArgNb
6660           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
6661           {
6662             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6663             return 1;
6664           }
6665           aTrsfArgIter += 3;
6666         }
6667         else if (aTrsfArg.StartsWith ("-scale"))
6668         {
6669           isTrsfSet = Standard_True;
6670           if (++aTrsfArgIter >= theArgNb)
6671           {
6672             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6673             return 1;
6674           }
6675
6676           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
6677           if (!aScaleStr.IsRealValue())
6678           {
6679             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6680             return 1;
6681           }
6682           aScales[anIndex] = aScaleStr.RealValue();
6683         }
6684         else
6685         {
6686           anArgIter = aTrsfArgIter - 1;
6687           break;
6688         }
6689       }
6690       if (!isTrsfSet)
6691       {
6692         std::cout << "Syntax error at " << anArg << ".\n";
6693         return 1;
6694       }
6695       else if (aTrsfArgIter >= theArgNb)
6696       {
6697         anArgIter = theArgNb;
6698       }
6699
6700       aTrsfs[0].SetRotation        (aRotQuats[0]);
6701       aTrsfs[1].SetRotation        (aRotQuats[1]);
6702       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
6703       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
6704       aTrsfs[0].SetScaleFactor     (aScales[0]);
6705       aTrsfs[1].SetScaleFactor     (aScales[1]);
6706
6707       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
6708       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
6709     }
6710     else if (anArg == "-viewtrsf"
6711           || anArg == "-view")
6712     {
6713       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
6714       if (aCamAnimation.IsNull())
6715       {
6716         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
6717         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
6718       }
6719
6720       Handle(Graphic3d_Camera) aCams[2] =
6721       {
6722         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
6723         new Graphic3d_Camera (aCamAnimation->View()->Camera())
6724       };
6725
6726       Standard_Boolean isTrsfSet = Standard_False;
6727       Standard_Integer aViewArgIter = anArgIter + 1;
6728       for (; aViewArgIter < theArgNb; ++aViewArgIter)
6729       {
6730         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
6731         aViewArg.LowerCase();
6732         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
6733         if (aViewArg.StartsWith ("-scale"))
6734         {
6735           isTrsfSet = Standard_True;
6736           if (++aViewArgIter >= theArgNb)
6737           {
6738             std::cout << "Syntax error at " << anArg << ".\n";
6739             return 1;
6740           }
6741
6742           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
6743           if (!aScaleStr.IsRealValue())
6744           {
6745             std::cout << "Syntax error at " << aViewArg << ".\n";
6746             return 1;
6747           }
6748           Standard_Real aScale = aScaleStr.RealValue();
6749           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
6750           aCams[anIndex]->SetScale (aScale);
6751         }
6752         else if (aViewArg.StartsWith ("-eye")
6753               || aViewArg.StartsWith ("-center")
6754               || aViewArg.StartsWith ("-at")
6755               || aViewArg.StartsWith ("-up"))
6756         {
6757           isTrsfSet = Standard_True;
6758           gp_XYZ anXYZ;
6759           if (aViewArgIter + 3 >= theArgNb
6760           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
6761           {
6762             std::cout << "Syntax error at " << aViewArg << ".\n";
6763             return 1;
6764           }
6765           aViewArgIter += 3;
6766
6767           if (aViewArg.StartsWith ("-eye"))
6768           {
6769             aCams[anIndex]->SetEye (anXYZ);
6770           }
6771           else if (aViewArg.StartsWith ("-center")
6772                 || aViewArg.StartsWith ("-at"))
6773           {
6774             aCams[anIndex]->SetCenter (anXYZ);
6775           }
6776           else if (aViewArg.StartsWith ("-up"))
6777           {
6778             aCams[anIndex]->SetUp (anXYZ);
6779           }
6780         }
6781         else
6782         {
6783           anArgIter = aViewArgIter - 1;
6784           break;
6785         }
6786       }
6787       if (!isTrsfSet)
6788       {
6789         std::cout << "Syntax error at " << anArg << ".\n";
6790         return 1;
6791       }
6792       else if (aViewArgIter >= theArgNb)
6793       {
6794         anArgIter = theArgNb;
6795       }
6796
6797       aCamAnimation->SetCameraStart(aCams[0]);
6798       aCamAnimation->SetCameraEnd  (aCams[1]);
6799     }
6800     else
6801     {
6802       std::cout << "Syntax error at " << anArg << ".\n";
6803       return 1;
6804     }
6805   }
6806
6807   if (!toPlay)
6808   {
6809     return 0;
6810   }
6811
6812   // Start animation timeline and process frame updating.
6813   TheIsAnimating = Standard_True;
6814   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
6815   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
6816   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
6817   if (isFreeCamera)
6818   {
6819     aView->Camera()->Copy (aCameraBack);
6820   }
6821
6822   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
6823   if (aFpsNum <= 0)
6824   {
6825     while (!anAnimation->IsStopped())
6826     {
6827       aCameraBack->Copy (aView->Camera());
6828       const Standard_Real aPts = anAnimation->UpdateTimer();
6829       if (isFreeCamera)
6830       {
6831         aView->Camera()->Copy (aCameraBack);
6832       }
6833
6834       if (aPts >= anUpperPts)
6835       {
6836         anAnimation->Pause();
6837         break;
6838       }
6839
6840       if (aView->IsInvalidated())
6841       {
6842         aView->Redraw();
6843       }
6844       else
6845       {
6846         aView->RedrawImmediate();
6847       }
6848
6849       if (!isLockLoop)
6850       {
6851         // handle user events
6852         theDI.Eval ("after 1 set waiter 1");
6853         theDI.Eval ("vwait waiter");
6854       }
6855       if (!TheIsAnimating)
6856       {
6857         anAnimation->Pause();
6858         theDI << aPts;
6859         break;
6860       }
6861     }
6862
6863     if (aView->IsInvalidated())
6864     {
6865       aView->Redraw();
6866     }
6867     else
6868     {
6869       aView->RedrawImmediate();
6870     }
6871   }
6872   else
6873   {
6874     OSD_Timer aPerfTimer;
6875     aPerfTimer.Start();
6876
6877     // Manage frame-rated animation here
6878     Standard_Real aPts = aPlayStartTime;
6879     int64_t aNbFrames = 0;
6880     for (; aPts <= anUpperPts;)
6881     {
6882       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
6883       aPts = aPlayStartTime + aRecPts;
6884       ++aNbFrames;
6885       if (!anAnimation->Update (aPts))
6886       {
6887         break;
6888       }
6889
6890       aView->Redraw();
6891     }
6892
6893     aPerfTimer.Stop();
6894     anAnimation->Stop();
6895     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
6896     theDI << "Average FPS: " << aRecFps << "\n"
6897           << "Nb. Frames: "  << Standard_Real(aNbFrames);
6898
6899     aView->Redraw();
6900   }
6901
6902   aView->SetImmediateUpdate (wasImmediateUpdate);
6903   TheIsAnimating = Standard_False;
6904   return 0;
6905 }
6906
6907
6908 //=======================================================================
6909 //function : VChangeSelected
6910 //purpose  : Adds the shape to selection or remove one from it
6911 //=======================================================================
6912 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6913                                 Standard_Integer argc,
6914                                 const char ** argv)
6915 {
6916   if(argc != 2)
6917   {
6918     di<<"Usage : " << argv[0] << " shape \n";
6919     return 1;
6920   }
6921   //get AIS_Shape:
6922   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6923   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6924   TCollection_AsciiString aName(argv[1]);
6925   Handle(AIS_InteractiveObject) anAISObject;
6926
6927   if(!aMap.IsBound2(aName))
6928   {
6929     di<<"Use 'vdisplay' before";
6930     return 1;
6931   }
6932   else
6933   {
6934     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6935     if(anAISObject.IsNull()){
6936       di<<"No interactive object \n";
6937       return 1;
6938     }
6939
6940     aContext->AddOrRemoveSelected(anAISObject);
6941   }
6942   return 0;
6943 }
6944
6945 //=======================================================================
6946 //function : VNbSelected
6947 //purpose  : Returns number of selected objects
6948 //=======================================================================
6949 static Standard_Integer VNbSelected (Draw_Interpretor& di,
6950                                 Standard_Integer argc,
6951                                 const char ** argv)
6952 {
6953   if(argc != 1)
6954   {
6955     di << "Usage : " << argv[0] << "\n";
6956     return 1;
6957   }
6958   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6959   if(aContext.IsNull())
6960   {
6961     di << "use 'vinit' command before " << argv[0] << "\n";
6962     return 1;
6963   }
6964   di << aContext->NbSelected() << "\n";
6965   return 0;
6966 }
6967
6968 //=======================================================================
6969 //function : VPurgeDisplay
6970 //purpose  : Switches altialiasing on or off
6971 //=======================================================================
6972 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
6973                                 Standard_Integer argc,
6974                                 const char ** argv)
6975 {
6976   if (argc > 1)
6977   {
6978     di << "Usage : " << argv[0] << "\n";
6979     return 1;
6980   }
6981   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6982   if (aContext.IsNull())
6983   {
6984     di << "use 'vinit' command before " << argv[0] << "\n";
6985     return 1;
6986   }
6987   aContext->CloseAllContexts(Standard_False);
6988   di << aContext->PurgeDisplay() << "\n";
6989   return 0;
6990 }
6991
6992 //=======================================================================
6993 //function : VSetViewSize
6994 //purpose  :
6995 //=======================================================================
6996 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
6997                                 Standard_Integer argc,
6998                                 const char ** argv)
6999 {
7000   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7001   if(aContext.IsNull())
7002   {
7003     di << "use 'vinit' command before " << argv[0] << "\n";
7004     return 1;
7005   }
7006   if(argc != 2)
7007   {
7008     di<<"Usage : " << argv[0] << " Size\n";
7009     return 1;
7010   }
7011   Standard_Real aSize = Draw::Atof (argv[1]);
7012   if (aSize <= 0.)
7013   {
7014     di<<"Bad Size value  : " << aSize << "\n";
7015     return 1;
7016   }
7017
7018   Handle(V3d_View) aView = ViewerTest::CurrentView();
7019   aView->SetSize(aSize);
7020   return 0;
7021 }
7022
7023 //=======================================================================
7024 //function : VMoveView
7025 //purpose  :
7026 //=======================================================================
7027 static Standard_Integer VMoveView (Draw_Interpretor& di,
7028                                 Standard_Integer argc,
7029                                 const char ** argv)
7030 {
7031   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7032   if(aContext.IsNull())
7033   {
7034     di << "use 'vinit' command before " << argv[0] << "\n";
7035     return 1;
7036   }
7037   if(argc < 4 || argc > 5)
7038   {
7039     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7040     return 1;
7041   }
7042   Standard_Real Dx = Draw::Atof (argv[1]);
7043   Standard_Real Dy = Draw::Atof (argv[2]);
7044   Standard_Real Dz = Draw::Atof (argv[3]);
7045   Standard_Boolean aStart = Standard_True;
7046   if (argc == 5)
7047   {
7048       aStart = (Draw::Atoi (argv[4]) > 0);
7049   }
7050
7051   Handle(V3d_View) aView = ViewerTest::CurrentView();
7052   aView->Move(Dx,Dy,Dz,aStart);
7053   return 0;
7054 }
7055
7056 //=======================================================================
7057 //function : VTranslateView
7058 //purpose  :
7059 //=======================================================================
7060 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7061                                 Standard_Integer argc,
7062                                 const char ** argv)
7063 {
7064   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7065   if(aContext.IsNull())
7066   {
7067     di << "use 'vinit' command before " << argv[0] << "\n";
7068     return 1;
7069   }
7070   if(argc < 4 || argc > 5)
7071   {
7072     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7073     return 1;
7074   }
7075   Standard_Real Dx = Draw::Atof (argv[1]);
7076   Standard_Real Dy = Draw::Atof (argv[2]);
7077   Standard_Real Dz = Draw::Atof (argv[3]);
7078   Standard_Boolean aStart = Standard_True;
7079   if (argc == 5)
7080   {
7081       aStart = (Draw::Atoi (argv[4]) > 0);
7082   }
7083
7084   Handle(V3d_View) aView = ViewerTest::CurrentView();
7085   aView->Translate(Dx,Dy,Dz,aStart);
7086   return 0;
7087 }
7088
7089 //=======================================================================
7090 //function : VTurnView
7091 //purpose  :
7092 //=======================================================================
7093 static Standard_Integer VTurnView (Draw_Interpretor& di,
7094                                 Standard_Integer argc,
7095                                 const char ** argv)
7096 {
7097   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7098   if(aContext.IsNull()) {
7099     di << "use 'vinit' command before " << argv[0] << "\n";
7100     return 1;
7101   }
7102   if(argc < 4 || argc > 5){
7103     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7104     return 1;
7105   }
7106   Standard_Real Ax = Draw::Atof (argv[1]);
7107   Standard_Real Ay = Draw::Atof (argv[2]);
7108   Standard_Real Az = Draw::Atof (argv[3]);
7109   Standard_Boolean aStart = Standard_True;
7110   if (argc == 5)
7111   {
7112       aStart = (Draw::Atoi (argv[4]) > 0);
7113   }
7114
7115   Handle(V3d_View) aView = ViewerTest::CurrentView();
7116   aView->Turn(Ax,Ay,Az,aStart);
7117   return 0;
7118 }
7119
7120 //==============================================================================
7121 //function : VTextureEnv
7122 //purpose  : ENables or disables environment mapping
7123 //==============================================================================
7124 class OCC_TextureEnv : public Graphic3d_TextureEnv
7125 {
7126 public:
7127   OCC_TextureEnv(const Standard_CString FileName);
7128   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7129   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7130                             const Standard_Boolean theModulateFlag,
7131                             const Graphic3d_TypeOfTextureFilter theFilter,
7132                             const Standard_ShortReal theXScale,
7133                             const Standard_ShortReal theYScale,
7134                             const Standard_ShortReal theXShift,
7135                             const Standard_ShortReal theYShift,
7136                             const Standard_ShortReal theAngle);
7137   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7138 };
7139 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7140
7141 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7142   : Graphic3d_TextureEnv(theFileName)
7143 {
7144 }
7145
7146 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7147   : Graphic3d_TextureEnv(theTexId)
7148 {
7149 }
7150
7151 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7152                                           const Standard_Boolean theModulateFlag,
7153                                           const Graphic3d_TypeOfTextureFilter theFilter,
7154                                           const Standard_ShortReal theXScale,
7155                                           const Standard_ShortReal theYScale,
7156                                           const Standard_ShortReal theXShift,
7157                                           const Standard_ShortReal theYShift,
7158                                           const Standard_ShortReal theAngle)
7159 {
7160   myParams->SetRepeat     (theRepeatFlag);
7161   myParams->SetModulate   (theModulateFlag);
7162   myParams->SetFilter     (theFilter);
7163   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7164   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7165   myParams->SetRotation   (theAngle);
7166 }
7167
7168 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7169 {
7170   // get the active view
7171   Handle(V3d_View) aView = ViewerTest::CurrentView();
7172   if (aView.IsNull())
7173   {
7174     std::cerr << "No active view. Please call vinit.\n";
7175     return 1;
7176   }
7177
7178   // Checking the input arguments
7179   Standard_Boolean anEnableFlag = Standard_False;
7180   Standard_Boolean isOk         = theArgNb >= 2;
7181   if (isOk)
7182   {
7183     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7184     anEnableFlag = anEnableOpt.IsEqual("on");
7185     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7186   }
7187   if (anEnableFlag)
7188   {
7189     isOk = (theArgNb == 3 || theArgNb == 11);
7190     if (isOk)
7191     {
7192       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7193       isOk = (!aTextureOpt.IsIntegerValue() ||
7194              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7195
7196       if (isOk && theArgNb == 11)
7197       {
7198         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7199                                 aModulateOpt(theArgVec[4]),
7200                                 aFilterOpt  (theArgVec[5]),
7201                                 aSScaleOpt  (theArgVec[6]),
7202                                 aTScaleOpt  (theArgVec[7]),
7203                                 aSTransOpt  (theArgVec[8]),
7204                                 aTTransOpt  (theArgVec[9]),
7205                                 anAngleOpt  (theArgVec[10]);
7206         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7207                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7208                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7209                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7210                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7211                 anAngleOpt.IsRealValue());
7212       }
7213     }
7214   }
7215
7216   if (!isOk)
7217   {
7218     std::cerr << "Usage :" << std::endl;
7219     std::cerr << theArgVec[0] << " off" << std::endl;
7220     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;
7221     return 1;
7222   }
7223
7224   if (anEnableFlag)
7225   {
7226     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7227     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7228                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7229                                      new OCC_TextureEnv(theArgVec[2]);
7230
7231     if (theArgNb == 11)
7232     {
7233       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7234       aTexEnv->SetTextureParameters(
7235         aRepeatOpt.  IsEqual("repeat"),
7236         aModulateOpt.IsEqual("modulate"),
7237         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7238                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7239                                                                            Graphic3d_TOTF_TRILINEAR,
7240         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7241         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7242         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7243         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7244         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7245         );
7246     }
7247     aView->SetTextureEnv(aTexEnv);
7248   }
7249   else // Disabling environment mapping
7250   {
7251     Handle(Graphic3d_TextureEnv) aTexture;
7252     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7253   }
7254
7255   aView->Redraw();
7256   return 0;
7257 }
7258
7259 namespace
7260 {
7261   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7262
7263   //! Remove registered clipping plane from all views and objects.
7264   static void removePlane (MapOfPlanes& theRegPlanes,
7265                            const TCollection_AsciiString& theName)
7266   {
7267     Handle(Graphic3d_ClipPlane) aClipPlane;
7268     if (!theRegPlanes.Find (theName, aClipPlane))
7269     {
7270       std::cout << "Warning: no such plane.\n";
7271       return;
7272     }
7273
7274     theRegPlanes.UnBind (theName);
7275     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7276          anIObjIt.More(); anIObjIt.Next())
7277     {
7278       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7279       aPrs->RemoveClipPlane (aClipPlane);
7280     }
7281
7282     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
7283          aViewIt.More(); aViewIt.Next())
7284     {
7285       const Handle(V3d_View)& aView = aViewIt.Key2();
7286       aView->RemoveClipPlane(aClipPlane);
7287     }
7288
7289     ViewerTest::RedrawAllViews();
7290   }
7291 }
7292
7293 //===============================================================================================
7294 //function : VClipPlane
7295 //purpose  :
7296 //===============================================================================================
7297 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7298 {
7299   // use short-cut for created clip planes map of created (or "registered by name") clip planes
7300   static MapOfPlanes aRegPlanes;
7301
7302   if (theArgsNb < 2)
7303   {
7304     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
7305     {
7306       theDi << aPlaneIter.Key() << " ";
7307     }
7308     return 0;
7309   }
7310
7311   TCollection_AsciiString aCommand (theArgVec[1]);
7312   aCommand.LowerCase();
7313   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
7314   if (anActiveView.IsNull())
7315   {
7316     std::cout << "Error: no active view.\n";
7317     return 1;
7318   }
7319
7320   // print maximum number of planes for current viewer
7321   if (aCommand == "-maxplanes"
7322    || aCommand == "maxplanes")
7323   {
7324     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
7325           << " plane slots provided by driver.\n";
7326     return 0;
7327   }
7328
7329   // create / delete plane instance
7330   if (aCommand == "-create"
7331    || aCommand == "create"
7332    || aCommand == "-delete"
7333    || aCommand == "delete"
7334    || aCommand == "-clone"
7335    || aCommand == "clone")
7336   {
7337     if (theArgsNb < 3)
7338     {
7339       std::cout << "Syntax error: plane name is required.\n";
7340       return 1;
7341     }
7342
7343     Standard_Boolean toCreate = aCommand == "-create"
7344                              || aCommand == "create";
7345     Standard_Boolean toClone  = aCommand == "-clone"
7346                              || aCommand == "clone";
7347     Standard_Boolean toDelete = aCommand == "-delete"
7348                              || aCommand == "delete";
7349     TCollection_AsciiString aPlane (theArgVec[2]);
7350
7351     if (toCreate)
7352     {
7353       if (aRegPlanes.IsBound (aPlane))
7354       {
7355         std::cout << "Warning: existing plane has been overridden.\n";
7356         toDelete = true;
7357       }
7358       else
7359       {
7360         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7361         return 0;
7362       }
7363     }
7364     else if (toClone) // toClone
7365     {
7366       if (!aRegPlanes.IsBound (aPlane))
7367       {
7368         std::cout << "Error: no such plane.\n";
7369         return 1;
7370       }
7371       else if (theArgsNb < 4)
7372       {
7373         std::cout << "Syntax error: enter name for new plane.\n";
7374         return 1;
7375       }
7376
7377       TCollection_AsciiString aClone (theArgVec[3]);
7378       if (aRegPlanes.IsBound (aClone))
7379       {
7380         std::cout << "Error: plane name is in use.\n";
7381         return 1;
7382       }
7383
7384       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
7385
7386       aRegPlanes.Bind (aClone, aClipPlane->Clone());
7387       return 0;
7388     }
7389
7390     if (toDelete)
7391     {
7392       if (aPlane == "ALL"
7393        || aPlane == "all"
7394        || aPlane == "*")
7395       {
7396         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
7397         {
7398           aPlane = aPlaneIter.Key();
7399           removePlane (aRegPlanes, aPlane);
7400           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
7401         }
7402       }
7403       else
7404       {
7405         removePlane (aRegPlanes, aPlane);
7406       }
7407     }
7408
7409     if (toCreate)
7410     {
7411       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7412     }
7413     return 0;
7414   }
7415
7416   // set / unset plane command
7417   if (aCommand == "set"
7418    || aCommand == "unset")
7419   {
7420     if (theArgsNb < 5)
7421     {
7422       std::cout << "Syntax error: need more arguments.\n";
7423       return 1;
7424     }
7425
7426     // redirect to new syntax
7427     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
7428     anArgVec.SetValue (1, theArgVec[0]);
7429     anArgVec.SetValue (2, theArgVec[2]);
7430     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
7431     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
7432     {
7433       anArgVec.SetValue (anIt, theArgVec[anIt]);
7434     }
7435
7436     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
7437   }
7438
7439   // change plane command
7440   TCollection_AsciiString aPlaneName;
7441   Handle(Graphic3d_ClipPlane) aClipPlane;
7442   Standard_Integer anArgIter = 0;
7443   if (aCommand == "-change"
7444    || aCommand == "change")
7445   {
7446     // old syntax support
7447     if (theArgsNb < 3)
7448     {
7449       std::cout << "Syntax error: need more arguments.\n";
7450       return 1;
7451     }
7452
7453     anArgIter  = 3;
7454     aPlaneName = theArgVec[2];
7455     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
7456     {
7457       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
7458       return 1;
7459     }
7460   }
7461   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
7462   {
7463     anArgIter  = 2;
7464     aPlaneName = theArgVec[1];
7465   }
7466   else
7467   {
7468     anArgIter  = 2;
7469     aPlaneName = theArgVec[1];
7470     aClipPlane = new Graphic3d_ClipPlane();
7471     aRegPlanes.Bind (aPlaneName, aClipPlane);
7472     theDi << "Created new plane " << aPlaneName << ".\n";
7473   }
7474
7475   if (theArgsNb - anArgIter < 1)
7476   {
7477     std::cout << "Syntax error: need more arguments.\n";
7478     return 1;
7479   }
7480
7481   for (; anArgIter < theArgsNb; ++anArgIter)
7482   {
7483     const char**     aChangeArgs   = theArgVec + anArgIter;
7484     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
7485     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
7486     aChangeArg.LowerCase();
7487
7488     Standard_Boolean toEnable = Standard_True;
7489     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
7490     {
7491       aClipPlane->SetOn (toEnable);
7492     }
7493     else if (aChangeArg == "-equation"
7494           || aChangeArg == "equation")
7495     {
7496       if (aNbChangeArgs < 5)
7497       {
7498         std::cout << "Syntax error: need more arguments.\n";
7499         return 1;
7500       }
7501
7502       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
7503       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
7504       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
7505       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
7506       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
7507       anArgIter += 4;
7508     }
7509     else if (aChangeArg == "-capping"
7510           || aChangeArg == "capping")
7511     {
7512       if (aNbChangeArgs < 2)
7513       {
7514         std::cout << "Syntax error: need more arguments.\n";
7515         return 1;
7516       }
7517
7518       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7519       {
7520         aClipPlane->SetCapping (toEnable);
7521         anArgIter += 1;
7522       }
7523       else
7524       {
7525         // just skip otherwise (old syntax)
7526       }
7527     }
7528     else if (aChangeArg == "-useobjectmaterial"
7529           || aChangeArg == "-useobjectmat"
7530           || aChangeArg == "-useobjmat"
7531           || aChangeArg == "-useobjmaterial")
7532     {
7533       if (aNbChangeArgs < 2)
7534       {
7535         std::cout << "Syntax error: need more arguments.\n";
7536         return 1;
7537       }
7538
7539       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7540       {
7541         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
7542         anArgIter += 1;
7543       }
7544     }
7545     else if (aChangeArg == "-useobjecttexture"
7546           || aChangeArg == "-useobjecttex"
7547           || aChangeArg == "-useobjtexture"
7548           || aChangeArg == "-useobjtex")
7549     {
7550       if (aNbChangeArgs < 2)
7551       {
7552         std::cout << "Syntax error: need more arguments.\n";
7553         return 1;
7554       }
7555
7556       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7557       {
7558         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
7559         anArgIter += 1;
7560       }
7561     }
7562     else if (aChangeArg == "-useobjectshader"
7563           || aChangeArg == "-useobjshader")
7564     {
7565       if (aNbChangeArgs < 2)
7566       {
7567         std::cout << "Syntax error: need more arguments.\n";
7568         return 1;
7569       }
7570
7571       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7572       {
7573         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
7574         anArgIter += 1;
7575       }
7576     }
7577     else if (aChangeArg == "-color"
7578           || aChangeArg == "color")
7579     {
7580       Quantity_Color aColor;
7581       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
7582                                                            aChangeArgs + 1,
7583                                                            aColor);
7584       if (aNbParsed == 0)
7585       {
7586         std::cout << "Syntax error: need more arguments.\n";
7587         return 1;
7588       }
7589
7590       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
7591       aMat.SetAmbientColor (aColor);
7592       aMat.SetDiffuseColor (aColor);
7593       aClipPlane->SetCappingMaterial (aMat);
7594       anArgIter += aNbParsed;
7595     }
7596     else if (aChangeArg == "-texname"
7597           || aChangeArg == "texname")
7598     {
7599       if (aNbChangeArgs < 2)
7600       {
7601         std::cout << "Syntax error: need more arguments.\n";
7602         return 1;
7603       }
7604
7605       TCollection_AsciiString aTextureName (aChangeArgs[1]);
7606       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
7607       if (!aTexture->IsDone())
7608       {
7609         aClipPlane->SetCappingTexture (NULL);
7610       }
7611       else
7612       {
7613         aTexture->EnableModulate();
7614         aTexture->EnableRepeat();
7615         aClipPlane->SetCappingTexture (aTexture);
7616       }
7617       anArgIter += 1;
7618     }
7619     else if (aChangeArg == "-texscale"
7620           || aChangeArg == "texscale")
7621     {
7622       if (aClipPlane->CappingTexture().IsNull())
7623       {
7624         std::cout << "Error: no texture is set.\n";
7625         return 1;
7626       }
7627
7628       if (aNbChangeArgs < 3)
7629       {
7630         std::cout << "Syntax error: need more arguments.\n";
7631         return 1;
7632       }
7633
7634       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7635       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7636       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
7637       anArgIter += 2;
7638     }
7639     else if (aChangeArg == "-texorigin"
7640           || aChangeArg == "texorigin") // texture origin
7641     {
7642       if (aClipPlane->CappingTexture().IsNull())
7643       {
7644         std::cout << "Error: no texture is set.\n";
7645         return 1;
7646       }
7647
7648       if (aNbChangeArgs < 3)
7649       {
7650         std::cout << "Syntax error: need more arguments.\n";
7651         return 1;
7652       }
7653
7654       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7655       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7656
7657       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
7658       anArgIter += 2;
7659     }
7660     else if (aChangeArg == "-texrotate"
7661           || aChangeArg == "texrotate") // texture rotation
7662     {
7663       if (aClipPlane->CappingTexture().IsNull())
7664       {
7665         std::cout << "Error: no texture is set.\n";
7666         return 1;
7667       }
7668
7669       if (aNbChangeArgs < 2)
7670       {
7671         std::cout << "Syntax error: need more arguments.\n";
7672         return 1;
7673       }
7674
7675       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7676       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
7677       anArgIter += 1;
7678     }
7679     else if (aChangeArg == "-hatch"
7680           || aChangeArg == "hatch")
7681     {
7682       if (aNbChangeArgs < 2)
7683       {
7684         std::cout << "Syntax error: need more arguments.\n";
7685         return 1;
7686       }
7687
7688       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
7689       aHatchStr.LowerCase();
7690       if (aHatchStr == "on")
7691       {
7692         aClipPlane->SetCappingHatchOn();
7693       }
7694       else if (aHatchStr == "off")
7695       {
7696         aClipPlane->SetCappingHatchOff();
7697       }
7698       else
7699       {
7700         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
7701       }
7702       anArgIter += 1;
7703     }
7704     else if (aChangeArg == "-delete"
7705           || aChangeArg == "delete")
7706     {
7707       removePlane (aRegPlanes, aPlaneName);
7708       return 0;
7709     }
7710     else if (aChangeArg == "-set"
7711           || aChangeArg == "-unset")
7712     {
7713       // set / unset plane command
7714       Standard_Boolean toSet = aChangeArg == "-set";
7715       Standard_Integer anIt = 1;
7716       for (; anIt < aNbChangeArgs; ++anIt)
7717       {
7718         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
7719         if (anEntityName.IsEmpty()
7720          || anEntityName.Value (1) == '-')
7721         {
7722           break;
7723         }
7724         else if (ViewerTest_myViews.IsBound1 (anEntityName))
7725         {
7726           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
7727           if (toSet)
7728           {
7729             aView->AddClipPlane (aClipPlane);
7730           }
7731           else
7732           {
7733             aView->RemoveClipPlane (aClipPlane);
7734           }
7735           continue;
7736         }
7737         else if (GetMapOfAIS().IsBound2 (anEntityName))
7738         {
7739           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
7740           if (toSet)
7741           {
7742             aIObj->AddClipPlane (aClipPlane);
7743           }
7744           else
7745           {
7746             aIObj->RemoveClipPlane (aClipPlane);
7747           }
7748         }
7749         else
7750         {
7751           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
7752           return 1;
7753         }
7754       }
7755
7756       if (anIt == 1)
7757       {
7758         // apply to active view
7759         if (toSet)
7760         {
7761           anActiveView->AddClipPlane (aClipPlane);
7762         }
7763         else
7764         {
7765           anActiveView->RemoveClipPlane (aClipPlane);
7766         }
7767       }
7768       else
7769       {
7770         anArgIter = anArgIter + anIt - 1;
7771       }
7772     }
7773     else
7774     {
7775       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
7776       return 1;
7777     }
7778   }
7779
7780   ViewerTest::RedrawAllViews();
7781   return 0;
7782 }
7783
7784 //===============================================================================================
7785 //function : VZRange
7786 //purpose  :
7787 //===============================================================================================
7788 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7789 {
7790   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7791
7792   if (aCurrentView.IsNull())
7793   {
7794     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7795     return 1;
7796   }
7797
7798   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
7799
7800   if (theArgsNb < 2)
7801   {
7802     theDi << "ZNear: " << aCamera->ZNear() << "\n";
7803     theDi << "ZFar: " << aCamera->ZFar() << "\n";
7804     return 0;
7805   }
7806
7807   if (theArgsNb == 3)
7808   {
7809     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
7810     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
7811
7812     if (aNewZNear >= aNewZFar)
7813     {
7814       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
7815       return 1;
7816     }
7817
7818     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
7819     {
7820       std::cout << theArgVec[0] << ": invalid arguments: ";
7821       std::cout << "znear, zfar should be positive for perspective camera.\n";
7822       return 1;
7823     }
7824
7825     aCamera->SetZRange (aNewZNear, aNewZFar);
7826   }
7827   else
7828   {
7829     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7830     return 1;
7831   }
7832
7833   aCurrentView->Redraw();
7834
7835   return 0;
7836 }
7837
7838 //===============================================================================================
7839 //function : VAutoZFit
7840 //purpose  :
7841 //===============================================================================================
7842 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7843 {
7844   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7845
7846   if (aCurrentView.IsNull())
7847   {
7848     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7849     return 1;
7850   }
7851
7852   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
7853
7854   if (theArgsNb > 3)
7855   {
7856     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7857     return 1;
7858   }
7859
7860   if (theArgsNb < 2)
7861   {
7862     theDi << "Auto z-fit mode: \n"
7863           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
7864           << "Scale: " << aScale << "\n";
7865     return 0;
7866   }
7867
7868   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
7869
7870   if (theArgsNb >= 3)
7871   {
7872     aScale = Draw::Atoi (theArgVec[2]);
7873   }
7874
7875   aCurrentView->SetAutoZFitMode (isOn, aScale);
7876   aCurrentView->AutoZFit();
7877   aCurrentView->Redraw();
7878
7879   return 0;
7880 }
7881
7882 //! Auxiliary function to print projection type
7883 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
7884 {
7885   switch (theProjType)
7886   {
7887     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
7888     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
7889     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
7890     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
7891     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
7892   }
7893   return "UNKNOWN";
7894 }
7895
7896 //===============================================================================================
7897 //function : VCamera
7898 //purpose  :
7899 //===============================================================================================
7900 static int VCamera (Draw_Interpretor& theDI,
7901                     Standard_Integer  theArgsNb,
7902                     const char**      theArgVec)
7903 {
7904   Handle(V3d_View) aView = ViewerTest::CurrentView();
7905   if (aView.IsNull())
7906   {
7907     std::cout << "Error: no active view.\n";
7908     return 1;
7909   }
7910
7911   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7912   if (theArgsNb < 2)
7913   {
7914     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7915     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7916     theDI << "Distance:   " << aCamera->Distance() << "\n";
7917     theDI << "IOD:        " << aCamera->IOD() << "\n";
7918     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7919     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7920     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7921     return 0;
7922   }
7923
7924   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7925   {
7926     Standard_CString        anArg = theArgVec[anArgIter];
7927     TCollection_AsciiString anArgCase (anArg);
7928     anArgCase.LowerCase();
7929     if (anArgCase == "-proj"
7930      || anArgCase == "-projection"
7931      || anArgCase == "-projtype"
7932      || anArgCase == "-projectiontype")
7933     {
7934       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7935     }
7936     else if (anArgCase == "-ortho"
7937           || anArgCase == "-orthographic")
7938     {
7939       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
7940     }
7941     else if (anArgCase == "-persp"
7942           || anArgCase == "-perspective"
7943           || anArgCase == "-perspmono"
7944           || anArgCase == "-perspectivemono"
7945           || anArgCase == "-mono")
7946     {
7947       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7948     }
7949     else if (anArgCase == "-stereo"
7950           || anArgCase == "-stereoscopic"
7951           || anArgCase == "-perspstereo"
7952           || anArgCase == "-perspectivestereo")
7953     {
7954       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7955     }
7956     else if (anArgCase == "-left"
7957           || anArgCase == "-lefteye"
7958           || anArgCase == "-monoleft"
7959           || anArgCase == "-monolefteye"
7960           || anArgCase == "-perpsleft"
7961           || anArgCase == "-perpslefteye")
7962     {
7963       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
7964     }
7965     else if (anArgCase == "-right"
7966           || anArgCase == "-righteye"
7967           || anArgCase == "-monoright"
7968           || anArgCase == "-monorighteye"
7969           || anArgCase == "-perpsright")
7970     {
7971       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
7972     }
7973     else if (anArgCase == "-dist"
7974           || anArgCase == "-distance")
7975     {
7976       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7977       if (anArgValue != NULL
7978       && *anArgValue != '-')
7979       {
7980         ++anArgIter;
7981         aCamera->SetDistance (Draw::Atof (anArgValue));
7982         continue;
7983       }
7984       theDI << aCamera->Distance() << " ";
7985     }
7986     else if (anArgCase == "-iod")
7987     {
7988       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7989       if (anArgValue != NULL
7990       && *anArgValue != '-')
7991       {
7992         ++anArgIter;
7993         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
7994         continue;
7995       }
7996       theDI << aCamera->IOD() << " ";
7997     }
7998     else if (anArgCase == "-iodtype")
7999     {
8000       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8001       TCollection_AsciiString anValueCase (anArgValue);
8002       anValueCase.LowerCase();
8003       if (anValueCase == "abs"
8004        || anValueCase == "absolute")
8005       {
8006         ++anArgIter;
8007         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8008         continue;
8009       }
8010       else if (anValueCase == "rel"
8011             || anValueCase == "relative")
8012       {
8013         ++anArgIter;
8014         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8015         continue;
8016       }
8017       else if (*anArgValue != '-')
8018       {
8019         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8020         return 1;
8021       }
8022       switch (aCamera->GetIODType())
8023       {
8024         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8025         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8026       }
8027     }
8028     else if (anArgCase == "-zfocus")
8029     {
8030       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8031       if (anArgValue != NULL
8032       && *anArgValue != '-')
8033       {
8034         ++anArgIter;
8035         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8036         continue;
8037       }
8038       theDI << aCamera->ZFocus() << " ";
8039     }
8040     else if (anArgCase == "-zfocustype")
8041     {
8042       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8043       TCollection_AsciiString anValueCase (anArgValue);
8044       anValueCase.LowerCase();
8045       if (anValueCase == "abs"
8046        || anValueCase == "absolute")
8047       {
8048         ++anArgIter;
8049         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8050         continue;
8051       }
8052       else if (anValueCase == "rel"
8053             || anValueCase == "relative")
8054       {
8055         ++anArgIter;
8056         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8057         continue;
8058       }
8059       else if (*anArgValue != '-')
8060       {
8061         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8062         return 1;
8063       }
8064       switch (aCamera->ZFocusType())
8065       {
8066         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8067         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8068       }
8069     }
8070     else if (anArgCase == "-fov"
8071           || anArgCase == "-fovy")
8072     {
8073       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8074       if (anArgValue != NULL
8075       && *anArgValue != '-')
8076       {
8077         ++anArgIter;
8078         aCamera->SetFOVy (Draw::Atof (anArgValue));
8079         continue;
8080       }
8081       theDI << aCamera->FOVy() << " ";
8082     }
8083     else
8084     {
8085       std::cout << "Error: unknown argument '" << anArg << "'\n";
8086       return 1;
8087     }
8088   }
8089
8090   aView->AutoZFit();
8091   aView->Redraw();
8092
8093   return 0;
8094 }
8095
8096 //! Parse stereo output mode
8097 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8098                                          Graphic3d_StereoMode& theMode)
8099 {
8100   TCollection_AsciiString aFlag (theArg);
8101   aFlag.LowerCase();
8102   if (aFlag == "quadbuffer")
8103   {
8104     theMode = Graphic3d_StereoMode_QuadBuffer;
8105   }
8106   else if (aFlag == "anaglyph")
8107   {
8108     theMode = Graphic3d_StereoMode_Anaglyph;
8109   }
8110   else if (aFlag == "row"
8111         || aFlag == "rowinterlaced")
8112   {
8113     theMode = Graphic3d_StereoMode_RowInterlaced;
8114   }
8115   else if (aFlag == "col"
8116         || aFlag == "colinterlaced"
8117         || aFlag == "columninterlaced")
8118   {
8119     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8120   }
8121   else if (aFlag == "chess"
8122         || aFlag == "chessboard")
8123   {
8124     theMode = Graphic3d_StereoMode_ChessBoard;
8125   }
8126   else if (aFlag == "sbs"
8127         || aFlag == "sidebyside")
8128   {
8129     theMode = Graphic3d_StereoMode_SideBySide;
8130   }
8131   else if (aFlag == "ou"
8132         || aFlag == "overunder")
8133   {
8134     theMode = Graphic3d_StereoMode_OverUnder;
8135   }
8136   else if (aFlag == "pageflip"
8137         || aFlag == "softpageflip")
8138   {
8139     theMode = Graphic3d_StereoMode_SoftPageFlip;
8140   }
8141   else
8142   {
8143     return Standard_False;
8144   }
8145   return Standard_True;
8146 }
8147
8148 //! Parse anaglyph filter
8149 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8150                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8151 {
8152   TCollection_AsciiString aFlag (theArg);
8153   aFlag.LowerCase();
8154   if (aFlag == "redcyansimple")
8155   {
8156     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8157   }
8158   else if (aFlag == "redcyan"
8159         || aFlag == "redcyanoptimized")
8160   {
8161     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8162   }
8163   else if (aFlag == "yellowbluesimple")
8164   {
8165     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8166   }
8167   else if (aFlag == "yellowblue"
8168         || aFlag == "yellowblueoptimized")
8169   {
8170     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8171   }
8172   else if (aFlag == "greenmagenta"
8173         || aFlag == "greenmagentasimple")
8174   {
8175     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8176   }
8177   else
8178   {
8179     return Standard_False;
8180   }
8181   return Standard_True;
8182 }
8183
8184 //==============================================================================
8185 //function : VStereo
8186 //purpose  :
8187 //==============================================================================
8188
8189 static int VStereo (Draw_Interpretor& theDI,
8190                     Standard_Integer  theArgNb,
8191                     const char**      theArgVec)
8192 {
8193   Handle(V3d_View) aView = ViewerTest::CurrentView();
8194   if (theArgNb < 2)
8195   {
8196     if (aView.IsNull())
8197     {
8198       std::cout << "Error: no active viewer!\n";
8199       return 0;
8200     }
8201
8202     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8203     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8204     if (isActive)
8205     {
8206       TCollection_AsciiString aMode;
8207       switch (aView->RenderingParams().StereoMode)
8208       {
8209         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8210         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8211         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8212         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8213         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8214         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8215         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8216         case Graphic3d_StereoMode_Anaglyph  :
8217           aMode = "anaglyph";
8218           switch (aView->RenderingParams().AnaglyphFilter)
8219           {
8220             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8221             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8222             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8223             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8224             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8225             default: break;
8226           }
8227         default: break;
8228       }
8229       theDI << "Mode " << aMode << "\n";
8230     }
8231     return 0;
8232   }
8233
8234   Handle(Graphic3d_Camera) aCamera;
8235   Graphic3d_RenderingParams*   aParams   = NULL;
8236   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8237   if (!aView.IsNull())
8238   {
8239     aParams   = &aView->ChangeRenderingParams();
8240     aMode     = aParams->StereoMode;
8241     aCamera   = aView->Camera();
8242   }
8243
8244   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8245   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8246   {
8247     Standard_CString        anArg = theArgVec[anArgIter];
8248     TCollection_AsciiString aFlag (anArg);
8249     aFlag.LowerCase();
8250     if (anUpdateTool.parseRedrawMode (aFlag))
8251     {
8252       continue;
8253     }
8254     else if (aFlag == "0"
8255           || aFlag == "off")
8256     {
8257       if (++anArgIter < theArgNb)
8258       {
8259         std::cout << "Error: wrong number of arguments!\n";
8260         return 1;
8261       }
8262
8263       if (!aCamera.IsNull()
8264        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8265       {
8266         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8267       }
8268       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8269       return 0;
8270     }
8271     else if (aFlag == "1"
8272           || aFlag == "on")
8273     {
8274       if (++anArgIter < theArgNb)
8275       {
8276         std::cout << "Error: wrong number of arguments!\n";
8277         return 1;
8278       }
8279
8280       if (!aCamera.IsNull())
8281       {
8282         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8283       }
8284       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8285       return 0;
8286     }
8287     else if (aFlag == "-reverse"
8288           || aFlag == "-reversed"
8289           || aFlag == "-swap")
8290     {
8291       Standard_Boolean toEnable = Standard_True;
8292       if (++anArgIter < theArgNb
8293       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8294       {
8295         --anArgIter;
8296       }
8297       aParams->ToReverseStereo = toEnable;
8298     }
8299     else if (aFlag == "-noreverse"
8300           || aFlag == "-noswap")
8301     {
8302       Standard_Boolean toDisable = Standard_True;
8303       if (++anArgIter < theArgNb
8304       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
8305       {
8306         --anArgIter;
8307       }
8308       aParams->ToReverseStereo = !toDisable;
8309     }
8310     else if (aFlag == "-mode"
8311           || aFlag == "-stereomode")
8312     {
8313       if (++anArgIter >= theArgNb
8314       || !parseStereoMode (theArgVec[anArgIter], aMode))
8315       {
8316         std::cout << "Error: syntax error at '" << anArg << "'\n";
8317         return 1;
8318       }
8319
8320       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8321       {
8322         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8323       }
8324     }
8325     else if (aFlag == "-anaglyph"
8326           || aFlag == "-anaglyphfilter")
8327     {
8328       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8329       if (++anArgIter >= theArgNb
8330       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
8331       {
8332         std::cout << "Error: syntax error at '" << anArg << "'\n";
8333         return 1;
8334       }
8335
8336       aMode = Graphic3d_StereoMode_Anaglyph;
8337       aParams->AnaglyphFilter = aFilter;
8338     }
8339     else if (parseStereoMode (anArg, aMode)) // short syntax
8340     {
8341       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8342       {
8343         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8344       }
8345     }
8346     else
8347     {
8348       std::cout << "Error: syntax error at '" << anArg << "'\n";
8349       return 1;
8350     }
8351   }
8352
8353   if (!aView.IsNull())
8354   {
8355     aParams->StereoMode = aMode;
8356     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8357   }
8358   return 0;
8359 }
8360
8361 //===============================================================================================
8362 //function : VDefaults
8363 //purpose  :
8364 //===============================================================================================
8365 static int VDefaults (Draw_Interpretor& theDi,
8366                       Standard_Integer  theArgsNb,
8367                       const char**      theArgVec)
8368 {
8369   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
8370   if (aCtx.IsNull())
8371   {
8372     std::cerr << "No active viewer!\n";
8373     return 1;
8374   }
8375
8376   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
8377   if (theArgsNb < 2)
8378   {
8379     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
8380     {
8381       theDi << "DeflType:           relative\n"
8382             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
8383     }
8384     else
8385     {
8386       theDi << "DeflType:           absolute\n"
8387             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
8388     }
8389     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
8390     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
8391     return 0;
8392   }
8393
8394   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8395   {
8396     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8397     anArg.UpperCase();
8398     if (anArg == "-ABSDEFL"
8399      || anArg == "-ABSOLUTEDEFLECTION"
8400      || anArg == "-DEFL"
8401      || anArg == "-DEFLECTION")
8402     {
8403       if (++anArgIter >= theArgsNb)
8404       {
8405         std::cout << "Error: wrong syntax at " << anArg << "\n";
8406         return 1;
8407       }
8408       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
8409       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
8410     }
8411     else if (anArg == "-RELDEFL"
8412           || anArg == "-RELATIVEDEFLECTION"
8413           || anArg == "-DEVCOEFF"
8414           || anArg == "-DEVIATIONCOEFF"
8415           || anArg == "-DEVIATIONCOEFFICIENT")
8416     {
8417       if (++anArgIter >= theArgsNb)
8418       {
8419         std::cout << "Error: wrong syntax at " << anArg << "\n";
8420         return 1;
8421       }
8422       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
8423       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
8424     }
8425     else if (anArg == "-ANGDEFL"
8426           || anArg == "-ANGULARDEFL"
8427           || anArg == "-ANGULARDEFLECTION")
8428     {
8429       if (++anArgIter >= theArgsNb)
8430       {
8431         std::cout << "Error: wrong syntax at " << anArg << "\n";
8432         return 1;
8433       }
8434       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
8435       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
8436     }
8437     else if (anArg == "-AUTOTR"
8438           || anArg == "-AUTOTRIANG"
8439           || anArg == "-AUTOTRIANGULATION")
8440     {
8441       if (++anArgIter >= theArgsNb)
8442       {
8443         std::cout << "Error: wrong syntax at " << anArg << "\n";
8444         return 1;
8445       }
8446       TCollection_AsciiString aValue (theArgVec[anArgIter]);
8447       aValue.LowerCase();
8448       if (aValue == "on"
8449        || aValue == "1")
8450       {
8451         aDefParams->SetAutoTriangulation (Standard_True);
8452       }
8453       else if (aValue == "off"
8454             || aValue == "0")
8455       {
8456         aDefParams->SetAutoTriangulation (Standard_False);
8457       }
8458     }
8459     else
8460     {
8461       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
8462     }
8463   }
8464
8465   return 0;
8466 }
8467
8468 //! Auxiliary method
8469 inline void addLight (const Handle(V3d_Light)& theLightNew,
8470                       const Standard_Boolean   theIsGlobal)
8471 {
8472   if (theLightNew.IsNull())
8473   {
8474     return;
8475   }
8476
8477   if (theIsGlobal)
8478   {
8479     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
8480   }
8481   else
8482   {
8483     ViewerTest::CurrentView()->SetLightOn (theLightNew);
8484   }
8485 }
8486
8487 //! Auxiliary method
8488 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
8489 {
8490   TCollection_AsciiString anArgNextCase (theArgNext);
8491   anArgNextCase.UpperCase();
8492   if (anArgNextCase.Length() > 5
8493    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
8494   {
8495     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
8496   }
8497   else
8498   {
8499     return theArgNext.IntegerValue();
8500   }
8501 }
8502
8503 //===============================================================================================
8504 //function : VLight
8505 //purpose  :
8506 //===============================================================================================
8507 static int VLight (Draw_Interpretor& theDi,
8508                    Standard_Integer  theArgsNb,
8509                    const char**      theArgVec)
8510 {
8511   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8512   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8513   if (aView.IsNull()
8514    || aViewer.IsNull())
8515   {
8516     std::cerr << "No active viewer!\n";
8517     return 1;
8518   }
8519
8520   Standard_Real        anXYZ[3];
8521   Quantity_Coefficient anAtten[2];
8522   if (theArgsNb < 2)
8523   {
8524     // print lights info
8525     Standard_Integer aLightId = 0;
8526     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
8527     {
8528       Handle(V3d_Light) aLight = aLightIter.Value();
8529       const Quantity_Color aColor = aLight->Color();
8530       theDi << "Light" << aLightId << "\n";
8531       switch (aLight->Type())
8532       {
8533         case V3d_AMBIENT:
8534         {
8535           theDi << "  Type:       Ambient\n";
8536           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8537           break;
8538         }
8539         case V3d_DIRECTIONAL:
8540         {
8541           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
8542           theDi << "  Type:       Directional\n";
8543           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8544           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8545           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8546           if (!aLightDir.IsNull())
8547           {
8548             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8549             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8550             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8551             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8552           }
8553           break;
8554         }
8555         case V3d_POSITIONAL:
8556         {
8557           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
8558           theDi << "  Type:       Positional\n";
8559           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8560           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8561           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8562           if (!aLightPos.IsNull())
8563           {
8564             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8565             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8566             aLightPos->Attenuation (anAtten[0], anAtten[1]);
8567             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8568           }
8569           break;
8570         }
8571         case V3d_SPOT:
8572         {
8573           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
8574           theDi << "  Type:       Spot\n";
8575           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8576           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8577           if (!aLightSpot.IsNull())
8578           {
8579             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8580             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8581             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8582             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8583             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8584             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8585             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
8586             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
8587           }
8588           break;
8589         }
8590         default:
8591         {
8592           theDi << "  Type:       UNKNOWN\n";
8593           break;
8594         }
8595       }
8596       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
8597     }
8598   }
8599
8600   Handle(V3d_Light) aLightNew;
8601   Handle(V3d_Light) aLightOld;
8602   Standard_Boolean  isGlobal = Standard_True;
8603   Standard_Boolean  toCreate = Standard_False;
8604   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8605   {
8606     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
8607     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
8608     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
8609     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
8610     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
8611
8612     TCollection_AsciiString aName, aValue;
8613     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
8614     TCollection_AsciiString anArgCase (anArg);
8615     anArgCase.UpperCase();
8616     if (anArgCase.IsEqual ("NEW")
8617      || anArgCase.IsEqual ("ADD")
8618      || anArgCase.IsEqual ("CREATE"))
8619     {
8620       toCreate = Standard_True;
8621     }
8622     else if (anArgCase.IsEqual ("GLOB")
8623           || anArgCase.IsEqual ("GLOBAL"))
8624     {
8625       isGlobal = Standard_True;
8626     }
8627     else if (anArgCase.IsEqual ("LOC")
8628           || anArgCase.IsEqual ("LOCAL"))
8629     {
8630       isGlobal = Standard_False;
8631     }
8632     else if (anArgCase.IsEqual ("DEF")
8633           || anArgCase.IsEqual ("DEFAULTS"))
8634     {
8635       toCreate = Standard_False;
8636       aViewer->SetDefaultLights();
8637     }
8638     else if (anArgCase.IsEqual ("CLR")
8639           || anArgCase.IsEqual ("CLEAR"))
8640     {
8641       toCreate = Standard_False;
8642       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
8643       {
8644         Handle(V3d_Light) aLight = aLightIter.Value();
8645         aViewer->DelLight (aLight);
8646         aLightIter = aView->ActiveLightIterator();
8647       }
8648     }
8649     else if (anArgCase.IsEqual ("AMB")
8650           || anArgCase.IsEqual ("AMBIENT")
8651           || anArgCase.IsEqual ("AMBLIGHT"))
8652     {
8653       addLight (aLightNew, isGlobal);
8654       if (!toCreate)
8655       {
8656         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8657         return 1;
8658       }
8659       toCreate  = Standard_False;
8660       aLightNew = new V3d_AmbientLight (aViewer);
8661     }
8662     else if (anArgCase.IsEqual ("DIRECTIONAL")
8663           || anArgCase.IsEqual ("DIRLIGHT"))
8664     {
8665       addLight (aLightNew, isGlobal);
8666       if (!toCreate)
8667       {
8668         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8669         return 1;
8670       }
8671       toCreate  = Standard_False;
8672       aLightNew = new V3d_DirectionalLight (aViewer);
8673     }
8674     else if (anArgCase.IsEqual ("SPOT")
8675           || anArgCase.IsEqual ("SPOTLIGHT"))
8676     {
8677       addLight (aLightNew, isGlobal);
8678       if (!toCreate)
8679       {
8680         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8681         return 1;
8682       }
8683       toCreate  = Standard_False;
8684       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
8685     }
8686     else if (anArgCase.IsEqual ("POSLIGHT")
8687           || anArgCase.IsEqual ("POSITIONAL"))
8688     {
8689       addLight (aLightNew, isGlobal);
8690       if (!toCreate)
8691       {
8692         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8693         return 1;
8694       }
8695       toCreate  = Standard_False;
8696       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
8697     }
8698     else if (anArgCase.IsEqual ("CHANGE"))
8699     {
8700       addLight (aLightNew, isGlobal);
8701       aLightNew.Nullify();
8702       if (++anArgIt >= theArgsNb)
8703       {
8704         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8705         return 1;
8706       }
8707
8708       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
8709       Standard_Integer aLightIt = 0;
8710       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8711       {
8712         if (aLightIt == aLightId)
8713         {
8714           aLightOld = aLightIter.Value();
8715           break;
8716         }
8717       }
8718
8719       if (aLightOld.IsNull())
8720       {
8721         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
8722         return 1;
8723       }
8724     }
8725     else if (anArgCase.IsEqual ("DEL")
8726           || anArgCase.IsEqual ("DELETE"))
8727     {
8728       Handle(V3d_Light) aLightDel;
8729       if (++anArgIt >= theArgsNb)
8730       {
8731         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8732         return 1;
8733       }
8734
8735       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8736       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
8737       Standard_Integer aLightIt = 0;
8738       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8739       {
8740         aLightDel = aLightIter.Value();
8741         if (aLightIt == aLightDelId)
8742         {
8743           break;
8744         }
8745       }
8746       if (!aLightDel.IsNull())
8747       {
8748         aViewer->DelLight (aLightDel);
8749       }
8750     }
8751     else if (anArgCase.IsEqual ("COLOR")
8752           || anArgCase.IsEqual ("COLOUR"))
8753     {
8754       if (++anArgIt >= theArgsNb)
8755       {
8756         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8757         return 1;
8758       }
8759
8760       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8761       anArgNext.UpperCase();
8762       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
8763       if (!aLightCurr.IsNull())
8764       {
8765         aLightCurr->SetColor (aColor);
8766       }
8767     }
8768     else if (anArgCase.IsEqual ("POS")
8769           || anArgCase.IsEqual ("POSITION"))
8770     {
8771       if ((anArgIt + 3) >= theArgsNb)
8772       {
8773         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8774         return 1;
8775       }
8776
8777       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8778       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8779       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8780       if (!aLightDir.IsNull())
8781       {
8782         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8783       }
8784       else if (!aLightPos.IsNull())
8785       {
8786         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8787       }
8788       else if (!aLightSpot.IsNull())
8789       {
8790         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8791       }
8792       else
8793       {
8794         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8795         return 1;
8796       }
8797     }
8798     else if (anArgCase.IsEqual ("DIR")
8799           || anArgCase.IsEqual ("DIRECTION"))
8800     {
8801       if ((anArgIt + 3) >= theArgsNb)
8802       {
8803         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8804         return 1;
8805       }
8806
8807       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8808       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8809       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8810       if (!aLightDir.IsNull())
8811       {
8812         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8813       }
8814       else if (!aLightSpot.IsNull())
8815       {
8816         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8817       }
8818       else
8819       {
8820         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8821         return 1;
8822       }
8823     }
8824     else if (anArgCase.IsEqual ("SM")
8825           || anArgCase.IsEqual ("SMOOTHNESS"))
8826     {
8827       if (++anArgIt >= theArgsNb)
8828       {
8829         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8830         return 1;
8831       }
8832
8833       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
8834
8835       if (fabs (aSmoothness) < Precision::Confusion())
8836       {
8837         aLightCurr->SetIntensity (1.f);
8838       }
8839       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
8840       {
8841         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
8842       }
8843       else
8844       {
8845         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
8846         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
8847       }
8848
8849       if (!aLightPos.IsNull())
8850       {
8851         aLightPos->SetSmoothRadius (aSmoothness);
8852       }
8853       else if (!aLightDir.IsNull())
8854       {
8855         aLightDir->SetSmoothAngle (aSmoothness);
8856       }
8857     }
8858     else if (anArgCase.IsEqual ("INT")
8859           || anArgCase.IsEqual ("INTENSITY"))
8860     {
8861       if (++anArgIt >= theArgsNb)
8862       {
8863         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8864         return 1;
8865       }
8866
8867       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
8868
8869       if (!aLightCurr.IsNull())
8870       {
8871         aLightCurr->SetIntensity (aIntensity);
8872       }
8873     }
8874     else if (anArgCase.IsEqual ("ANG")
8875           || anArgCase.IsEqual ("ANGLE"))
8876     {
8877       if (++anArgIt >= theArgsNb)
8878       {
8879         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8880         return 1;
8881       }
8882
8883       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
8884
8885       if (!aLightSpot.IsNull())
8886       {
8887         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
8888       }
8889     }
8890     else if (anArgCase.IsEqual ("CONSTATTEN")
8891           || anArgCase.IsEqual ("CONSTATTENUATION"))
8892     {
8893       if (++anArgIt >= theArgsNb)
8894       {
8895         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8896         return 1;
8897       }
8898
8899       if (!aLightPos.IsNull())
8900       {
8901         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8902         anAtten[0] = Atof (theArgVec[anArgIt]);
8903         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8904       }
8905       else if (!aLightSpot.IsNull())
8906       {
8907         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8908         anAtten[0] = Atof (theArgVec[anArgIt]);
8909         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8910       }
8911       else
8912       {
8913         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8914         return 1;
8915       }
8916     }
8917     else if (anArgCase.IsEqual ("LINATTEN")
8918           || anArgCase.IsEqual ("LINEARATTEN")
8919           || anArgCase.IsEqual ("LINEARATTENUATION"))
8920     {
8921       if (++anArgIt >= theArgsNb)
8922       {
8923         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8924         return 1;
8925       }
8926
8927       if (!aLightPos.IsNull())
8928       {
8929         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8930         anAtten[1] = Atof (theArgVec[anArgIt]);
8931         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8932       }
8933       else if (!aLightSpot.IsNull())
8934       {
8935         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8936         anAtten[1] = Atof (theArgVec[anArgIt]);
8937         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8938       }
8939       else
8940       {
8941         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8942         return 1;
8943       }
8944     }
8945     else if (anArgCase.IsEqual ("EXP")
8946           || anArgCase.IsEqual ("EXPONENT")
8947           || anArgCase.IsEqual ("SPOTEXP")
8948           || anArgCase.IsEqual ("SPOTEXPONENT"))
8949     {
8950       if (++anArgIt >= theArgsNb)
8951       {
8952         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8953         return 1;
8954       }
8955
8956       if (!aLightSpot.IsNull())
8957       {
8958         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
8959       }
8960       else
8961       {
8962         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8963         return 1;
8964       }
8965     }
8966     else if (anArgCase.IsEqual ("HEAD")
8967           || anArgCase.IsEqual ("HEADLIGHT"))
8968     {
8969       if (++anArgIt >= theArgsNb)
8970       {
8971         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8972         return 1;
8973       }
8974
8975       if (aLightAmb.IsNull()
8976        && !aLightCurr.IsNull())
8977       {
8978         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
8979       }
8980       else
8981       {
8982         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8983         return 1;
8984       }
8985     }
8986     else
8987     {
8988       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
8989     }
8990   }
8991
8992   addLight (aLightNew, isGlobal);
8993   aViewer->UpdateLights();
8994
8995   return 0;
8996 }
8997
8998 //=======================================================================
8999 //function : VRenderParams
9000 //purpose  : Enables/disables rendering features
9001 //=======================================================================
9002
9003 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9004                                        Standard_Integer  theArgNb,
9005                                        const char**      theArgVec)
9006 {
9007   Handle(V3d_View) aView = ViewerTest::CurrentView();
9008   if (aView.IsNull())
9009   {
9010     std::cerr << "Error: no active viewer!\n";
9011     return 1;
9012   }
9013
9014   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9015   TCollection_AsciiString aCmdName (theArgVec[0]);
9016   aCmdName.LowerCase();
9017   if (aCmdName == "vraytrace")
9018   {
9019     if (theArgNb == 1)
9020     {
9021       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9022       return 0;
9023     }
9024     else if (theArgNb == 2)
9025     {
9026       TCollection_AsciiString aValue (theArgVec[1]);
9027       aValue.LowerCase();
9028       if (aValue == "on"
9029        || aValue == "1")
9030       {
9031         aParams.Method = Graphic3d_RM_RAYTRACING;
9032         aView->Redraw();
9033         return 0;
9034       }
9035       else if (aValue == "off"
9036             || aValue == "0")
9037       {
9038         aParams.Method = Graphic3d_RM_RASTERIZATION;
9039         aView->Redraw();
9040         return 0;
9041       }
9042       else
9043       {
9044         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9045         return 1;
9046       }
9047     }
9048     else
9049     {
9050       std::cout << "Error: wrong number of arguments\n";
9051       return 1;
9052     }
9053   }
9054
9055   if (theArgNb < 2)
9056   {
9057     theDI << "renderMode:  ";
9058     switch (aParams.Method)
9059     {
9060       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9061       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9062     }
9063     theDI << "\n";
9064     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9065     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9066     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9067     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9068     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9069     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9070     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9071     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9072     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9073     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9074     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9075     theDI << "shadingModel: ";
9076     switch (aView->ShadingModel())
9077     {
9078       case V3d_COLOR:   theDI << "color";   break;
9079       case V3d_FLAT:    theDI << "flat";    break;
9080       case V3d_GOURAUD: theDI << "gouraud"; break;
9081       case V3d_PHONG:   theDI << "phong";   break;
9082     }
9083     theDI << "\n";
9084     return 0;
9085   }
9086
9087   Standard_Boolean toPrint = Standard_False;
9088   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9089   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9090   {
9091     Standard_CString        anArg (theArgVec[anArgIter]);
9092     TCollection_AsciiString aFlag (anArg);
9093     aFlag.LowerCase();
9094     if (anUpdateTool.parseRedrawMode (aFlag))
9095     {
9096       continue;
9097     }
9098     else if (aFlag == "-echo"
9099           || aFlag == "-print")
9100     {
9101       toPrint = Standard_True;
9102       anUpdateTool.Invalidate();
9103     }
9104     else if (aFlag == "-mode"
9105           || aFlag == "-rendermode"
9106           || aFlag == "-render_mode")
9107     {
9108       if (toPrint)
9109       {
9110         switch (aParams.Method)
9111         {
9112           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9113           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9114         }
9115         continue;
9116       }
9117       else
9118       {
9119         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9120         return 1;
9121       }
9122     }
9123     else if (aFlag == "-ray"
9124           || aFlag == "-raytrace")
9125     {
9126       if (toPrint)
9127       {
9128         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9129         continue;
9130       }
9131
9132       aParams.Method = Graphic3d_RM_RAYTRACING;
9133     }
9134     else if (aFlag == "-rast"
9135           || aFlag == "-raster"
9136           || aFlag == "-rasterization")
9137     {
9138       if (toPrint)
9139       {
9140         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9141         continue;
9142       }
9143
9144       aParams.Method = Graphic3d_RM_RASTERIZATION;
9145     }
9146     else if (aFlag == "-msaa")
9147     {
9148       if (toPrint)
9149       {
9150         theDI << aParams.NbMsaaSamples << " ";
9151         continue;
9152       }
9153       else if (++anArgIter >= theArgNb)
9154       {
9155         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9156         return 1;
9157       }
9158
9159       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9160       if (aNbSamples < 0)
9161       {
9162         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9163         return 1;
9164       }
9165       else
9166       {
9167         aParams.NbMsaaSamples = aNbSamples;
9168       }
9169     }
9170     else if (aFlag == "-raydepth"
9171           || aFlag == "-ray_depth")
9172     {
9173       if (toPrint)
9174       {
9175         theDI << aParams.RaytracingDepth << " ";
9176         continue;
9177       }
9178       else if (++anArgIter >= theArgNb)
9179       {
9180         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9181         return 1;
9182       }
9183
9184       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9185
9186       // We allow RaytracingDepth be more than 10 in case of GI enabled
9187       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9188       {
9189         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9190         return 1;
9191       }
9192       else
9193       {
9194         aParams.RaytracingDepth = aDepth;
9195       }
9196     }
9197     else if (aFlag == "-shad"
9198           || aFlag == "-shadows")
9199     {
9200       if (toPrint)
9201       {
9202         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
9203         continue;
9204       }
9205
9206       Standard_Boolean toEnable = Standard_True;
9207       if (++anArgIter < theArgNb
9208       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9209       {
9210         --anArgIter;
9211       }
9212       aParams.IsShadowEnabled = toEnable;
9213     }
9214     else if (aFlag == "-refl"
9215           || aFlag == "-reflections")
9216     {
9217       if (toPrint)
9218       {
9219         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
9220         continue;
9221       }
9222
9223       Standard_Boolean toEnable = Standard_True;
9224       if (++anArgIter < theArgNb
9225       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9226       {
9227         --anArgIter;
9228       }
9229       aParams.IsReflectionEnabled = toEnable;
9230     }
9231     else if (aFlag == "-fsaa")
9232     {
9233       if (toPrint)
9234       {
9235         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
9236         continue;
9237       }
9238
9239       Standard_Boolean toEnable = Standard_True;
9240       if (++anArgIter < theArgNb
9241       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9242       {
9243         --anArgIter;
9244       }
9245       aParams.IsAntialiasingEnabled = toEnable;
9246     }
9247     else if (aFlag == "-gleam")
9248     {
9249       if (toPrint)
9250       {
9251         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
9252         continue;
9253       }
9254
9255       Standard_Boolean toEnable = Standard_True;
9256       if (++anArgIter < theArgNb
9257       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9258       {
9259         --anArgIter;
9260       }
9261       aParams.IsTransparentShadowEnabled = toEnable;
9262     }
9263     else if (aFlag == "-gi")
9264     {
9265       if (toPrint)
9266       {
9267         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
9268         continue;
9269       }
9270
9271       Standard_Boolean toEnable = Standard_True;
9272       if (++anArgIter < theArgNb
9273       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9274       {
9275         --anArgIter;
9276       }
9277       aParams.IsGlobalIlluminationEnabled = toEnable;
9278       if (!toEnable)
9279       {
9280         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
9281       }
9282     }
9283     else if (aFlag == "-blockedrng"
9284           || aFlag == "-brng")
9285     {
9286       if (toPrint)
9287       {
9288         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
9289         continue;
9290       }
9291
9292       Standard_Boolean toEnable = Standard_True;
9293       if (++anArgIter < theArgNb
9294         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9295       {
9296         --anArgIter;
9297       }
9298       aParams.CoherentPathTracingMode = toEnable;
9299     }
9300     else if (aFlag == "-iss")
9301     {
9302       if (toPrint)
9303       {
9304         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
9305         continue;
9306       }
9307
9308       Standard_Boolean toEnable = Standard_True;
9309       if (++anArgIter < theArgNb
9310         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9311       {
9312         --anArgIter;
9313       }
9314       aParams.AdaptiveScreenSampling = toEnable;
9315     }
9316     else if (aFlag == "-issd")
9317     {
9318       if (toPrint)
9319       {
9320         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
9321         continue;
9322       }
9323
9324       Standard_Boolean toEnable = Standard_True;
9325       if (++anArgIter < theArgNb
9326         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9327       {
9328         --anArgIter;
9329       }
9330       aParams.ShowSamplingTiles = toEnable;
9331     }
9332     else if (aFlag == "-env")
9333     {
9334       if (toPrint)
9335       {
9336         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
9337         continue;
9338       }
9339
9340       Standard_Boolean toEnable = Standard_True;
9341       if (++anArgIter < theArgNb
9342         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9343       {
9344         --anArgIter;
9345       }
9346       aParams.UseEnvironmentMapBackground = toEnable;
9347     }
9348     else if (aFlag == "-twoside")
9349     {
9350       if (toPrint)
9351       {
9352         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
9353         continue;
9354       }
9355
9356       Standard_Boolean toEnable = Standard_True;
9357       if (++anArgIter < theArgNb
9358         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9359       {
9360         --anArgIter;
9361       }
9362       aParams.TwoSidedBsdfModels = toEnable;
9363     }
9364     else if (aFlag == "-shademodel"
9365           || aFlag == "-shadingmodel"
9366           || aFlag == "-shading")
9367     {
9368       if (toPrint)
9369       {
9370         switch (aView->ShadingModel())
9371         {
9372           case V3d_COLOR:   theDI << "color ";   break;
9373           case V3d_FLAT:    theDI << "flat ";    break;
9374           case V3d_GOURAUD: theDI << "gouraud "; break;
9375           case V3d_PHONG:   theDI << "phong ";   break;
9376         }
9377         continue;
9378       }
9379
9380       if (++anArgIter >= theArgNb)
9381       {
9382         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9383       }
9384
9385       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9386       aMode.LowerCase();
9387       if (aMode == "color"
9388        || aMode == "none")
9389       {
9390         aView->SetShadingModel (V3d_COLOR);
9391       }
9392       else if (aMode == "flat"
9393             || aMode == "facet")
9394       {
9395         aView->SetShadingModel (V3d_FLAT);
9396       }
9397       else if (aMode == "gouraud"
9398             || aMode == "vertex"
9399             || aMode == "vert")
9400       {
9401         aView->SetShadingModel (V3d_GOURAUD);
9402       }
9403       else if (aMode == "phong"
9404             || aMode == "fragment"
9405             || aMode == "frag"
9406             || aMode == "pixel")
9407       {
9408         aView->SetShadingModel (V3d_PHONG);
9409       }
9410       else
9411       {
9412         std::cout << "Error: unknown shading model '" << aMode << "'\n";
9413         return 1;
9414       }
9415     }
9416     else if (aFlag == "-resolution")
9417     {
9418       if (++anArgIter >= theArgNb)
9419       {
9420         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9421         return 1;
9422       }
9423
9424       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
9425       if (aResolution.IsIntegerValue())
9426       {
9427         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
9428       }
9429       else
9430       {
9431         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9432         return 1;
9433       }
9434     }
9435     else if (aFlag == "-rebuildglsl"
9436           || aFlag == "-rebuild")
9437     {
9438       if (toPrint)
9439       {
9440         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
9441         continue;
9442       }
9443
9444       Standard_Boolean toEnable = Standard_True;
9445       if (++anArgIter < theArgNb
9446           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9447       {
9448         --anArgIter;
9449       }
9450       aParams.RebuildRayTracingShaders = toEnable;
9451     }
9452     else
9453     {
9454       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
9455       return 1;
9456     }
9457   }
9458
9459   return 0;
9460 }
9461
9462 //=======================================================================
9463 //function : VProgressiveMode
9464 //purpose  :
9465 //=======================================================================
9466 #if defined(_WIN32)
9467 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
9468                                           Standard_Integer  /*theNbArgs*/,
9469                                           const char**      /*theArgs*/)
9470 {
9471   Handle(V3d_View) aView = ViewerTest::CurrentView();
9472   if (aView.IsNull())
9473   {
9474     std::cerr << "Error: no active viewer!\n";
9475     return 1;
9476   }
9477
9478   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
9479
9480   for (;;)
9481   {
9482     aView->Redraw();
9483
9484     Standard_Boolean toExit = Standard_False;
9485
9486     MSG aMsg;
9487     while (PeekMessage (&aMsg, NULL, 0, 0, PM_REMOVE))
9488     {
9489       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
9490       {
9491         toExit = Standard_True;
9492       }
9493
9494       TranslateMessage (&aMsg);
9495       DispatchMessage  (&aMsg);
9496     }
9497
9498     if (toExit)
9499     {
9500       break;
9501     }
9502   }
9503
9504   return 0;
9505 }
9506 #endif
9507
9508 //=======================================================================
9509 //function : VFrustumCulling
9510 //purpose  : enables/disables view volume's culling.
9511 //=======================================================================
9512 static int VFrustumCulling (Draw_Interpretor& theDI,
9513                             Standard_Integer  theArgNb,
9514                             const char**      theArgVec)
9515 {
9516   Handle(V3d_View) aView = ViewerTest::CurrentView();
9517   if (aView.IsNull())
9518   {
9519     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
9520     return 1;
9521   }
9522
9523   if (theArgNb < 2)
9524   {
9525     theDI << (aView->IsCullingEnabled() ? "on" : "off");
9526     return 0;
9527   }
9528   else if (theArgNb != 2)
9529   {
9530     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
9531     return 1;
9532   }
9533
9534   TCollection_AsciiString aModeStr (theArgVec[1]);
9535   aModeStr.LowerCase();
9536   Standard_Boolean toEnable = 0;
9537   if (aModeStr == "on")
9538   {
9539     toEnable = 1;
9540   }
9541   else if (aModeStr == "off")
9542   {
9543     toEnable = 0;
9544   }
9545   else
9546   {
9547     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9548   }
9549
9550   aView->SetFrustumCulling (toEnable);
9551   aView->Redraw();
9552   return 0;
9553 }
9554
9555 //=======================================================================
9556 //function : VHighlightSelected
9557 //purpose  : 
9558 //=======================================================================
9559 static int VHighlightSelected (Draw_Interpretor& theDI,
9560                                Standard_Integer  theArgNb,
9561                                const char**      theArgVec)
9562 {
9563   if (ViewerTest::GetAISContext().IsNull())
9564   {
9565     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
9566     return 1;
9567   }
9568
9569   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9570
9571   if (theArgNb < 2)
9572   {
9573     theDI << (aContext->ToHilightSelected() ? "on" : "off");
9574     return 0;
9575   }
9576
9577   if (theArgNb != 2)
9578   {
9579     std::cout  << theArgVec[0] << " error : wrong number of parameters."
9580           << "Type 'help" << theArgVec[0] << "' for more information.";
9581     return 1;
9582   }
9583
9584   // Parse parameter
9585   TCollection_AsciiString aMode (theArgVec[1]);
9586   aMode.LowerCase();
9587   Standard_Boolean toEnable = Standard_False;
9588   if (aMode.IsEqual ("on"))
9589   {
9590     toEnable = Standard_True;
9591   }
9592   else if (aMode.IsEqual ("off"))
9593   {
9594     toEnable = Standard_False;
9595   }
9596   else
9597   {
9598     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9599   }
9600
9601   if (toEnable != aContext->ToHilightSelected())
9602   {
9603     aContext->SetToHilightSelected (toEnable);
9604
9605     // Move cursor to null position and  back to process updating of detection
9606     // and highlighting of selected object immediatly.
9607     Standard_Integer aPixX = 0;
9608     Standard_Integer aPixY = 0;
9609     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
9610
9611     anEventManager->GetCurrentPosition (aPixX, aPixY);
9612     anEventManager->MoveTo (0, 0);
9613     anEventManager->MoveTo (aPixX, aPixY);
9614   }
9615
9616   return 0;
9617 }
9618
9619 //=======================================================================
9620 //function : VXRotate
9621 //purpose  :
9622 //=======================================================================
9623 static Standard_Integer VXRotate (Draw_Interpretor& di,
9624                                    Standard_Integer argc,
9625                                    const char ** argv)
9626 {
9627   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9628   if (aContext.IsNull())
9629   {
9630     di << argv[0] << "ERROR : use 'vinit' command before \n";
9631     return 1;
9632   }
9633   
9634   if (argc != 3)
9635   {
9636     di << "ERROR : Usage : " << argv[0] << " name angle\n";
9637     return 1;
9638   }
9639
9640   TCollection_AsciiString aName (argv[1]);
9641   Standard_Real anAngle = Draw::Atof (argv[2]);
9642
9643   // find object
9644   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
9645   Handle(AIS_InteractiveObject) anIObj;
9646   if (!aMap.IsBound2 (aName) )
9647   {
9648     di << "Use 'vdisplay' before\n";
9649     return 1;
9650   }
9651   else
9652   {
9653     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
9654
9655     gp_Trsf aTransform;
9656     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
9657     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
9658
9659     aContext->SetLocation (anIObj, aTransform);
9660     aContext->UpdateCurrentViewer();
9661   }
9662
9663   return 0;
9664 }
9665
9666 //===============================================================================================
9667 //class   : ViewerTest_AISManipulator
9668 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
9669 //===============================================================================================
9670 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9671
9672 class ViewerTest_AISManipulator : public AIS_Manipulator
9673 {
9674 public:
9675
9676   ViewerTest_AISManipulator() : AIS_Manipulator()
9677   {
9678     GetMapOfAISManipulators().Add (this);
9679   }
9680
9681   virtual ~ViewerTest_AISManipulator()
9682   {
9683     GetMapOfAISManipulators().Remove (this);
9684   }
9685
9686   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9687 };
9688
9689 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9690 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9691
9692 //===============================================================================================
9693 //function : VManipulator
9694 //purpose  :
9695 //===============================================================================================
9696 static int VManipulator (Draw_Interpretor& theDi,
9697                          Standard_Integer  theArgsNb,
9698                          const char**      theArgVec)
9699 {
9700   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9701   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9702   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
9703   if (aView.IsNull()
9704    || aViewer.IsNull())
9705   {
9706     std::cerr << "No active viewer!\n";
9707     return 1;
9708   }
9709
9710   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
9711   Standard_Integer anArgIter = 1;
9712   for (; anArgIter < theArgsNb; ++anArgIter)
9713   {
9714     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
9715   }
9716
9717   ViewerTest_CmdParser aCmd;
9718   aCmd.AddDescription ("Manages manipulator for interactive objects:");
9719   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
9720   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
9721   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
9722   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
9723   aCmd.AddOption ("detach",         "...       - detach manipulator");
9724
9725   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
9726   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
9727   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
9728
9729   aCmd.AddOption ("move",   "... x y z - move object");
9730   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
9731   aCmd.AddOption ("scale",  "... factor - scale object");
9732
9733   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
9734   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
9735   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
9736   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
9737   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
9738   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
9739   aCmd.AddOption ("size",              "... size - set size of manipulator");
9740   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
9741
9742   aCmd.Parse (theArgsNb, theArgVec);
9743
9744   if (aCmd.HasOption ("help"))
9745   {
9746     theDi.PrintHelp (theArgVec[0]);
9747     return 0;
9748   }
9749
9750   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
9751
9752   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
9753
9754   if (aName.IsEmpty())
9755   {
9756     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
9757     return 1;
9758   }
9759
9760   // ----------------------------------
9761   // detach existing manipulator object
9762   // ----------------------------------
9763
9764   if (aCmd.HasOption ("detach"))
9765   {
9766     if (!aMapAIS.IsBound2 (aName))
9767     {
9768       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
9769       return 1;
9770     }
9771
9772     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9773     if (aManipulator.IsNull())
9774     {
9775       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9776       return 1;
9777     }
9778
9779     aManipulator->Detach();
9780     aMapAIS.UnBind2 (aName);
9781     ViewerTest::GetAISContext()->Remove (aManipulator);
9782
9783     return 0;
9784   }
9785
9786   // -----------------------------------------------
9787   // find or create manipulator if it does not exist
9788   // -----------------------------------------------
9789
9790   Handle(AIS_Manipulator) aManipulator;
9791   if (!aMapAIS.IsBound2 (aName))
9792   {
9793     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
9794
9795     aManipulator = new ViewerTest_AISManipulator();
9796     aMapAIS.Bind (aManipulator, aName);
9797   }
9798   else
9799   {
9800     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9801     if (aManipulator.IsNull())
9802     {
9803       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9804       return 1;
9805     }
9806   }
9807
9808   // -----------------------------------------
9809   // change properties of manipulator instance
9810   // -----------------------------------------
9811
9812   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
9813   {
9814     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
9815   }
9816   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
9817   {
9818     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
9819   }
9820   if (aCmd.HasOption ("followRotation", 1, Standard_True))
9821   {
9822     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
9823   }
9824   if (aCmd.HasOption ("gap", 1, Standard_True))
9825   {
9826     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
9827   }
9828   if (aCmd.HasOption ("part", 3, Standard_True))
9829   {
9830     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
9831     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
9832     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
9833     if (aMode < 1 || aMode > 3)
9834     {
9835       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
9836       return 1;
9837     }
9838
9839     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
9840   }
9841   if (aCmd.HasOption ("pos", 3, Standard_True))
9842   {
9843     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
9844     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
9845     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
9846
9847     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
9848   }
9849   if (aCmd.HasOption ("size", 1, Standard_True))
9850   {
9851     aManipulator->SetSize (aCmd.ArgFloat ("size"));
9852   }
9853   if (aCmd.HasOption ("zoomable", 1, Standard_True))
9854   {
9855     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
9856
9857     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
9858     {
9859       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
9860       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
9861     }
9862   }
9863
9864   // ---------------------------------------------------
9865   // attach, detach or access manipulator from an object
9866   // ---------------------------------------------------
9867
9868   if (aCmd.HasOption ("attach"))
9869   {
9870     // Find an object and attach manipulator to it
9871     if (!aCmd.HasOption ("attach", 1, Standard_True))
9872     {
9873       return 1;
9874     }
9875
9876     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
9877     if (!aMapAIS.IsBound2 (anObjName))
9878     {
9879       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
9880       return 1;
9881     }
9882
9883     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
9884     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
9885     for (; anIt.More(); anIt.Next())
9886     {
9887       if (anIt.Value()->IsAttached()
9888        && anIt.Value()->Object() == anObject)
9889       {
9890         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
9891         return 1;
9892       }
9893     }
9894
9895     AIS_Manipulator::OptionsForAttach anOptions;
9896     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
9897     {
9898       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
9899     }
9900     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
9901     {
9902       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
9903     }
9904     if (aCmd.HasOption ("enableModes", 1, Standard_True))
9905     {
9906       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
9907     }
9908
9909     aManipulator->Attach (anObject, anOptions);
9910   }
9911
9912   // --------------------------------------
9913   // apply transformation using manipulator
9914   // --------------------------------------
9915
9916   if (aCmd.HasOption ("startTransform", 2, Standard_True))
9917   {
9918     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
9919   }
9920   if (aCmd.HasOption ("transform", 2, Standard_True))
9921   {
9922     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
9923   }
9924   if (aCmd.HasOption ("stopTransform"))
9925   {
9926     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
9927
9928     aManipulator->StopTransform (toApply);
9929   }
9930
9931   gp_Trsf aT;
9932   if (aCmd.HasOption ("move", 3, Standard_True))
9933   {
9934     aT.SetTranslationPart (aCmd.ArgVec ("move"));
9935   }
9936   if (aCmd.HasOption ("rotate", 7, Standard_True))
9937   {
9938     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
9939   }
9940   if (aCmd.HasOption ("scale", 1))
9941   {
9942     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
9943   }
9944
9945   if (aT.Form() != gp_Identity)
9946   {
9947     aManipulator->Transform (aT);
9948   }
9949
9950   ViewerTest::GetAISContext()->Redisplay (aManipulator);
9951
9952   return 0;
9953 }
9954
9955 //===============================================================================================
9956 //function : parseColor
9957 //purpose  :
9958 //===============================================================================================
9959 static Standard_Boolean parseColor (ViewerTest_CmdParser& theParser,
9960                                     const std::string&    theOptionName,
9961                                     Quantity_Color&       theColor)
9962 {
9963   std::string aColorArg = theParser.Arg (theOptionName, 0);
9964   if (std::isdigit (aColorArg[0]))
9965   {
9966     Graphic3d_Vec3d aColor = theParser.ArgVec3d (theOptionName);
9967     if (aColor.x() < 0.0 || aColor.x() > 1.0
9968       || aColor.y() < 0.0 || aColor.y() > 1.0
9969       || aColor.z() < 0.0 || aColor.z() > 1.0)
9970     {
9971       std::cerr << "Error: RGB color values should be within range 0..1!\n";
9972       return Standard_False;
9973     }
9974     theColor.SetValues (aColor.x(), aColor.y(), aColor.z(), Quantity_TOC_RGB);
9975   }
9976   else
9977   {
9978     Quantity_NameOfColor aName = Quantity_NOC_BLACK;
9979     if (!Quantity_Color::ColorFromName (aColorArg.c_str(), aName))
9980     {
9981       std::cerr << "Name: " << theParser.Arg (theOptionName, 0)
9982                 << " does not correspond to any color in Quantity_NameOfColor!"
9983                 << std::endl;
9984       return Standard_False;
9985     }
9986     theColor.SetValues (aName);
9987   }
9988
9989   return Standard_True;
9990 }
9991
9992 //===============================================================================================
9993 //function : VSelectionProperties
9994 //purpose  :
9995 //===============================================================================================
9996 static int VSelectionProperties (Draw_Interpretor& theDi,
9997                                  Standard_Integer  theArgsNb,
9998                                  const char**      theArgVec)
9999 {
10000   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10001   if (aCtx.IsNull())
10002   {
10003     std::cerr << "No active viewer!\n";
10004     return 1;
10005   }
10006
10007   ViewerTest_CmdParser aCmd;
10008
10009   aCmd.AddOption ("autoActivate");
10010   aCmd.AddOption ("pixTol");
10011
10012   aCmd.AddOption ("selColor");
10013   aCmd.AddOption ("hiColor");
10014   aCmd.AddOption ("selTransp");
10015   aCmd.AddOption ("hiTransp");
10016
10017   aCmd.AddOption ("print");
10018
10019   aCmd.Parse (theArgsNb, theArgVec);
10020
10021   if (aCmd.HasOption ("help"))
10022   {
10023     theDi.PrintHelp (theArgVec[0]);
10024     return 0;
10025   }
10026
10027   if (aCmd.HasOption ("autoActivate", 1, Standard_False))
10028   {
10029     aCtx->SetAutoActivateSelection (aCmd.ArgBool ("autoActivate"));
10030   }
10031   if (aCmd.HasOption ("pixTol", 1, Standard_False))
10032   {
10033     aCtx->SetPixelTolerance (aCmd.ArgInt ("pixTol"));
10034   }
10035
10036   const Handle(Graphic3d_HighlightStyle)& aHiStyle  = aCtx->HighlightStyle();
10037   const Handle(Graphic3d_HighlightStyle)& aSelStyle = aCtx->SelectionStyle();
10038   Standard_Boolean toRedraw = Standard_False;
10039   if (aCmd.HasOption ("selColor"))
10040   {
10041     Quantity_Color aNewColor;
10042     if (!parseColor (aCmd, "selColor", aNewColor))
10043       return 1;
10044     aSelStyle->SetColor (aNewColor);
10045     toRedraw = Standard_True;
10046   }
10047   if (aCmd.HasOption ("hiColor"))
10048   {
10049     Quantity_Color aNewColor;
10050     if (!parseColor (aCmd, "hiColor", aNewColor))
10051       return 1;
10052     aHiStyle->SetColor (aNewColor);
10053   }
10054   if (aCmd.HasOption ("selTransp"))
10055   {
10056     aSelStyle->SetTransparency (aCmd.ArgFloat ("selTransp"));
10057     toRedraw = Standard_True;
10058   }
10059   if (aCmd.HasOption ("hiTransp"))
10060   {
10061     aHiStyle->SetTransparency (aCmd.ArgFloat ("hiTransp"));
10062   }
10063
10064   if (aCmd.HasOption ("print") || theArgsNb == 1)
10065   {
10066     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
10067     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
10068     theDi << "Selection color                : " << Quantity_Color::StringName (aCtx->SelectionStyle()->Color().Name()) << "\n";
10069     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aCtx->HighlightStyle()->Color().Name()) << "\n";
10070     theDi << "Selection transparency         : " << aCtx->SelectionStyle()->Transparency() << "\n";
10071     theDi << "Dynamic highlight transparency : " << aCtx->HighlightStyle()->Transparency() << "\n";
10072   }
10073
10074   if (aCtx->NbSelected() != 0 && toRedraw)
10075   {
10076     aCtx->HilightSelected (Standard_True);
10077   }
10078
10079   return 0;
10080 }
10081
10082 //=======================================================================
10083 //function : ViewerCommands
10084 //purpose  :
10085 //=======================================================================
10086
10087 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
10088 {
10089
10090   const char *group = "ZeViewer";
10091   theCommands.Add("vinit",
10092 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10093     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10094 #else
10095     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10096 #endif
10097     " - Creates new View window with specified name view_name.\n"
10098     "By default the new view is created in the viewer and in"
10099     " graphic driver shared with active view.\n"
10100     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
10101     "If driverName isn't specified the driver will be shared with active view.\n"
10102     "If viewerName isn't specified the viewer will be shared with active view.\n"
10103 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10104     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
10105     "is used in creation of graphic driver\n"
10106 #endif
10107     " - l, t: pixel position of left top corner of the window\n"
10108     " - w,h: width and heigth of window respectively.\n"
10109     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
10110     __FILE__,VInit,group);
10111   theCommands.Add("vclose" ,
10112     "[view_id [keep_context=0|1]]\n"
10113     "or vclose ALL - to remove all created views\n"
10114     " - removes view(viewer window) defined by its view_id.\n"
10115     " - keep_context: by default 0; if 1 and the last view is deleted"
10116     " the current context is not removed.",
10117     __FILE__,VClose,group);
10118   theCommands.Add("vactivate" ,
10119     "view_id"
10120     " - activates view(viewer window) defined by its view_id",
10121     __FILE__,VActivate,group);
10122   theCommands.Add("vviewlist",
10123     "vviewlist [format={tree, long}]"
10124     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
10125     " - format: format of result output, if tree the output is a tree view;"
10126     "otherwise it's a list of full view names. By default format = tree",
10127     __FILE__,VViewList,group);
10128   theCommands.Add("vhelp" ,
10129     "vhelp            : display help on the viewer commands",
10130     __FILE__,VHelp,group);
10131   theCommands.Add("vtop" ,
10132     "vtop or <T>      : Top view. Orientation +X+Y" ,
10133     __FILE__,VTop,group);
10134   theCommands.Add("vbottom" ,
10135     "vbottom          : Bottom view. Orientation +X-Y" ,
10136     __FILE__,VBottom,group);
10137   theCommands.Add("vleft" ,
10138     "vleft            : Left view. Orientation -Y+Z" ,
10139     __FILE__,VLeft,group);
10140   theCommands.Add("vright" ,
10141     "vright           : Right view. Orientation +Y+Z" ,
10142     __FILE__,VRight,group);
10143   theCommands.Add("vaxo" ,
10144     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
10145     __FILE__,VAxo,group);
10146   theCommands.Add("vfront" ,
10147     "vfront           : Front view. Orientation +X+Z" ,
10148     __FILE__,VFront,group);
10149   theCommands.Add("vback" ,
10150     "vback            : Back view. Orientation -X+Z" ,
10151     __FILE__,VBack,group);
10152   theCommands.Add("vpick" ,
10153     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
10154     VPick,group);
10155   theCommands.Add("vfit",
10156     "vfit or <F> [-selected] [-noupdate]"
10157     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
10158     __FILE__,VFit,group);
10159   theCommands.Add ("vfitarea",
10160     "vfitarea x1 y1 x2 y2"
10161     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
10162     "\n\t\t: Fit view to show area located between two points"
10163     "\n\t\t: given in world 2D or 3D corrdinates.",
10164     __FILE__, VFitArea, group);
10165   theCommands.Add ("vzfit", "vzfit [scale]\n"
10166     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
10167     "   \"scale\" - specifies factor to scale computed z range.\n",
10168     __FILE__, VZFit, group);
10169   theCommands.Add("vrepaint",
10170     "vrepaint        : vrepaint, force redraw",
10171     __FILE__,VRepaint,group);
10172   theCommands.Add("vclear",
10173     "vclear          : vclear"
10174     "\n\t\t: remove all the object from the viewer",
10175     __FILE__,VClear,group);
10176   theCommands.Add("vsetbg",
10177     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
10178     __FILE__,VSetBg,group);
10179   theCommands.Add("vsetbgmode",
10180     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
10181     __FILE__,VSetBgMode,group);
10182   theCommands.Add("vsetgradientbg",
10183     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
10184     __FILE__,VSetGradientBg,group);
10185   theCommands.Add("vsetgrbgmode",
10186     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
10187     __FILE__,VSetGradientBgMode,group);
10188   theCommands.Add("vsetcolorbg",
10189     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
10190     __FILE__,VSetColorBg,group);
10191   theCommands.Add("vsetdefaultbg",
10192     "vsetdefaultbg r g b\n"
10193     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
10194     "\n\t\t: Set default viewer background fill color (flat/gradient).",
10195     __FILE__,VSetDefaultBg,group);
10196   theCommands.Add("vscale",
10197     "vscale          : vscale X Y Z",
10198     __FILE__,VScale,group);
10199   theCommands.Add("vzbufftrihedron",
10200             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
10201     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
10202     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
10203     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
10204     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
10205     "\n\t\t: Displays a trihedron",
10206     __FILE__,VZBuffTrihedron,group);
10207   theCommands.Add("vrotate",
10208     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
10209     "\n                : Option -mouseStart starts rotation according to the mouse position"
10210     "\n                : Option -mouseMove continues rotation with angle computed"
10211     "\n                : from last and new mouse position."
10212     "\n                : vrotate AX AY AZ [X Y Z]",
10213     __FILE__,VRotate,group);
10214   theCommands.Add("vzoom",
10215     "vzoom           : vzoom coef",
10216     __FILE__,VZoom,group);
10217   theCommands.Add("vpan",
10218     "vpan            : vpan dx dy",
10219     __FILE__,VPan,group);
10220   theCommands.Add("vexport",
10221     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
10222     " : exports the view to a vector file of a given format"
10223     " : notice that EMF format requires patched gl2ps",
10224     __FILE__,VExport,group);
10225   theCommands.Add("vcolorscale",
10226     "vcolorscale     : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16  -textpos "
10227     "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n"
10228     "-demo/-demoversion draw a demoversion of color scale.\n"
10229     "-show/display display color scale.\n"
10230     "-hide/erase erase color scale.\n"
10231     "Please note that -show/-hide option must be the first argument!\n"
10232     "-color Index R G B: set color for indexed interval\n"
10233     "-color Index ColorName: set color for indexed interval\n"
10234     "-colors R G B R G B ...: set colors for all intervals\n"
10235     "-colors ColorName1 ColorName2 ...: set colors for all intervals\n"
10236     "-colors supports both color names and rgb values in one call\n"
10237     "-label Index Text: set label for indexed interval\n"
10238     "-labels Text Text Text ...: set labels for all intervals\n"
10239     "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n"
10240     "Available text positions: left, right, center, none;\n",
10241     __FILE__,VColorScale,group);
10242   theCommands.Add("vgraduatedtrihedron",
10243     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
10244     "\t[-namefont Name] [-valuesfont Name]\n"
10245     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
10246     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
10247     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
10248     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
10249     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
10250     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
10251     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
10252     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
10253     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
10254     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
10255     " - Displays or erases graduated trihedron"
10256     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
10257     " - namefont - font of axes names. Default: Arial\n"
10258     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
10259     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
10260     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
10261     " - valuesfont - font of axes values. Default: Arial\n"
10262     " - xcolor, ycolor, zcolor - color of axis and values\n"
10263     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
10264     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
10265     __FILE__,VGraduatedTrihedron,group);
10266   theCommands.Add("vtile" ,
10267             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
10268     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
10269     "\n\t\t:  -totalSize the size of virtual bigger viewport"
10270     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
10271     "\n\t\t:  -lowerLeft tile offset as lower left corner"
10272     "\n\t\t:  -upperLeft tile offset as upper left corner",
10273     __FILE__, VTile, group);
10274   theCommands.Add("vzlayer",
10275               "vzlayer [layerId]"
10276       "\n\t\t:         [-add|-delete|-get|-settings]"
10277       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
10278       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
10279       "\n\t\t: ZLayer list management:"
10280       "\n\t\t:   -add      add new z layer to viewer and print its id"
10281       "\n\t\t:   -delete   delete z layer"
10282       "\n\t\t:   -get      print sequence of z layers"
10283       "\n\t\t:   -settings print status of z layer settings"
10284       "\n\t\t:   -disable  disables given setting"
10285       "\n\t\t:   -enable   enables  given setting",
10286     __FILE__,VZLayer,group);
10287   theCommands.Add("vlayerline",
10288     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
10289     __FILE__,VLayerLine,group);
10290   theCommands.Add ("vgrid",
10291     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
10292     " : Mode - rectangular or circular"
10293     " : Type - lines or points",
10294     __FILE__, VGrid, group);
10295   theCommands.Add ("vpriviledgedplane",
10296     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
10297     "\n\t\t:   Ox, Oy, Oz - plane origin"
10298     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
10299     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
10300     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
10301     __FILE__, VPriviledgedPlane, group);
10302   theCommands.Add ("vconvert",
10303     "vconvert v [Mode={window|view}]"
10304     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
10305     "\n\t\t: vconvert x y z [Mode={window|grid}]"
10306     "\n\t\t:   window - convert to window coordinates, pixels"
10307     "\n\t\t:   view   - convert to view projection plane"
10308     "\n\t\t:   grid   - convert to model coordinates, given on grid"
10309     "\n\t\t:   ray    - convert projection ray to model coordiantes"
10310     "\n\t\t: - vconvert v window : convert view to window;"
10311     "\n\t\t: - vconvert v view   : convert window to view;"
10312     "\n\t\t: - vconvert x y window : convert view to window;"
10313     "\n\t\t: - vconvert x y view : convert window to view;"
10314     "\n\t\t: - vconvert x y : convert window to model;"
10315     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
10316     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
10317     "\n\t\t: - vconvert x y z window : convert model to window;"
10318     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
10319     "\n\t\t: Converts the given coordinates to window/view/model space.",
10320     __FILE__, VConvert, group);
10321   theCommands.Add ("vfps",
10322     "vfps [framesNb=100] : estimate average frame rate for active view",
10323     __FILE__, VFps, group);
10324   theCommands.Add ("vgldebug",
10325             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
10326     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
10327     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
10328     "\n\t\t: Debug context can be requested only on Windows"
10329     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
10330     "\n\t\t:  -sync     - request synchronized debug GL context"
10331     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
10332     "\n\t\t:              which are suppressed by default,"
10333     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
10334     "\n\t\t:              which are suppressed by default",
10335     __FILE__, VGlDebug, group);
10336   theCommands.Add ("vvbo",
10337     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
10338     __FILE__, VVbo, group);
10339   theCommands.Add ("vstereo",
10340             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
10341     "\n\t\t:         [-anaglyph Filter]"
10342     "\n\t\t: Control stereo output mode. Available modes for -mode:"
10343     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
10344     "\n\t\t:                     requires driver support."
10345     "\n\t\t:                     Should be called BEFORE vinit!"
10346     "\n\t\t:  anaglyph         - Anaglyph glasses"
10347     "\n\t\t:  rowInterlaced    - row-interlaced display"
10348     "\n\t\t:  columnInterlaced - column-interlaced display"
10349     "\n\t\t:  chessBoard       - chess-board output"
10350     "\n\t\t:  sideBySide       - horizontal pair"
10351     "\n\t\t:  overUnder        - vertical   pair"
10352     "\n\t\t: Available Anaglyph filters for -anaglyph:"
10353     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
10354     "\n\t\t:  greenMagentaSimple",
10355     __FILE__, VStereo, group);
10356   theCommands.Add ("vcaps",
10357             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
10358     "\n\t\t:       [-compatibleProfile {0|1}]"
10359     "\n\t\t:       [-vsync {0|1}]"
10360     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
10361     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
10362     "\n\t\t: Modify particular graphic driver options:"
10363     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
10364     "\n\t\t:             built-in GLSL programs"
10365     "\n\t\t:            (requires compatible profile)"
10366     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
10367     "\n\t\t:             arrays to GPU memory)"
10368     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
10369     "\n\t\t:  vsync    - switch VSync on or off"
10370     "\n\t\t: Context creation options:"
10371     "\n\t\t:  softMode          - software OpenGL implementation"
10372     "\n\t\t:  compatibleProfile - backward-compatible profile"
10373     "\n\t\t:  quadbuffer        - QuadBuffer"
10374     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
10375     "\n\t\t: rendering paths producing the same visual result when"
10376     "\n\t\t: possible."
10377     "\n\t\t: Command is intended for testing old hardware compatibility.",
10378     __FILE__, VCaps, group);
10379   theCommands.Add ("vmemgpu",
10380     "vmemgpu [f]: print system-dependent GPU memory information if available;"
10381     " with f option returns free memory in bytes",
10382     __FILE__, VMemGpu, group);
10383   theCommands.Add ("vreadpixel",
10384     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
10385     " : Read pixel value for active view",
10386     __FILE__, VReadPixel, group);
10387   theCommands.Add("diffimage",
10388     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
10389     __FILE__, VDiffImage, group);
10390   theCommands.Add ("vselect",
10391     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
10392     "- emulates different types of selection:\n"
10393     "- 1) single click selection\n"
10394     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
10395     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
10396     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
10397     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
10398     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
10399     " (partial inclusion - overlap - is not allowed by default)\n"
10400     "- 5) any of these selections with shift button pressed",
10401     __FILE__, VSelect, group);
10402   theCommands.Add ("vmoveto",
10403     "vmoveto x y"
10404     "- emulates cursor movement to pixel postion (x,y)",
10405     __FILE__, VMoveTo, group);
10406   theCommands.Add ("vviewparams",
10407               "vviewparams [-args] [-scale [s]]"
10408       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
10409       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
10410       "\n\t\t: Manage current view parameters or prints all"
10411       "\n\t\t: current values when called without argument."
10412       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
10413       "\n\t\t:   -eye  [x y z] prints or sets eye location"
10414       "\n\t\t:   -at   [x y z] prints or sets center of look"
10415       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
10416       "\n\t\t:   -proj [x y z] prints or sets direction of look"
10417       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
10418       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
10419       "\n\t\t:                 or changes the size of its maximum dimension"
10420       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
10421     __FILE__, VViewParams, group);
10422
10423   theCommands.Add("vanimation", "Alias for vanim",
10424     __FILE__, VAnimation, group);
10425
10426   theCommands.Add("vanim",
10427             "List existing animations:"
10428     "\n\t\t:  vanim"
10429     "\n\t\t: Animation playback:"
10430     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
10431     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
10432     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
10433     "\n\t\t:   -freeLook skip camera animations"
10434     "\n\t\t:   -lockLoop disable any interactions"
10435     "\n\t\t:"
10436     "\n\t\t: Animation definition:"
10437     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
10438     "\n\t\t:        [start TimeSec] [duration TimeSec]"
10439     "\n\t\t:"
10440     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
10441     "\n\t\t: specifies nested animations."
10442     "\n\t\t: There is no syntax to explicitly add new animation,"
10443     "\n\t\t: and all non-existing animations within the name will be"
10444     "\n\t\t: implicitly created on first use (including parents)."
10445     "\n\t\t:"
10446     "\n\t\t: Each animation might define the SINGLE action (see below),"
10447     "\n\t\t: like camera transition, object transformation or custom callback."
10448     "\n\t\t: Child animations can be used for defining concurrent actions."
10449     "\n\t\t:"
10450     "\n\t\t: Camera animation:"
10451     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
10452     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
10453     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
10454     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
10455     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
10456     "\n\t\t:   -atX    camera Center positions pair"
10457     "\n\t\t:   -upX    camera Up directions pair"
10458     "\n\t\t:   -scaleX camera Scale factors pair"
10459     "\n\t\t: Object animation:"
10460     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
10461     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
10462     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
10463     "\n\t\t:   -locX   object Location points pair (translation)"
10464     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
10465     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
10466     "\n\t\t: Custom callback:"
10467     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
10468     "\n\t\t:   %Pts        overall animation presentation timestamp"
10469     "\n\t\t:   %LocalPts   local animation timestamp"
10470     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
10471     __FILE__, VAnimation, group);
10472
10473   theCommands.Add("vchangeselected",
10474     "vchangeselected shape"
10475     "- adds to shape to selection or remove one from it",
10476                 __FILE__, VChangeSelected, group);
10477   theCommands.Add ("vnbselected",
10478     "vnbselected"
10479     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
10480   theCommands.Add ("vcamera",
10481               "vcamera [-ortho] [-projtype]"
10482       "\n\t\t:         [-persp]"
10483       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
10484       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
10485       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
10486       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
10487       "\n\t\t: Manage camera parameters."
10488       "\n\t\t: Prints current value when option called without argument."
10489       "\n\t\t: Orthographic camera:"
10490       "\n\t\t:   -ortho      activate orthographic projection"
10491       "\n\t\t: Perspective camera:"
10492       "\n\t\t:   -persp      activate perspective  projection (mono)"
10493       "\n\t\t:   -fovy       field of view in y axis, in degrees"
10494       "\n\t\t:   -distance   distance of eye from camera center"
10495       "\n\t\t: Stereoscopic camera:"
10496       "\n\t\t:   -stereo     perspective  projection (stereo)"
10497       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
10498       "\n\t\t:   -rightEye   perspective  projection (right eye)"
10499       "\n\t\t:   -iod        intraocular distance value"
10500       "\n\t\t:   -iodType    distance type, absolute or relative"
10501       "\n\t\t:   -zfocus     stereographic focus value"
10502       "\n\t\t:   -zfocusType focus type, absolute or relative",
10503     __FILE__, VCamera, group);
10504   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
10505     "- vautozfit [on={1|0}] [scale]\n"
10506     "    Prints or changes parameters of automatic z-fit mode:\n"
10507     "   \"on\" - turns automatic z-fit on or off\n"
10508     "   \"scale\" - specifies factor to scale computed z range.\n",
10509     __FILE__, VAutoZFit, group);
10510   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
10511     "   vzrange                - without parameters shows current values\n"
10512     "   vzrange [znear] [zfar] - applies provided values to view",
10513     __FILE__,VZRange, group);
10514   theCommands.Add ("vpurgedisplay",
10515     "vpurgedisplay"
10516     "- removes structures which don't belong to objects displayed in neutral point",
10517     __FILE__, VPurgeDisplay, group);
10518   theCommands.Add("vsetviewsize",
10519     "vsetviewsize size",
10520     __FILE__,VSetViewSize,group);
10521   theCommands.Add("vmoveview",
10522     "vmoveview Dx Dy Dz [Start = 1|0]",
10523     __FILE__,VMoveView,group);
10524   theCommands.Add("vtranslateview",
10525     "vtranslateview Dx Dy Dz [Start = 1|0)]",
10526     __FILE__,VTranslateView,group);
10527   theCommands.Add("vturnview",
10528     "vturnview Ax Ay Az [Start = 1|0]",
10529     __FILE__,VTurnView,group);
10530   theCommands.Add("vtextureenv",
10531     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
10532     "or user-defined file and optionally applying texture mapping parameters\n"
10533     "                  Usage:\n"
10534     "                  vtextureenv off - disables environment mapping\n"
10535     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
10536     "                              std_texture = (0..7)\n"
10537     "                              rep         = {clamp|repeat}\n"
10538     "                              mod         = {decal|modulate}\n"
10539     "                              flt         = {nearest|bilinear|trilinear}\n"
10540     "                              ss, st      - scale factors for s and t texture coordinates\n"
10541     "                              ts, tt      - translation for s and t texture coordinates\n"
10542     "                              rot         - texture rotation angle in degrees",
10543     __FILE__, VTextureEnv, group);
10544   theCommands.Add("vhlr" ,
10545     "is_enabled={on|off} [show_hidden={1|0}]"
10546     " - Hidden line removal algorithm:"
10547     " - is_enabled: if is on HLR algorithm is applied\n"
10548     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
10549     __FILE__,VHLR,group);
10550   theCommands.Add("vhlrtype" ,
10551     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
10552     " - Changes the type of HLR algorithm using for shapes."
10553     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
10554     "   if equals to polyalgo, polygonal HLR algorithm is applied."
10555     "If shapes are not given HLR algoithm of given type is applied"
10556     " to all shapes in the view\n",
10557     __FILE__,VHLRType,group);
10558   theCommands.Add("vclipplane",
10559               "vclipplane planeName [{0|1}]"
10560       "\n\t\t:   [-equation A B C D]"
10561       "\n\t\t:   [-set|-unset [objects|views]]"
10562       "\n\t\t:   [-maxPlanes]"
10563       "\n\t\t:   [-capping {0|1}]"
10564       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
10565       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
10566       "\n\t\t:       [-texRotate Angle]"
10567       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
10568       "\n\t\t:       [-useObjShader {0|1}]"
10569       "\n\t\t: Clipping planes management:"
10570       "\n\t\t:   -maxPlanes   print plane limit for view"
10571       "\n\t\t:   -delete      delete plane with given name"
10572       "\n\t\t:   {off|on|0|1} turn clipping on/off"
10573       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
10574       "\n\t\t:                applied to active View when list is omitted"
10575       "\n\t\t:   -equation A B C D change plane equation"
10576       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
10577       "\n\t\t: Capping options:"
10578       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
10579       "\n\t\t:   -color R G B          set capping color"
10580       "\n\t\t:   -texName Texture      set capping texture"
10581       "\n\t\t:   -texScale SX SY       set capping tex scale"
10582       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
10583       "\n\t\t:   -texRotate Angle      set capping tex rotation"
10584       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
10585       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
10586       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
10587       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
10588       __FILE__, VClipPlane, group);
10589   theCommands.Add("vdefaults",
10590                "vdefaults [-absDefl value]"
10591        "\n\t\t:           [-devCoeff value]"
10592        "\n\t\t:           [-angDefl value]"
10593        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
10594     , __FILE__, VDefaults, group);
10595   theCommands.Add("vlight",
10596     "tool to manage light sources, without arguments shows list of lights."
10597     "\n    Main commands: "
10598     "\n      'clear' to clear lights"
10599     "\n      '{def}aults' to load deafault lights"
10600     "\n      'add' (or 'new') <type> to add any light source"
10601     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
10602     "\n      'change' <lightId> to edit light source with specified lightId"
10603     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
10604     "\n        {pos}ition X Y Z"
10605     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
10606     "\n        color colorName"
10607     "\n        {head}light 0|1"
10608     "\n        {sm}oothness value"
10609     "\n        {int}ensity value"
10610     "\n        {constAtten}uation value"
10611     "\n        {linearAtten}uation value"
10612     "\n        angle angleDeg"
10613     "\n        {spotexp}onent value"
10614     "\n        local|global"
10615     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
10616     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
10617     __FILE__, VLight, group);
10618   theCommands.Add("vraytrace",
10619             "vraytrace [0|1]"
10620     "\n\t\t: Turns on/off ray-tracing renderer."
10621     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
10622     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
10623     __FILE__, VRenderParams, group);
10624   theCommands.Add("vrenderparams",
10625     "\n    Manages rendering parameters: "
10626     "\n      '-raster'               Disables GPU ray-tracing"
10627     "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
10628     "\n      '-rayTrace'             Enables  GPU ray-tracing"
10629     "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
10630     "\n      '-shadows      on|off'  Enables/disables shadows rendering"
10631     "\n      '-reflections  on|off'  Enables/disables specular reflections"
10632     "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
10633     "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
10634     "\n      '-gi           on|off'  Enables/disables global illumination effects"
10635     "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
10636     "\n      '-env          on|off'  Enables/disables environment map background"
10637     "\n      '-twoside      on|off'  Enables/disables two-sided BSDF models (PT mode)"
10638     "\n      '-iss          on|off'  Enables/disables adaptive screen sampling (PT mode)"
10639     "\n      '-issd         on|off'  Shows screen sampling distribution in ISS mode"
10640     "\n      '-rebuildGlsl  on|off'  Rebuild Ray-Tracing GLSL programs (for debugging)"
10641     "\n      '-shadingModel model'   Controls shading model from enumeration"
10642     "\n                              color, flat, gouraud, phong"
10643     "\n      '-resolution   value'   Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
10644     "\n    Unlike vcaps, these parameters dramatically change visual properties."
10645     "\n    Command is intended to control presentation quality depending on"
10646     "\n    hardware capabilities and performance.",
10647     __FILE__, VRenderParams, group);
10648   theCommands.Add("vfrustumculling",
10649     "vfrustumculling [toEnable]: enables/disables objects clipping",
10650     __FILE__,VFrustumCulling,group);
10651   theCommands.Add("vhighlightselected",
10652     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
10653     "Without arguments it shows if highlighting of selected objects is enabled now.",
10654     __FILE__,VHighlightSelected,group);
10655   theCommands.Add ("vplace",
10656             "vplace dx dy"
10657     "\n\t\t: Places the point (in pixels) at the center of the window",
10658     __FILE__, VPlace, group);
10659   theCommands.Add("vxrotate",
10660     "vxrotate",
10661     __FILE__,VXRotate,group);
10662
10663     theCommands.Add("vmanipulator",
10664       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
10665       "\n    tool to create and manage AIS manipulators."
10666       "\n    Options: "
10667       "\n      '-attach AISObject'                 attach manipulator to AISObject"
10668       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
10669       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
10670       "\n      '-enableModes    {0|1}'             enable modes when attaching"
10671       "\n      '-detach'                           detach manipulator"
10672       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
10673       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
10674       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
10675       "\n      '-move x y z'                     - move attached object"
10676       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
10677       "\n      '-scale factor'                   - scale attached object"
10678       "\n      '-autoActivate      {0|1}'        - set activation on detection"
10679       "\n      '-followTranslation {0|1}'        - set following translation transform"
10680       "\n      '-followRotation    {0|1}'        - set following rotation transform"
10681       "\n      '-gap value'                      - set gap between sub-parts"
10682       "\n      '-part axis mode    {0|1}'        - set visual part"
10683       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
10684       "\n      '-size value'                     - set size of manipulator"
10685       "\n      '-zoomable {0|1}'                 - set zoom persistence",
10686     __FILE__, VManipulator, group);
10687
10688   theCommands.Add("vselprops",
10689     "\n    vselprops [options]"
10690     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
10691     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
10692     "\n    -pixTol    value        : sets up pixel tolerance"
10693     "\n    -selColor  {name|r g b} : sets selection color"
10694     "\n    -hiColor   {name|r g b} : sets dynamic highlight color"
10695     "\n    -selTransp value        : sets transparency coefficient for selection"
10696     "\n    -hiTransp  value        : sets transparency coefficient for dynamic highlight"
10697     "\n    -print                  : prints current state of all mentioned parameters",
10698     __FILE__, VSelectionProperties, group);
10699
10700 #if defined(_WIN32)
10701   theCommands.Add("vprogressive",
10702     "vprogressive",
10703     __FILE__, VProgressiveMode, group);
10704 #endif
10705 }