6ac6cc65bf482827391752bb28b4c74c9b8cae22
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_ColorScale.hxx>
23 #include <AIS_Manipulator.hxx>
24 #include <AIS_RubberBand.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_InteractiveObject.hxx>
27 #include <AIS_ListOfInteractive.hxx>
28 #include <AIS_ListIteratorOfListOfInteractive.hxx>
29 #include <DBRep.hxx>
30 #include <Graphic3d_ArrayOfPolylines.hxx>
31 #include <Graphic3d_AspectMarker3d.hxx>
32 #include <Graphic3d_ExportFormat.hxx>
33 #include <Graphic3d_NameOfTextureEnv.hxx>
34 #include <Graphic3d_GraduatedTrihedron.hxx>
35 #include <Graphic3d_TextureEnv.hxx>
36 #include <Graphic3d_TextureParams.hxx>
37 #include <Graphic3d_TypeOfTextureFilter.hxx>
38 #include <Graphic3d_AspectFillArea3d.hxx>
39 #include <ViewerTest.hxx>
40 #include <ViewerTest_AutoUpdater.hxx>
41 #include <ViewerTest_EventManager.hxx>
42 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
43 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_CmdParser.hxx>
45 #include <V3d_AmbientLight.hxx>
46 #include <V3d_DirectionalLight.hxx>
47 #include <V3d_PositionalLight.hxx>
48 #include <V3d_SpotLight.hxx>
49 #include <NCollection_DoubleMap.hxx>
50 #include <NCollection_List.hxx>
51 #include <NCollection_Vector.hxx>
52 #include <AIS_InteractiveContext.hxx>
53 #include <Draw_Interpretor.hxx>
54 #include <Draw.hxx>
55 #include <Draw_Appli.hxx>
56 #include <Image_AlienPixMap.hxx>
57 #include <OpenGl_GraphicDriver.hxx>
58 #include <OSD_Timer.hxx>
59 #include <TColStd_HSequenceOfAsciiString.hxx>
60 #include <TColStd_SequenceOfInteger.hxx>
61 #include <TColStd_HSequenceOfReal.hxx>
62 #include <TColgp_Array1OfPnt2d.hxx>
63 #include <TColStd_MapOfAsciiString.hxx>
64 #include <Aspect_TypeOfLine.hxx>
65 #include <Image_Diff.hxx>
66 #include <Aspect_DisplayConnection.hxx>
67 #include <gp_Pnt.hxx>
68 #include <gp_Dir.hxx>
69 #include <gp_Pln.hxx>
70 #include <PrsMgr_PresentableObject.hxx>
71 #include <Graphic3d_ClipPlane.hxx>
72 #include <NCollection_DataMap.hxx>
73 #include <Graphic3d_Texture2Dmanual.hxx>
74 #include <Prs3d_ShadingAspect.hxx>
75 #include <Prs3d_Drawer.hxx>
76 #include <Prs3d_LineAspect.hxx>
77 #include <Prs3d_Root.hxx>
78
79 #ifdef _WIN32
80 #undef DrawText
81 #endif
82
83 #include <cstdlib>
84
85 #if defined(_WIN32)
86   #include <WNT_WClass.hxx>
87   #include <WNT_Window.hxx>
88 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
89   #include <Cocoa_Window.hxx>
90 #else
91   #include <Xw_Window.hxx>
92   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
93   #include <X11/Xutil.h>
94   #include <tk.h>
95 #endif
96
97 // Auxiliary definitions
98 static const char THE_KEY_DELETE = 127;
99
100 //==============================================================================
101 //  VIEWER GLOBAL VARIABLES
102 //==============================================================================
103
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
106
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
109
110 extern int VErase (Draw_Interpretor& theDI,
111                    Standard_Integer  theArgNb,
112                    const char**      theArgVec);
113
114 #if defined(_WIN32)
115 static Handle(WNT_Window)& VT_GetWindow() {
116   static Handle(WNT_Window) WNTWin;
117   return WNTWin;
118 }
119 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
120 static Handle(Cocoa_Window)& VT_GetWindow()
121 {
122   static Handle(Cocoa_Window) aWindow;
123   return aWindow;
124 }
125 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
126 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
127 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
128
129 #else
130 static Handle(Xw_Window)& VT_GetWindow(){
131   static Handle(Xw_Window) XWWin;
132   return XWWin;
133 }
134
135 static void VProcessEvents(ClientData,int);
136 #endif
137
138 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
139 {
140   static Handle(Aspect_DisplayConnection) aDisplayConnection;
141   return aDisplayConnection;
142 }
143
144 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
145 {
146   GetDisplayConnection() = theDisplayConnection;
147 }
148
149 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
150 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
151 {
152   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
153 #if defined(_WIN32)
154   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156     return aWindow->HWindow();
157 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
158   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
159   if (!aWindow.IsNull())
160   return aWindow->XWindow();
161 #endif
162   return aWindowHandle;
163 }
164 #endif
165
166 static Standard_Boolean MyHLRIsOn = Standard_False;
167
168 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
169 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
170 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
171 static OpenGl_Caps ViewerTest_myDefaultCaps;
172
173 static void OSWindowSetup();
174
175 static struct
176 {
177   Quantity_Color FlatColor;
178   Quantity_Color GradientColor1;
179   Quantity_Color GradientColor2;
180   Aspect_GradientFillMethod FillMethod;
181 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
182
183 //==============================================================================
184 //  EVENT GLOBAL VARIABLES
185 //==============================================================================
186
187 static int Start_Rot = 0;
188 int X_Motion = 0; // Current cursor position
189 int Y_Motion = 0;
190 int X_ButtonPress = 0; // Last ButtonPress position
191 int Y_ButtonPress = 0;
192 Standard_Boolean IsDragged = Standard_False;
193 Standard_Boolean DragFirst = Standard_False;
194 Standard_Boolean TheIsAnimating = Standard_False;
195
196
197 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
198 {
199   static Handle(AIS_RubberBand) aBand;
200   if (aBand.IsNull())
201   {
202     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
203     aBand->SetDisplayMode (0);
204   }
205   return aBand;
206 }
207
208 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
209
210 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
211 {
212   static ViewerTest_MapOfAISManipulators aMap;
213   return aMap;
214 }
215
216 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
217 {
218   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
219   for (; anIt.More(); anIt.Next())
220   {
221     if (anIt.Value()->HasActiveMode())
222     {
223       return anIt.Value();
224     }
225   }
226   return NULL;
227 }
228
229 //==============================================================================
230
231 #ifdef _WIN32
232 static LRESULT WINAPI ViewerWindowProc(
233                                        HWND hwnd,
234                                        UINT uMsg,
235                                        WPARAM wParam,
236                                        LPARAM lParam );
237 static LRESULT WINAPI AdvViewerWindowProc(
238   HWND hwnd,
239   UINT uMsg,
240   WPARAM wParam,
241   LPARAM lParam );
242 #endif
243
244
245 //==============================================================================
246 //function : WClass
247 //purpose  :
248 //==============================================================================
249
250 const Handle(Standard_Transient)& ViewerTest::WClass()
251 {
252   static Handle(Standard_Transient) theWClass;
253 #if defined(_WIN32)
254   if (theWClass.IsNull())
255   {
256     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
257                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
258                                 ::LoadCursorW (NULL, IDC_ARROW));
259   }
260 #endif
261   return theWClass;
262 }
263
264 //==============================================================================
265 //function : CreateName
266 //purpose  : Create numerical name for new object in theMap
267 //==============================================================================
268 template <typename ObjectType>
269 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
270                                     const TCollection_AsciiString& theDefaultString)
271 {
272   if (theObjectMap.IsEmpty())
273     return theDefaultString + TCollection_AsciiString(1);
274
275   Standard_Integer aNextKey = 1;
276   Standard_Boolean isFound = Standard_False;
277   while (!isFound)
278   {
279     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
280     // Look for objects with default names
281     if (theObjectMap.IsBound1(aStringKey))
282     {
283       aNextKey++;
284     }
285     else
286       isFound = Standard_True;
287   }
288
289   return theDefaultString + TCollection_AsciiString(aNextKey);
290 }
291
292 //==============================================================================
293 //structure : ViewerTest_Names
294 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
295 //==============================================================================
296 struct ViewerTest_Names
297 {
298 private:
299   TCollection_AsciiString myDriverName;
300   TCollection_AsciiString myViewerName;
301   TCollection_AsciiString myViewName;
302
303 public:
304
305   const TCollection_AsciiString& GetDriverName () const
306   {
307     return myDriverName;
308   }
309   void SetDriverName (const TCollection_AsciiString& theDriverName)
310   {
311     myDriverName = theDriverName;
312   }
313   const TCollection_AsciiString& GetViewerName () const
314   {
315     return myViewerName;
316   }
317   void SetViewerName (const TCollection_AsciiString& theViewerName)
318   {
319     myViewerName = theViewerName;
320   }
321   const TCollection_AsciiString& GetViewName () const
322   {
323     return myViewName;
324   }
325   void SetViewName (const TCollection_AsciiString& theViewName)
326   {
327     myViewName = theViewName;
328   }
329
330   //===========================================================================
331   //function : Constructor for ViewerTest_Names
332   //purpose  : Get view, viewer, driver names from custom string
333   //===========================================================================
334
335   ViewerTest_Names (const TCollection_AsciiString& theInputString)
336   {
337     TCollection_AsciiString aName(theInputString);
338     if (theInputString.IsEmpty())
339     {
340       // Get current configuration
341       if (ViewerTest_myDrivers.IsEmpty())
342         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
343           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
344       else
345         myDriverName = ViewerTest_myDrivers.Find2
346         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
347
348       if(ViewerTest_myContexts.IsEmpty())
349       {
350         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
351           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
352       }
353       else
354       {
355         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
356       }
357
358       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
359     }
360     else
361     {
362       // There is at least view name
363       Standard_Integer aParserNumber = 0;
364       for (Standard_Integer i = 0; i < 3; ++i)
365       {
366         Standard_Integer aParserPos = aName.SearchFromEnd("/");
367         if(aParserPos != -1)
368         {
369           aParserNumber++;
370           aName.Split(aParserPos-1);
371         }
372         else
373           break;
374       }
375       if (aParserNumber == 0)
376       {
377         // Only view name
378         if (!ViewerTest::GetAISContext().IsNull())
379         {
380           myDriverName = ViewerTest_myDrivers.Find2
381           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
382           myViewerName = ViewerTest_myContexts.Find2
383           (ViewerTest::GetAISContext());
384         }
385         else
386         {
387           // There is no opened contexts here, need to create names for viewer and driver
388           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
389             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
390
391           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
392             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
393         }
394         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
395       }
396       else if (aParserNumber == 1)
397       {
398         // Here is viewerName/viewName
399         if (!ViewerTest::GetAISContext().IsNull())
400           myDriverName = ViewerTest_myDrivers.Find2
401           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
402         else
403         {
404           // There is no opened contexts here, need to create name for driver
405           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
406             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
407         }
408         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
409
410         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
411       }
412       else
413       {
414         //Here is driverName/viewerName/viewName
415         myDriverName = TCollection_AsciiString(aName);
416
417         TCollection_AsciiString aViewerName(theInputString);
418         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
419         myViewerName = TCollection_AsciiString(aViewerName);
420
421         myViewName = TCollection_AsciiString(theInputString);
422       }
423     }
424   }
425 };
426
427 //==============================================================================
428 //function : FindContextByView
429 //purpose  : Find AIS_InteractiveContext by View
430 //==============================================================================
431
432 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
433 {
434   Handle(AIS_InteractiveContext) anAISContext;
435
436   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
437        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
438   {
439     if (anIter.Value()->CurrentViewer() == theView->Viewer())
440        return anIter.Key2();
441   }
442   return anAISContext;
443 }
444
445
446 //==============================================================================
447 //function : SetWindowTitle
448 //purpose  : Set window title
449 //==============================================================================
450
451 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
452                      Standard_CString theTitle)
453 {
454 #if defined(_WIN32)
455   const TCollection_ExtendedString theTitleW (theTitle);
456   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
457 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
458   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
459 #else
460   if(GetDisplayConnection()->GetDisplay())
461   {
462     Window aWindow =
463       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
464     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
465   }
466 #endif
467 }
468
469 //==============================================================================
470 //function : IsWindowOverlapped
471 //purpose  : Check if theWindow overlapp another view
472 //==============================================================================
473
474 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
475                                      const Standard_Integer thePxTop,
476                                      const Standard_Integer thePxRight,
477                                      const Standard_Integer thePxBottom,
478                                      TCollection_AsciiString& theViewId)
479 {
480   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
481       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
482   {
483     Standard_Integer aTop = 0,
484       aLeft = 0,
485       aRight = 0,
486       aBottom = 0;
487     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
488     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
489         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
490         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
491         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
492     {
493       theViewId = anIter.Key1();
494       return Standard_True;
495     }
496   }
497   return Standard_False;
498 }
499
500 // Workaround: to create and delete non-orthographic views outside ViewerTest
501 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
502 {
503   ViewerTest_myViews.UnBind1 (theName);
504 }
505
506 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
507                                const Handle(V3d_View)& theView)
508 {
509   ViewerTest_myViews.Bind (theName, theView);
510 }
511
512 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
513 {
514   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
515 }
516 //==============================================================================
517 //function : ViewerInit
518 //purpose  : Create the window viewer and initialize all the global variable
519 //==============================================================================
520
521 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
522                                                 const Standard_Integer thePxTop,
523                                                 const Standard_Integer thePxWidth,
524                                                 const Standard_Integer thePxHeight,
525                                                 Standard_CString theViewName,
526                                                 Standard_CString theDisplayName)
527 {
528   // Default position and dimension of the viewer window.
529   // Note that left top corner is set to be sufficiently small to have
530   // window fit in the small screens (actual for remote desktops, see #23003).
531   // The position corresponds to the window's client area, thus some
532   // gap is added for window frame to be visible.
533   Standard_Integer aPxLeft   = 20;
534   Standard_Integer aPxTop    = 40;
535   Standard_Integer aPxWidth  = 409;
536   Standard_Integer aPxHeight = 409;
537   Standard_Boolean toCreateViewer = Standard_False;
538
539   Handle(OpenGl_GraphicDriver) aGraphicDriver;
540   ViewerTest_Names aViewNames(theViewName);
541   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
542     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
543
544   if (thePxLeft != 0)
545     aPxLeft = thePxLeft;
546   if (thePxTop != 0)
547     aPxTop = thePxTop;
548   if (thePxWidth != 0)
549     aPxWidth = thePxWidth;
550   if (thePxHeight != 0)
551     aPxHeight = thePxHeight;
552
553   // Get graphic driver (create it or get from another view)
554   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
555   {
556     // Get connection string
557   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
558     TCollection_AsciiString aDisplayName(theDisplayName);
559     if (!aDisplayName.IsEmpty())
560       SetDisplayConnection (new Aspect_DisplayConnection ());
561     else
562       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
563   #else
564     (void)theDisplayName; // avoid warning on unused argument
565     SetDisplayConnection (new Aspect_DisplayConnection ());
566   #endif
567
568     if (Draw_VirtualWindows)
569     {
570       // don't waste the time waiting for VSync when window is not displayed on the screen
571       ViewerTest_myDefaultCaps.swapInterval = 0;
572       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
573       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
574     }
575     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
576     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
577
578     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
579     toCreateViewer = Standard_True;
580   }
581   else
582   {
583     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
584   }
585
586   //Dispose the window if input parameters are default
587   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
588   {
589     Standard_Integer aTop = 0,
590                      aLeft = 0,
591                      aRight = 0,
592                      aBottom = 0,
593                      aScreenWidth = 0,
594                      aScreenHeight = 0;
595
596     // Get screen resolution
597 #if defined(_WIN32) || defined(__WIN32__)
598     RECT aWindowSize;
599     GetClientRect(GetDesktopWindow(), &aWindowSize);
600     aScreenHeight = aWindowSize.bottom;
601     aScreenWidth = aWindowSize.right;
602 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
603     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
604 #else
605     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
606     aScreenWidth = WidthOfScreen(aScreen);
607     aScreenHeight = HeightOfScreen(aScreen);
608 #endif
609
610     TCollection_AsciiString anOverlappedViewId("");
611
612     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
613     {
614       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
615
616       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
617         && aRight + 2*aPxWidth + 40 > aScreenWidth)
618       {
619         if (aBottom + aPxHeight + 40 > aScreenHeight)
620         {
621           aPxLeft = 20;
622           aPxTop = 40;
623           break;
624         }
625         aPxLeft = 20;
626         aPxTop = aBottom + 40;
627       }
628       else
629         aPxLeft = aRight + 20;
630     }
631   }
632
633   // Get viewer name
634   TCollection_AsciiString aTitle("3D View - ");
635   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
636
637   // Change name of current active window
638   if (!ViewerTest::CurrentView().IsNull())
639   {
640     TCollection_AsciiString anActiveWindowTitle("3D View - ");
641     anActiveWindowTitle = anActiveWindowTitle
642       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
643     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
644   }
645
646   // Create viewer
647   Handle(V3d_Viewer) a3DViewer;
648   // If it's the single view, we first look for empty context
649   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
650   {
651     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
652       anIter(ViewerTest_myContexts);
653     if (anIter.More())
654       ViewerTest::SetAISContext (anIter.Value());
655     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
656   }
657   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
658   {
659     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
660     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
661   }
662   else if (a3DViewer.IsNull())
663   {
664     toCreateViewer = Standard_True;
665     a3DViewer = new V3d_Viewer(aGraphicDriver);
666     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
667     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
668                                            ViewerTest_DefaultBackground.GradientColor2,
669                                            ViewerTest_DefaultBackground.FillMethod);
670   }
671
672   // AIS context setup
673   if (ViewerTest::GetAISContext().IsNull() ||
674       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
675   {
676     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
677     ViewerTest::SetAISContext (aContext);
678     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
679   }
680   else
681   {
682     ViewerTest::ResetEventManager();
683   }
684
685   // Create window
686 #if defined(_WIN32)
687   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
688                                     Handle(WNT_WClass)::DownCast (WClass()),
689                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
690                                     aPxLeft, aPxTop,
691                                     aPxWidth, aPxHeight,
692                                     Quantity_NOC_BLACK);
693 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
694   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
695                                      aPxLeft, aPxTop,
696                                      aPxWidth, aPxHeight);
697   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
698 #else
699   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
700                                   aTitle.ToCString(),
701                                   aPxLeft, aPxTop,
702                                   aPxWidth, aPxHeight);
703 #endif
704   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
705
706   // View setup
707   Handle(V3d_View) aView = a3DViewer->CreateView();
708   aView->SetWindow (VT_GetWindow());
709   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
710
711   ViewerTest::CurrentView(aView);
712   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
713
714   // Setup for X11 or NT
715   OSWindowSetup();
716
717   // Set parameters for V3d_View and V3d_Viewer
718   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
719   aV3dView->SetComputedMode(Standard_False);
720   MyHLRIsOn = aV3dView->ComputedMode();
721
722   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
723   if (toCreateViewer)
724   {
725     a3DViewer->SetDefaultLights();
726     a3DViewer->SetLightOn();
727   }
728
729   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
730   #if TCL_MAJOR_VERSION  < 8
731   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
732       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
733   #else
734   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
735       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
736   #endif
737   #endif
738
739   VT_GetWindow()->Map();
740
741   // Set the handle of created view in the event manager
742   ViewerTest::ResetEventManager();
743
744   ViewerTest::CurrentView()->Redraw();
745
746   aView.Nullify();
747   a3DViewer.Nullify();
748
749   return aViewNames.GetViewName();
750 }
751
752 //==============================================================================
753 //function : RedrawAllViews
754 //purpose  : Redraw all created views
755 //==============================================================================
756 void ViewerTest::RedrawAllViews()
757 {
758   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
759   for (; aViewIt.More(); aViewIt.Next())
760   {
761     const Handle(V3d_View)& aView = aViewIt.Key2();
762     aView->Redraw();
763   }
764 }
765
766 //==============================================================================
767 //function : Vinit
768 //purpose  : Create the window viewer and initialize all the global variable
769 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
770 //==============================================================================
771
772 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
773 {
774   if (theArgsNb > 9)
775   {
776     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
777               << "Type help for more information.\n";
778     return 1;
779   }
780
781   TCollection_AsciiString aViewName, aDisplayName;
782   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
783   TCollection_AsciiString aName, aValue;
784   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
785   {
786     const TCollection_AsciiString anArg = theArgVec[anArgIt];
787     TCollection_AsciiString anArgCase = anArg;
788     anArgCase.UpperCase();
789     if (ViewerTest::SplitParameter (anArg, aName, aValue))
790     {
791       aName.UpperCase();
792       if (aName.IsEqual ("NAME"))
793       {
794         aViewName = aValue;
795       }
796       else if (aName.IsEqual ("L")
797             || aName.IsEqual ("LEFT"))
798       {
799         aPxLeft = aValue.IntegerValue();
800       }
801       else if (aName.IsEqual ("T")
802             || aName.IsEqual ("TOP"))
803       {
804         aPxTop = aValue.IntegerValue();
805       }
806     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
807       else if (aName.IsEqual ("DISP")
808             || aName.IsEqual ("DISPLAY"))
809       {
810         aDisplayName = aValue;
811       }
812     #endif
813       else if (aName.IsEqual ("W")
814             || aName.IsEqual ("WIDTH"))
815       {
816         aPxWidth = aValue.IntegerValue();
817       }
818       else if (aName.IsEqual ("H")
819             || aName.IsEqual ("HEIGHT"))
820       {
821         aPxHeight = aValue.IntegerValue();
822       }
823       else
824       {
825         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
826       }
827     }
828     else if (aViewName.IsEmpty())
829     {
830       aViewName = anArg;
831     }
832     else
833     {
834       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
835     }
836   }
837
838   ViewerTest_Names aViewNames (aViewName);
839   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
840   {
841     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
842     theDi.Eval (aCommand.ToCString());
843     return 0;
844   }
845
846   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
847                                                             aViewName.ToCString(),
848                                                             aDisplayName.ToCString());
849   theDi << aViewId;
850   return 0;
851 }
852
853 //==============================================================================
854 //function : VHLR
855 //purpose  : hidden lines removal algorithm
856 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
857 //==============================================================================
858
859 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
860 {
861   if (ViewerTest::CurrentView().IsNull())
862   {
863     di << argv[0] << ": Call vinit before this command, please.\n";
864     return 1;
865   }
866
867   if (argc < 2)
868   {
869     di << argv[0] << ": Wrong number of command arguments.\n"
870       << "Type help " << argv[0] << " for more information.\n";
871     return 1;
872   }
873
874   // Enable or disable HLR mode.
875   Standard_Boolean isHLROn =
876     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
877
878   if (isHLROn != MyHLRIsOn)
879   {
880     MyHLRIsOn = isHLROn;
881     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
882   }
883
884   // Show or hide hidden lines in HLR mode.
885   Standard_Boolean isCurrentShowHidden
886     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
887
888   Standard_Boolean isShowHidden =
889     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
890                 : isCurrentShowHidden;
891
892
893   if (isShowHidden != isCurrentShowHidden)
894   {
895     if (isShowHidden)
896     {
897       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
898     }
899     else
900     {
901       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
902     }
903
904     // Redisplay shapes.
905     if (MyHLRIsOn)
906     {
907       AIS_ListOfInteractive aListOfShapes;
908       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
909
910       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
911       {
912         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
913         if (aShape.IsNull())
914         {
915           continue;
916         }
917         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
918       }
919     }
920   }
921
922   ViewerTest::CurrentView()->Update();
923   return 0;
924 }
925
926 //==============================================================================
927 //function : VHLRType
928 //purpose  : change type of using HLR algorithm
929 //==============================================================================
930
931 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
932 {
933   if (ViewerTest::CurrentView().IsNull())
934   {
935     di << argv[0] << ": Call vinit before this command, please.\n";
936     return 1;
937   }
938
939   if (argc < 2)
940   {
941     di << argv[0] << ": Wrong number of command arguments.\n"
942       << "Type help " << argv[0] << " for more information.\n";
943     return 1;
944   }
945
946   Prs3d_TypeOfHLR aTypeOfHLR =
947     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
948
949   if (argc == 2)
950   {
951     AIS_ListOfInteractive aListOfShapes;
952     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
953     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
954     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
955       anIter.More(); anIter.Next())
956     {
957       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
958       if (aShape.IsNull())
959         continue;
960       if (aShape->TypeOfHLR() != aTypeOfHLR)
961         aShape->SetTypeOfHLR (aTypeOfHLR);
962       if (MyHLRIsOn)
963         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
964     }
965     ViewerTest::CurrentView()->Update();
966     return 0;
967   }
968   else
969   {
970     for (Standard_Integer i = 2; i < argc; ++i)
971     {
972       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
973       TCollection_AsciiString aName (argv[i]);
974
975       if (!aMap.IsBound2 (aName))
976       {
977         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
978         continue;
979       }
980       Handle(AIS_Shape) anAISObject =
981         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
982       if (anAISObject.IsNull())
983         continue;
984       anAISObject->SetTypeOfHLR (aTypeOfHLR);
985       if (MyHLRIsOn)
986         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
987     }
988     ViewerTest::CurrentView()->Update();
989   }
990
991   return 0;
992 }
993
994 //==============================================================================
995 //function : FindViewIdByWindowHandle
996 //purpose  : Find theView Id in the map of views by window handle
997 //==============================================================================
998 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
999 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1000 {
1001   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1002        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1003   {
1004     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1005     if (aWindowHandle == theWindowHandle)
1006       return anIter.Key1();
1007   }
1008   return TCollection_AsciiString("");
1009 }
1010 #endif
1011
1012 //==============================================================================
1013 //function : ActivateView
1014 //purpose  : Make the view active
1015 //==============================================================================
1016
1017 void ActivateView (const TCollection_AsciiString& theViewName)
1018 {
1019   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1020   if (!aView.IsNull())
1021   {
1022     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1023     if (!anAISContext.IsNull())
1024     {
1025       if (!ViewerTest::CurrentView().IsNull())
1026       {
1027         TCollection_AsciiString aTitle("3D View - ");
1028         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1029         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1030       }
1031
1032       ViewerTest::CurrentView (aView);
1033       // Update degenerate mode
1034       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1035       ViewerTest::SetAISContext (anAISContext);
1036       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1037       aTitle = aTitle + theViewName + "(*)";
1038       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1039 #if defined(_WIN32) || defined(__WIN32__)
1040       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1041 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1042       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1043 #else
1044       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1045 #endif
1046       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1047       ViewerTest::CurrentView()->Redraw();
1048     }
1049   }
1050 }
1051
1052 //==============================================================================
1053 //function : RemoveView
1054 //purpose  :
1055 //==============================================================================
1056 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1057                              const Standard_Boolean  theToRemoveContext)
1058 {
1059   if (!ViewerTest_myViews.IsBound2 (theView))
1060   {
1061     return;
1062   }
1063
1064   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1065   RemoveView (aViewName, theToRemoveContext);
1066 }
1067
1068 //==============================================================================
1069 //function : RemoveView
1070 //purpose  : Close and remove view from display, clear maps if neccessary
1071 //==============================================================================
1072 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1073 {
1074   if (!ViewerTest_myViews.IsBound1(theViewName))
1075   {
1076     cout << "Wrong view name\n";
1077     return;
1078   }
1079
1080   // Activate another view if it's active now
1081   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1082   {
1083     if (ViewerTest_myViews.Extent() > 1)
1084     {
1085       TCollection_AsciiString aNewViewName;
1086       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1087            anIter.More(); anIter.Next())
1088       {
1089         if (anIter.Key1() != theViewName)
1090         {
1091           aNewViewName = anIter.Key1();
1092           break;
1093         }
1094       }
1095       ActivateView (aNewViewName);
1096     }
1097     else
1098     {
1099       Handle(V3d_View) anEmptyView;
1100 #if defined(_WIN32) || defined(__WIN32__)
1101       Handle(WNT_Window) anEmptyWindow;
1102 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1103       Handle(Cocoa_Window) anEmptyWindow;
1104 #else
1105       Handle(Xw_Window) anEmptyWindow;
1106 #endif
1107       VT_GetWindow() = anEmptyWindow;
1108       ViewerTest::CurrentView (anEmptyView);
1109       if (isContextRemoved)
1110       {
1111         Handle(AIS_InteractiveContext) anEmptyContext;
1112         ViewerTest::SetAISContext(anEmptyContext);
1113       }
1114     }
1115   }
1116
1117   // Delete view
1118   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1119   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1120
1121   // Remove view resources
1122   ViewerTest_myViews.UnBind1(theViewName);
1123   aView->Remove();
1124
1125 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1126   XFlush (GetDisplayConnection()->GetDisplay());
1127 #endif
1128
1129   // Keep context opened only if the closed view is last to avoid
1130   // unused empty contexts
1131   if (!aCurrentContext.IsNull())
1132   {
1133     // Check if there are more difined views in the viewer
1134     aCurrentContext->CurrentViewer()->InitDefinedViews();
1135     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1136     {
1137       // Remove driver if there is no viewers that use it
1138       Standard_Boolean isRemoveDriver = Standard_True;
1139       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1140           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1141       {
1142         if (aCurrentContext != anIter.Key2() &&
1143           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1144         {
1145           isRemoveDriver = Standard_False;
1146           break;
1147         }
1148       }
1149
1150       aCurrentContext->RemoveAll (Standard_False);
1151       if(isRemoveDriver)
1152       {
1153         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1154       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1155         #if TCL_MAJOR_VERSION  < 8
1156         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1157         #else
1158         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1159         #endif
1160       #endif
1161       }
1162
1163       ViewerTest_myContexts.UnBind2(aCurrentContext);
1164     }
1165   }
1166   cout << "3D View - " << theViewName << " was deleted.\n";
1167
1168 }
1169
1170 //==============================================================================
1171 //function : VClose
1172 //purpose  : Remove the view defined by its name
1173 //==============================================================================
1174
1175 static int VClose (Draw_Interpretor& /*theDi*/,
1176                    Standard_Integer  theArgsNb,
1177                    const char**      theArgVec)
1178 {
1179   NCollection_List<TCollection_AsciiString> aViewList;
1180   if (theArgsNb > 1)
1181   {
1182     TCollection_AsciiString anArg (theArgVec[1]);
1183     anArg.UpperCase();
1184     if (anArg.IsEqual ("ALL")
1185      || anArg.IsEqual ("*"))
1186     {
1187       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1188            anIter.More(); anIter.Next())
1189       {
1190         aViewList.Append (anIter.Key1());
1191       }
1192       if (aViewList.IsEmpty())
1193       {
1194         std::cout << "No view to close\n";
1195         return 0;
1196       }
1197     }
1198     else
1199     {
1200       ViewerTest_Names aViewName (theArgVec[1]);
1201       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1202       {
1203         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1204         return 1;
1205       }
1206       aViewList.Append (aViewName.GetViewName());
1207     }
1208   }
1209   else
1210   {
1211     // close active view
1212     if (ViewerTest::CurrentView().IsNull())
1213     {
1214       std::cerr << "No active view!\n";
1215       return 1;
1216     }
1217     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1218   }
1219
1220   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1221   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1222        anIter.More(); anIter.Next())
1223   {
1224     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1225   }
1226
1227   return 0;
1228 }
1229
1230 //==============================================================================
1231 //function : VActivate
1232 //purpose  : Activate the view defined by its ID
1233 //==============================================================================
1234
1235 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1236 {
1237   if (theArgsNb > 2)
1238   {
1239     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1240     << "Usage: " << theArgVec[0] << " ViewID\n";
1241     return 1;
1242   }
1243   if(theArgsNb == 1)
1244   {
1245     theDi.Eval("vviewlist");
1246     return 0;
1247   }
1248
1249   TCollection_AsciiString aNameString(theArgVec[1]);
1250   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1251   {
1252     TCollection_AsciiString aTitle("3D View - ");
1253     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1254     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1255     Handle(V3d_View) anEmptyView;
1256 #if defined(_WIN32) || defined(__WIN32__)
1257     Handle(WNT_Window) anEmptyWindow;
1258 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1259     Handle(Cocoa_Window) anEmptyWindow;
1260 #else
1261     Handle(Xw_Window) anEmptyWindow;
1262 #endif
1263     VT_GetWindow() = anEmptyWindow;
1264     ViewerTest::CurrentView (anEmptyView);
1265     ViewerTest::ResetEventManager();
1266     theDi << theArgVec[0] << ": all views are inactive\n";
1267     return 0;
1268   }
1269
1270   ViewerTest_Names aViewNames(aNameString);
1271
1272   // Check if this view exists in the viewer with the driver
1273   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1274   {
1275     theDi << "Wrong view name\n";
1276     return 1;
1277   }
1278
1279   // Check if it is active already
1280   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1281   {
1282     theDi << theArgVec[0] << ": the view is active already\n";
1283     return 0;
1284   }
1285
1286   ActivateView (aViewNames.GetViewName());
1287   return 0;
1288 }
1289
1290 //==============================================================================
1291 //function : VViewList
1292 //purpose  : Print current list of views per viewer and graphic driver ID
1293 //           shared between viewers
1294 //==============================================================================
1295
1296 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1297 {
1298   if (theArgsNb > 2)
1299   {
1300     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1301           << "Usage: " << theArgVec[0] << " name";
1302     return 1;
1303   }
1304   if (ViewerTest_myContexts.Size() < 1)
1305     return 0;
1306
1307   Standard_Boolean isTreeView =
1308     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1309
1310   if (isTreeView)
1311   {
1312     theDi << theArgVec[0] <<":\n";
1313   }
1314
1315   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1316        aDriverIter.More(); aDriverIter.Next())
1317   {
1318     if (isTreeView)
1319       theDi << aDriverIter.Key1() << ":\n";
1320
1321     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1322       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1323     {
1324       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1325       {
1326         if (isTreeView)
1327         {
1328           TCollection_AsciiString aContextName(aContextIter.Key1());
1329           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1330         }
1331
1332         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1333              aViewIter.More(); aViewIter.Next())
1334         {
1335           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1336           {
1337             TCollection_AsciiString aViewName(aViewIter.Key1());
1338             if (isTreeView)
1339             {
1340               if (aViewIter.Value() == ViewerTest::CurrentView())
1341                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1342               else
1343                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1344             }
1345             else
1346             {
1347               theDi << aViewName << " ";
1348             }
1349           }
1350         }
1351       }
1352     }
1353   }
1354   return 0;
1355 }
1356
1357 //==============================================================================
1358 //function : VT_ProcessKeyPress
1359 //purpose  : Handle KeyPress event from a CString
1360 //==============================================================================
1361 void VT_ProcessKeyPress (const char* buf_ret)
1362 {
1363   //cout << "KeyPress" << endl;
1364   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1365   // Letter in alphabetic order
1366
1367   if (!strcasecmp (buf_ret, "A"))
1368   {
1369     // AXO
1370     aView->SetProj(V3d_XposYnegZpos);
1371   }
1372   else if (!strcasecmp (buf_ret, "D"))
1373   {
1374     // Reset
1375     aView->Reset();
1376   }
1377   else if (!strcasecmp (buf_ret, "F"))
1378   {
1379     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1380     {
1381       ViewerTest::GetAISContext()->FitSelected (aView);
1382     }
1383     else
1384     {
1385       // FitAll
1386       aView->FitAll();
1387     }
1388   }
1389   else if (!strcasecmp (buf_ret, "H"))
1390   {
1391     // HLR
1392     cout << "HLR" << endl;
1393     aView->SetComputedMode (!aView->ComputedMode());
1394     MyHLRIsOn = aView->ComputedMode();
1395   }
1396   else if (!strcasecmp (buf_ret, "P"))
1397   {
1398     // Type of HLR
1399     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1400     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1401       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1402     else
1403       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1404     if (aContext->NbSelected()==0)
1405     {
1406       AIS_ListOfInteractive aListOfShapes;
1407       aContext->DisplayedObjects(aListOfShapes);
1408       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1409         anIter.More(); anIter.Next())
1410       {
1411         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1412         if (aShape.IsNull())
1413           continue;
1414         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1415           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1416         else
1417           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1418         aContext->Redisplay (aShape, Standard_False);
1419       }
1420     }
1421     else
1422     {
1423       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1424       {
1425         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1426         if (aShape.IsNull())
1427           continue;
1428         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1429           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1430         else
1431           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1432         aContext->Redisplay (aShape, Standard_False);
1433       }
1434     }
1435
1436     aContext->UpdateCurrentViewer();
1437
1438   }
1439   else if (!strcasecmp (buf_ret, "S"))
1440   {
1441     std::cout << "setup Shaded display mode" << std::endl;
1442
1443     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1444     if(Ctx->NbSelected()==0)
1445       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1446     else{
1447       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1448         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1449       Ctx->UpdateCurrentViewer();
1450     }
1451   }
1452   else if (!strcasecmp (buf_ret, "U"))
1453   {
1454     // Unset display mode
1455     std::cout << "reset display mode to defaults" << std::endl;
1456
1457     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1458     if(Ctx->NbSelected()==0)
1459       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1460     else{
1461       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1462         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1463       Ctx->UpdateCurrentViewer();
1464     }
1465
1466   }
1467   else if (!strcasecmp (buf_ret, "T"))
1468   {
1469     // Top
1470     aView->SetProj(V3d_Zpos);
1471   }
1472   else if (!strcasecmp (buf_ret, "B"))
1473   {
1474     // Bottom
1475     aView->SetProj(V3d_Zneg);
1476   }
1477   else if (!strcasecmp (buf_ret, "L"))
1478   {
1479     // Left
1480     aView->SetProj(V3d_Xneg);
1481   }
1482   else if (!strcasecmp (buf_ret, "R"))
1483   {
1484     // Right
1485     aView->SetProj(V3d_Xpos);
1486   }
1487   else if (!strcasecmp (buf_ret, "W"))
1488   {
1489     std::cout << "setup WireFrame display mode" << std::endl;
1490     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1491     if(Ctx->NbSelected()==0)
1492       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1493     else{
1494       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1495         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1496       Ctx->UpdateCurrentViewer();
1497     }
1498   }
1499   else if (!strcasecmp (buf_ret, ","))
1500   {
1501     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1502   }
1503   else if (!strcasecmp (buf_ret, "."))
1504   {
1505     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1506   }
1507   else if (!strcasecmp (buf_ret, "/"))
1508   {
1509     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1510     if (aCamera->IsStereo())
1511     {
1512       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1513       aView->Redraw();
1514     }
1515   }
1516   else if (!strcasecmp (buf_ret, "*"))
1517   {
1518     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1519     if (aCamera->IsStereo())
1520     {
1521       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1522       aView->Redraw();
1523     }
1524   }
1525   else if (*buf_ret == THE_KEY_DELETE)
1526   {
1527     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1528     if (!aCtx.IsNull()
1529      && aCtx->NbSelected() > 0)
1530     {
1531       Draw_Interprete ("verase");
1532     }
1533   }
1534   else
1535   {
1536     // Number
1537     Standard_Integer Num = Draw::Atoi(buf_ret);
1538     if(Num>=0 && Num<=7)
1539       ViewerTest::StandardModeActivation(Num);
1540   }
1541 }
1542
1543 //==============================================================================
1544 //function : VT_ProcessExpose
1545 //purpose  : Redraw the View on an Expose Event
1546 //==============================================================================
1547 void VT_ProcessExpose()
1548 {
1549   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1550   if (!aView3d.IsNull())
1551   {
1552     aView3d->Redraw();
1553   }
1554 }
1555
1556 //==============================================================================
1557 //function : VT_ProcessConfigure
1558 //purpose  : Resize the View on an Configure Event
1559 //==============================================================================
1560 void VT_ProcessConfigure()
1561 {
1562   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1563   if (aView3d.IsNull())
1564   {
1565     return;
1566   }
1567
1568   aView3d->MustBeResized();
1569   aView3d->Update();
1570   aView3d->Redraw();
1571 }
1572
1573 //==============================================================================
1574 //function : VT_ProcessButton1Press
1575 //purpose  : Picking
1576 //==============================================================================
1577 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1578                                          const char**     theArgVec,
1579                                          Standard_Boolean theToPick,
1580                                          Standard_Boolean theIsShift)
1581 {
1582   if (TheIsAnimating)
1583   {
1584     TheIsAnimating = Standard_False;
1585     return Standard_False;
1586   }
1587
1588   if (theToPick)
1589   {
1590     Standard_Real X, Y, Z;
1591     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1592
1593     Draw::Set (theArgVec[1], X);
1594     Draw::Set (theArgVec[2], Y);
1595     Draw::Set (theArgVec[3], Z);
1596   }
1597
1598   if (theIsShift)
1599   {
1600     ViewerTest::CurrentEventManager()->ShiftSelect();
1601   }
1602   else
1603   {
1604     ViewerTest::CurrentEventManager()->Select();
1605   }
1606
1607   return Standard_False;
1608 }
1609
1610 //==============================================================================
1611 //function : VT_ProcessButton1Release
1612 //purpose  : End selecting
1613 //==============================================================================
1614 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1615 {
1616   if (IsDragged)
1617   {
1618     IsDragged = Standard_False;
1619     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1620     if (theIsShift)
1621     {
1622       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1623                        X_Motion, Y_Motion);
1624     }
1625     else
1626     {
1627       EM->Select (X_ButtonPress, Y_ButtonPress,
1628                   X_Motion, Y_Motion);
1629     }
1630   }
1631 }
1632
1633 //==============================================================================
1634 //function : VT_ProcessButton3Press
1635 //purpose  : Start Rotation
1636 //==============================================================================
1637 void VT_ProcessButton3Press()
1638 {
1639   Start_Rot = 1;
1640   if (MyHLRIsOn)
1641   {
1642     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1643   }
1644   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1645 }
1646
1647 //==============================================================================
1648 //function : VT_ProcessButton3Release
1649 //purpose  : End rotation
1650 //==============================================================================
1651 void VT_ProcessButton3Release()
1652 {
1653   if (Start_Rot)
1654   {
1655     Start_Rot = 0;
1656     if (MyHLRIsOn)
1657     {
1658       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1659     }
1660   }
1661 }
1662
1663 //==============================================================================
1664 //function : ProcessControlButton1Motion
1665 //purpose  : Zoom
1666 //==============================================================================
1667
1668 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1669 static void ProcessControlButton1Motion()
1670 {
1671   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1672
1673   X_ButtonPress = X_Motion;
1674   Y_ButtonPress = Y_Motion;
1675 }
1676 #endif
1677
1678 //==============================================================================
1679 //function : VT_ProcessControlButton2Motion
1680 //purpose  : Panning
1681 //==============================================================================
1682 void VT_ProcessControlButton2Motion()
1683 {
1684   Standard_Integer aDx = X_Motion - X_ButtonPress;
1685   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1686
1687   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1688
1689   ViewerTest::CurrentView()->Pan (aDx, aDy);
1690
1691   X_ButtonPress = X_Motion;
1692   Y_ButtonPress = Y_Motion;
1693 }
1694
1695 //==============================================================================
1696 //function : VT_ProcessControlButton3Motion
1697 //purpose  : Rotation
1698 //==============================================================================
1699 void VT_ProcessControlButton3Motion()
1700 {
1701   if (Start_Rot)
1702   {
1703     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1704   }
1705 }
1706
1707 //==============================================================================
1708 //function : VT_ProcessMotion
1709 //purpose  :
1710 //==============================================================================
1711 void VT_ProcessMotion()
1712 {
1713   //pre-hilights detected objects at mouse position
1714
1715   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1716   EM->MoveTo(X_Motion, Y_Motion);
1717 }
1718
1719
1720 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1721 {
1722   Xpix = X_Motion;Ypix=Y_Motion;
1723 }
1724
1725 //==============================================================================
1726 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1727 //purpose  : Switches to an axonometric, top, left and other views
1728 //==============================================================================
1729
1730 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1731 {
1732   if ( ViewerTest::CurrentView().IsNull() )
1733   {
1734     di<<"Call vinit before this command, please\n";
1735     return 1;
1736   }
1737
1738   ViewerTest::CurrentView()->SetProj(ori);
1739   return 0;
1740 }
1741
1742 //==============================================================================
1743 //function : VAxo
1744 //purpose  : Switch to an Axonometric view
1745 //Draw arg : No args
1746 //==============================================================================
1747
1748 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1749 {
1750   return ViewProject(di, V3d_XposYnegZpos);
1751 }
1752
1753 //==============================================================================
1754 //function : VTop
1755 //purpose  : Switch to a Top View
1756 //Draw arg : No args
1757 //==============================================================================
1758
1759 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1760 {
1761   return ViewProject(di, V3d_Zpos);
1762 }
1763
1764 //==============================================================================
1765 //function : VBottom
1766 //purpose  : Switch to a Bottom View
1767 //Draw arg : No args
1768 //==============================================================================
1769
1770 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1771 {
1772   return ViewProject(di, V3d_Zneg);
1773 }
1774
1775 //==============================================================================
1776 //function : VLeft
1777 //purpose  : Switch to a Left View
1778 //Draw arg : No args
1779 //==============================================================================
1780
1781 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1782 {
1783   return ViewProject(di, V3d_Xneg);
1784 }
1785
1786 //==============================================================================
1787 //function : VRight
1788 //purpose  : Switch to a Right View
1789 //Draw arg : No args
1790 //==============================================================================
1791
1792 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1793 {
1794   return ViewProject(di, V3d_Xpos);
1795 }
1796
1797 //==============================================================================
1798 //function : VFront
1799 //purpose  : Switch to a Front View
1800 //Draw arg : No args
1801 //==============================================================================
1802
1803 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1804 {
1805   return ViewProject(di, V3d_Yneg);
1806 }
1807
1808 //==============================================================================
1809 //function : VBack
1810 //purpose  : Switch to a Back View
1811 //Draw arg : No args
1812 //==============================================================================
1813
1814 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1815 {
1816   return ViewProject(di, V3d_Ypos);
1817 }
1818
1819 //==============================================================================
1820 //function : VHelp
1821 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1822 //Draw arg : No args
1823 //==============================================================================
1824
1825 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1826 {
1827
1828   di << "Q : Quit the application\n";
1829
1830   di << "=========================\n";
1831   di << "F : FitAll\n";
1832   di << "T : TopView\n";
1833   di << "B : BottomView\n";
1834   di << "R : RightView\n";
1835   di << "L : LeftView\n";
1836   di << "A : AxonometricView\n";
1837   di << "D : ResetView\n";
1838
1839   di << "=========================\n";
1840   di << "S : Shading\n";
1841   di << "W : Wireframe\n";
1842   di << "H : HidelLineRemoval\n";
1843   di << "U : Unset display mode\n";
1844   di << "Delete : Remove selection from viewer\n";
1845
1846   di << "=========================\n";
1847   di << "Selection mode \n";
1848   di << "0 : Shape\n";
1849   di << "1 : Vertex\n";
1850   di << "2 : Edge\n";
1851   di << "3 : Wire\n";
1852   di << "4 : Face\n";
1853   di << "5 : Shell\n";
1854   di << "6 : Solid\n";
1855   di << "7 : Compound\n";
1856
1857   di << "=========================\n";
1858   di << "Z : Switch Z clipping On/Off\n";
1859   di << ", : Hilight next detected\n";
1860   di << ". : Hilight previous detected\n";
1861
1862   return 0;
1863 }
1864
1865 #ifdef _WIN32
1866
1867 static Standard_Boolean Ppick = 0;
1868 static Standard_Integer Pargc = 0;
1869 static const char**           Pargv = NULL;
1870
1871
1872 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1873                                           UINT Msg,
1874                                           WPARAM wParam,
1875                                           LPARAM lParam )
1876 {
1877   if (!ViewerTest_myViews.IsEmpty()) {
1878
1879     WPARAM fwKeys = wParam;
1880
1881     switch( Msg ) {
1882     case WM_CLOSE:
1883        {
1884          // Delete view from map of views
1885          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1886          return 0;
1887        }
1888        break;
1889     case WM_ACTIVATE:
1890       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1891         || ViewerTest::CurrentView().IsNull())
1892       {
1893         // Activate inactive window
1894         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1895         {
1896           ActivateView (FindViewIdByWindowHandle(hwnd));
1897         }
1898       }
1899       break;
1900
1901     case WM_LBUTTONUP:
1902       if (IsDragged && !DragFirst)
1903       {
1904         if (!GetActiveAISManipulator().IsNull())
1905         {
1906           GetActiveAISManipulator()->StopTransform();
1907           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1908         }
1909
1910         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1911         {
1912           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1913           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1914         }
1915
1916         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1917       }
1918       IsDragged = Standard_False;
1919       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1920
1921     case WM_RBUTTONUP:
1922       if (IsDragged && !DragFirst)
1923       {
1924         if (!GetActiveAISManipulator().IsNull())
1925         {
1926           GetActiveAISManipulator()->StopTransform (Standard_False);
1927           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1928         }
1929         IsDragged = Standard_False;
1930       }
1931       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1932
1933     case WM_LBUTTONDOWN:
1934       if (!GetActiveAISManipulator().IsNull())
1935       {
1936         IsDragged = ( fwKeys == MK_LBUTTON );
1937       }
1938       else
1939       {
1940         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1941       }
1942
1943       if (IsDragged)
1944       {
1945         DragFirst = Standard_True;
1946         X_ButtonPress = LOWORD(lParam);
1947         Y_ButtonPress = HIWORD(lParam);
1948       }
1949       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1950
1951     case WM_MOUSEMOVE:
1952       if (IsDragged)
1953       {
1954         X_Motion = LOWORD (lParam);
1955         Y_Motion = HIWORD (lParam);
1956         if (!GetActiveAISManipulator().IsNull())
1957         {
1958           if (DragFirst)
1959           {
1960             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1961           }
1962           else
1963           {
1964             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1965             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1966           }
1967         }
1968         else
1969         {
1970           bool toRedraw = false;
1971           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1972           {
1973             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1974             toRedraw = true;
1975           }
1976
1977           RECT aRect;
1978           if (GetClientRect (hwnd, &aRect))
1979           {
1980             int aHeight = aRect.bottom - aRect.top;
1981             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1982             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1983             toRedraw = true;
1984           }
1985           if (toRedraw)
1986           {
1987             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1988           }
1989         }
1990
1991         DragFirst = Standard_False;
1992       }
1993       else
1994         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1995       break;
1996
1997     default:
1998       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1999     }
2000     return 0;
2001   }
2002   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2003 }
2004
2005
2006 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2007                                        UINT Msg,
2008                                        WPARAM wParam,
2009                                        LPARAM lParam )
2010 {
2011   static int Up = 1;
2012   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2013   if (aView.IsNull())
2014   {
2015     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2016   }
2017
2018     PAINTSTRUCT    ps;
2019
2020     switch( Msg ) {
2021     case WM_PAINT:
2022       BeginPaint(hwnd, &ps);
2023       EndPaint(hwnd, &ps);
2024       VT_ProcessExpose();
2025       break;
2026
2027     case WM_SIZE:
2028       VT_ProcessConfigure();
2029       break;
2030     case WM_MOVE:
2031     case WM_MOVING:
2032     case WM_SIZING:
2033       switch (aView->RenderingParams().StereoMode)
2034       {
2035         case Graphic3d_StereoMode_RowInterlaced:
2036         case Graphic3d_StereoMode_ColumnInterlaced:
2037         case Graphic3d_StereoMode_ChessBoard:
2038           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2039           break;
2040         default:
2041           break;
2042       }
2043       break;
2044
2045     case WM_KEYDOWN:
2046       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2047       {
2048         char c[2];
2049         c[0] = (char) wParam;
2050         c[1] = '\0';
2051         if (wParam == VK_DELETE)
2052         {
2053           c[0] = THE_KEY_DELETE;
2054         }
2055         // comma
2056         else if (wParam == VK_OEM_COMMA)
2057         {
2058           c[0] = ',';
2059         }
2060         // dot
2061         else if (wParam == VK_OEM_PERIOD)
2062         {
2063           c[0] = '.';
2064         }
2065         else if (wParam == VK_DIVIDE)
2066         {
2067           c[0] = '/';
2068         }
2069         // dot
2070         else if (wParam == VK_MULTIPLY)
2071         {
2072           c[0] = '*';
2073         }
2074         VT_ProcessKeyPress (c);
2075       }
2076       break;
2077
2078     case WM_LBUTTONUP:
2079     case WM_MBUTTONUP:
2080     case WM_RBUTTONUP:
2081       Up = 1;
2082       VT_ProcessButton3Release();
2083       break;
2084
2085     case WM_LBUTTONDOWN:
2086     case WM_MBUTTONDOWN:
2087     case WM_RBUTTONDOWN:
2088       {
2089         WPARAM fwKeys = wParam;
2090
2091         Up = 0;
2092
2093         X_ButtonPress = LOWORD(lParam);
2094         Y_ButtonPress = HIWORD(lParam);
2095
2096         if (Msg == WM_LBUTTONDOWN)
2097         {
2098           if ((fwKeys & MK_CONTROL) != 0)
2099           {
2100             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2101           }
2102           else
2103           {
2104             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2105           }
2106         }
2107         else if (Msg == WM_RBUTTONDOWN)
2108         {
2109           // Start rotation
2110           VT_ProcessButton3Press();
2111         }
2112       }
2113       break;
2114
2115     case WM_MOUSEWHEEL:
2116     {
2117       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2118       if (wParam & MK_CONTROL)
2119       {
2120         if (aView->Camera()->IsStereo())
2121         {
2122           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2123           if (aFocus > 0.2
2124            && aFocus < 2.0)
2125           {
2126             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2127             aView->Redraw();
2128           }
2129         }
2130       }
2131       else
2132       {
2133         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2134       }
2135       break;
2136     }
2137
2138     case WM_MOUSEMOVE:
2139       {
2140         //cout << "\t WM_MOUSEMOVE" << endl;
2141         WPARAM fwKeys = wParam;
2142         X_Motion = LOWORD(lParam);
2143         Y_Motion = HIWORD(lParam);
2144
2145         if ( Up &&
2146           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2147           {
2148             Up = 0;
2149             X_ButtonPress = LOWORD(lParam);
2150             Y_ButtonPress = HIWORD(lParam);
2151
2152             if ((fwKeys & MK_RBUTTON) != 0) {
2153               // Start rotation
2154               VT_ProcessButton3Press();
2155             }
2156           }
2157
2158           if ((fwKeys & MK_CONTROL) != 0)
2159           {
2160             if ((fwKeys & MK_LBUTTON) != 0)
2161             {
2162               ProcessControlButton1Motion();
2163             }
2164             else if ((fwKeys & MK_MBUTTON) != 0
2165                  || ((fwKeys & MK_LBUTTON) != 0
2166                   && (fwKeys & MK_RBUTTON) != 0))
2167             {
2168               VT_ProcessControlButton2Motion();
2169             }
2170             else if ((fwKeys & MK_RBUTTON) != 0)
2171             {
2172               VT_ProcessControlButton3Motion();
2173             }
2174           }
2175           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2176           {
2177             VT_ProcessMotion();
2178           }
2179       }
2180       break;
2181
2182     default:
2183       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2184     }
2185     return 0L;
2186 }
2187
2188 //==============================================================================
2189 //function : ViewerMainLoop
2190 //purpose  : Get a Event on the view and dispatch it
2191 //==============================================================================
2192
2193
2194 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2195 {
2196   Ppick = (argc > 0)? 1 : 0;
2197   Pargc = argc;
2198   Pargv = argv;
2199
2200   if ( Ppick ) {
2201     MSG msg;
2202     msg.wParam = 1;
2203
2204     cout << "Start picking" << endl;
2205
2206     while ( Ppick == 1 ) {
2207       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2208       if (GetMessageW (&msg, NULL, 0, 0))
2209       {
2210         TranslateMessage (&msg);
2211         DispatchMessageW (&msg);
2212       }
2213     }
2214
2215     cout << "Picking done" << endl;
2216   }
2217
2218   return Ppick;
2219 }
2220
2221 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2222
2223 int min( int a, int b )
2224 {
2225   if( a<b )
2226     return a;
2227   else
2228     return b;
2229 }
2230
2231 int max( int a, int b )
2232 {
2233   if( a>b )
2234     return a;
2235   else
2236     return b;
2237 }
2238
2239 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2240
2241 {
2242   static XEvent aReport;
2243   Standard_Boolean pick = argc > 0;
2244   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2245   XNextEvent (aDisplay, &aReport);
2246
2247   // Handle event for the chosen display connection
2248   switch (aReport.type) {
2249       case ClientMessage:
2250         {
2251           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2252           {
2253             // Close the window
2254             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2255           }
2256         }
2257         return 0;
2258      case FocusIn:
2259       {
2260          // Activate inactive view
2261          Window aWindow = GetWindowHandle(VT_GetWindow());
2262          if(aWindow != aReport.xfocus.window)
2263          {
2264            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2265          }
2266       }
2267       break;
2268       case Expose:
2269         {
2270           VT_ProcessExpose();
2271         }
2272         break;
2273       case ConfigureNotify:
2274         {
2275           VT_ProcessConfigure();
2276         }
2277         break;
2278       case KeyPress:
2279         {
2280
2281           KeySym ks_ret ;
2282           char buf_ret[11] ;
2283           int ret_len ;
2284           XComposeStatus status_in_out;
2285
2286           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2287             (char *) buf_ret , 10 ,
2288             &ks_ret , &status_in_out ) ;
2289
2290
2291           buf_ret[ret_len] = '\0' ;
2292
2293           if (ret_len)
2294           {
2295             VT_ProcessKeyPress (buf_ret);
2296           }
2297         }
2298         break;
2299       case ButtonPress:
2300         {
2301           X_ButtonPress = aReport.xbutton.x;
2302           Y_ButtonPress = aReport.xbutton.y;
2303
2304           if (aReport.xbutton.button == Button1)
2305           {
2306             if (aReport.xbutton.state & ControlMask)
2307             {
2308               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2309             }
2310             else
2311             {
2312               IsDragged = Standard_True;
2313               DragFirst = Standard_True;
2314             }
2315           }
2316           else if (aReport.xbutton.button == Button3)
2317           {
2318             // Start rotation
2319             VT_ProcessButton3Press();
2320           }
2321         }
2322         break;
2323       case ButtonRelease:
2324         {
2325           if( IsDragged )
2326           {
2327             if( !DragFirst )
2328             {
2329               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2330               {
2331                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2332                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2333               }
2334             }
2335
2336             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2337             if( aContext.IsNull() )
2338             {
2339               cout << "The context is null. Please use vinit before createmesh" << endl;
2340               return 0;
2341             }
2342
2343             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2344             if( aReport.xbutton.button==1 )
2345               if( DragFirst )
2346                 if( ShiftPressed )
2347                 {
2348                   aContext->ShiftSelect (Standard_True);
2349                 }
2350                 else
2351                 {
2352                   aContext->Select (Standard_True);
2353                 }
2354               else
2355                 if( ShiftPressed )
2356                 {
2357                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2358                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2359                                         ViewerTest::CurrentView(), Standard_True);
2360                 }
2361                 else
2362                 {
2363                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2364                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2365                                    ViewerTest::CurrentView(), Standard_True);
2366                 }
2367             else
2368               VT_ProcessButton3Release();
2369
2370             IsDragged = Standard_False;
2371           }
2372           else
2373             VT_ProcessButton3Release();
2374         }
2375         break;
2376       case MotionNotify:
2377         {
2378           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2379           {
2380             break;
2381           }
2382           if( IsDragged )
2383           {
2384             if( !DragFirst )
2385             {
2386               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2387               {
2388                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2389               }
2390             }
2391
2392             X_Motion = aReport.xmotion.x;
2393             Y_Motion = aReport.xmotion.y;
2394             DragFirst = Standard_False;
2395
2396             Window aWindow = GetWindowHandle(VT_GetWindow());
2397             Window aRoot;
2398             int anX, anY;
2399             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2400             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2401             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2402             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2403             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2404           }
2405           else
2406           {
2407             X_Motion = aReport.xmotion.x;
2408             Y_Motion = aReport.xmotion.y;
2409
2410             // remove all the ButtonMotionMaskr
2411             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2412
2413             if ( aReport.xmotion.state & ControlMask ) {
2414               if ( aReport.xmotion.state & Button1Mask ) {
2415                 ProcessControlButton1Motion();
2416               }
2417               else if ( aReport.xmotion.state & Button2Mask ) {
2418                 VT_ProcessControlButton2Motion();
2419               }
2420               else if ( aReport.xmotion.state & Button3Mask ) {
2421                 VT_ProcessControlButton3Motion();
2422               }
2423             }
2424             else
2425             {
2426               VT_ProcessMotion();
2427             }
2428           }
2429         }
2430         break;
2431 }
2432 return pick;
2433 }
2434
2435 //==============================================================================
2436 //function : VProcessEvents
2437 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2438 //       event in the Viewer window
2439 //==============================================================================
2440
2441 static void VProcessEvents(ClientData,int)
2442 {
2443   NCollection_Vector<int> anEventNumbers;
2444   // Get number of messages from every display
2445   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2446        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2447   {
2448     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2449   }
2450     // Handle events for every display
2451   int anEventIter = 0;
2452   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2453        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2454   {
2455     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2456          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2457     {
2458       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2459       int anEventResult = ViewerMainLoop( 0, NULL);
2460       // If window is closed or context was not found finish current event processing loop
2461       if (!anEventResult)
2462         return;
2463     }
2464   }
2465
2466   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2467
2468 }
2469 #endif
2470
2471 //==============================================================================
2472 //function : OSWindowSetup
2473 //purpose  : Setup for the X11 window to be able to cath the event
2474 //==============================================================================
2475
2476
2477 static void OSWindowSetup()
2478 {
2479 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2480   // X11
2481
2482   Window  window   = VT_GetWindow()->XWindow();
2483   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2484   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2485   XSynchronize(aDisplay, 1);
2486
2487   // X11 : For keyboard on SUN
2488   XWMHints wmhints;
2489   wmhints.flags = InputHint;
2490   wmhints.input = 1;
2491
2492   XSetWMHints( aDisplay, window, &wmhints);
2493
2494   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2495     ButtonPressMask | ButtonReleaseMask |
2496     StructureNotifyMask |
2497     PointerMotionMask |
2498     Button1MotionMask | Button2MotionMask |
2499     Button3MotionMask | FocusChangeMask
2500     );
2501   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2502   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2503
2504   XSynchronize(aDisplay, 0);
2505
2506 #else
2507   // _WIN32
2508 #endif
2509
2510 }
2511
2512 //==============================================================================
2513 //function : VFit
2514 //purpose  :
2515 //==============================================================================
2516
2517 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2518 {
2519   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2520   if (aView.IsNull())
2521   {
2522     std::cout << "Error: no active viewer!\n";
2523     return 1;
2524   }
2525
2526   Standard_Boolean toFit = Standard_True;
2527   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2528   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2529   {
2530     TCollection_AsciiString anArg (theArgv[anArgIter]);
2531     anArg.LowerCase();
2532     if (anUpdateTool.parseRedrawMode (anArg))
2533     {
2534       continue;
2535     }
2536     else if (anArg == "-selected")
2537     {
2538       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2539       toFit = Standard_False;
2540     }
2541     else
2542     {
2543       std::cout << "Syntax error at '" << anArg << "'\n";
2544     }
2545   }
2546
2547   if (toFit)
2548   {
2549     aView->FitAll (0.01, Standard_False);
2550   }
2551   return 0;
2552 }
2553
2554 //=======================================================================
2555 //function : VFitArea
2556 //purpose  : Fit view to show area located between two points
2557 //         : given in world 2D or 3D coordinates.
2558 //=======================================================================
2559 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2560 {
2561   Handle(V3d_View) aView = ViewerTest::CurrentView();
2562   if (aView.IsNull())
2563   {
2564     std::cerr << theArgVec[0] << "Error: No active view.\n";
2565     return 1;
2566   }
2567
2568   // Parse arguments.
2569   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2570   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2571
2572   if (theArgNb == 5)
2573   {
2574     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2575     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2576     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2577     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2578   }
2579   else if (theArgNb == 7)
2580   {
2581     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2582     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2583     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2584     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2585     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2586     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2587   }
2588   else
2589   {
2590     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2591     theDI.PrintHelp(theArgVec[0]);
2592     return 1;
2593   }
2594
2595   // Convert model coordinates to view space
2596   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2597   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2598   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2599
2600   // Determine fit area
2601   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2602   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2603
2604   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2605
2606   if (aDiagonal < Precision::Confusion())
2607   {
2608     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2609     return 1;
2610   }
2611
2612   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2613   return 0;
2614 }
2615
2616 //==============================================================================
2617 //function : VZFit
2618 //purpose  : ZFitall, no DRAW arguments
2619 //Draw arg : No args
2620 //==============================================================================
2621 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2622 {
2623   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2624
2625   if (aCurrentView.IsNull())
2626   {
2627     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2628     return 1;
2629   }
2630
2631   if (theArgsNb == 1)
2632   {
2633     aCurrentView->ZFitAll();
2634     aCurrentView->Redraw();
2635     return 0;
2636   }
2637
2638   Standard_Real aScale = 1.0;
2639
2640   if (theArgsNb >= 2)
2641   {
2642     aScale = Draw::Atoi (theArgVec[1]);
2643   }
2644
2645   aCurrentView->ZFitAll (aScale);
2646   aCurrentView->Redraw();
2647
2648   return 0;
2649 }
2650
2651 //==============================================================================
2652 //function : VRepaint
2653 //purpose  :
2654 //==============================================================================
2655 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2656 {
2657   Handle(V3d_View) aView = ViewerTest::CurrentView();
2658   if (aView.IsNull())
2659   {
2660     std::cout << "Error: no active viewer!\n";
2661     return 1;
2662   }
2663
2664   Standard_Boolean isImmediateUpdate = Standard_False;
2665   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2666   {
2667     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2668     anArg.LowerCase();
2669     if (anArg == "-immediate")
2670     {
2671       isImmediateUpdate = Standard_True;
2672       if (anArgIter + 1 < theArgNb
2673        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2674       {
2675         ++anArgIter;
2676       }
2677     }
2678     else
2679     {
2680       std::cout << "Syntax error at '" << anArg << "'\n";
2681     }
2682   }
2683
2684   if (isImmediateUpdate)
2685   {
2686     aView->RedrawImmediate();
2687   }
2688   else
2689   {
2690     aView->Redraw();
2691   }
2692   return 0;
2693 }
2694
2695 //==============================================================================
2696 //function : VClear
2697 //purpose  : Remove all the object from the viewer
2698 //Draw arg : No args
2699 //==============================================================================
2700
2701 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2702 {
2703   Handle(V3d_View) V = ViewerTest::CurrentView();
2704   if(!V.IsNull())
2705     ViewerTest::Clear();
2706   return 0;
2707 }
2708
2709 //==============================================================================
2710 //function : VPick
2711 //purpose  :
2712 //==============================================================================
2713
2714 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2715 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2716
2717 if ( argc < 4 ) {
2718   di << argv[0] << "Invalid number of arguments\n";
2719   return 1;
2720 }
2721
2722 while (ViewerMainLoop( argc, argv)) {
2723 }
2724
2725 return 0;
2726 }
2727
2728 //==============================================================================
2729 //function : VSetBg
2730 //purpose  : Load image as background
2731 //==============================================================================
2732
2733 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2734 {
2735   if (argc < 2 || argc > 3)
2736   {
2737     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2738     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2739     return 1;
2740   }
2741
2742   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2743   if(AISContext.IsNull())
2744   {
2745     di << "use 'vinit' command before " << argv[0] << "\n";
2746     return 1;
2747   }
2748
2749   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2750   if (argc == 3)
2751   {
2752     const char* szType = argv[2];
2753     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2754     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2755     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2756     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2757     else
2758     {
2759       di << "Wrong fill type : " << szType << "\n";
2760       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2761       return 1;
2762     }
2763   }
2764
2765   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2766   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2767
2768   return 0;
2769 }
2770
2771 //==============================================================================
2772 //function : VSetBgMode
2773 //purpose  : Change background image fill type
2774 //==============================================================================
2775
2776 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2777 {
2778   if (argc != 2)
2779   {
2780     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2781     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2782     return 1;
2783   }
2784
2785   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2786   if(AISContext.IsNull())
2787   {
2788     di << "use 'vinit' command before " << argv[0] << "\n";
2789     return 1;
2790   }
2791   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2792   const char* szType = argv[1];
2793   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2794   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2795   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2796   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2797   else
2798   {
2799     di << "Wrong fill type : " << szType << "\n";
2800     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2801     return 1;
2802   }
2803   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2804   V3dView->SetBgImageStyle(aFillType, Standard_True);
2805   return 0;
2806 }
2807
2808 //==============================================================================
2809 //function : VSetGradientBg
2810 //purpose  : Mount gradient background
2811 //==============================================================================
2812 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2813 {
2814   if (argc != 8 )
2815   {
2816     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2817     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2818     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2819     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2820     return 1;
2821   }
2822
2823   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2824   if(AISContext.IsNull())
2825   {
2826     di << "use 'vinit' command before " << argv[0] << "\n";
2827     return 1;
2828   }
2829   if (argc == 8)
2830   {
2831
2832     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2833     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2834     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2835     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2836
2837     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2838     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2839     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2840
2841     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2842     int aType = Draw::Atoi(argv[7]);
2843     if( aType < 0 || aType > 8 )
2844     {
2845       di << "Wrong fill type \n";
2846       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2847       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2848       return 1;
2849     }
2850
2851     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2852
2853     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2854     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2855   }
2856
2857   return 0;
2858 }
2859
2860 //==============================================================================
2861 //function : VSetGradientBgMode
2862 //purpose  : Change gradient background fill style
2863 //==============================================================================
2864 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2865 {
2866   if (argc != 2 )
2867   {
2868     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2869     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2870     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2871     return 1;
2872   }
2873
2874   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2875   if(AISContext.IsNull())
2876   {
2877     di << "use 'vinit' command before " << argv[0] << "\n";
2878     return 1;
2879   }
2880   if (argc == 2)
2881   {
2882     int aType = Draw::Atoi(argv[1]);
2883     if( aType < 0 || aType > 8 )
2884     {
2885       di << "Wrong fill type \n";
2886       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2887       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2888       return 1;
2889     }
2890
2891     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2892
2893     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2894     V3dView->SetBgGradientStyle( aMethod, 1 );
2895   }
2896
2897   return 0;
2898 }
2899
2900 //==============================================================================
2901 //function : VSetColorBg
2902 //purpose  : Set color background
2903 //==============================================================================
2904 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2905 {
2906   if (argc != 4 )
2907   {
2908     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2909     di << "R,G,B = [0..255]\n";
2910     return 1;
2911   }
2912
2913   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2914   if(AISContext.IsNull())
2915   {
2916     di << "use 'vinit' command before " << argv[0] << "\n";
2917     return 1;
2918   }
2919   if (argc == 4)
2920   {
2921
2922     Standard_Real R = Draw::Atof(argv[1])/255.;
2923     Standard_Real G = Draw::Atof(argv[2])/255.;
2924     Standard_Real B = Draw::Atof(argv[3])/255.;
2925     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2926
2927     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2928     V3dView->SetBackgroundColor( aColor );
2929     V3dView->Update();
2930   }
2931
2932   return 0;
2933 }
2934
2935 //==============================================================================
2936 //function : VSetDefaultBg
2937 //purpose  : Set default viewer background fill color
2938 //==============================================================================
2939 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2940 {
2941   if (theArgNb != 4
2942    && theArgNb != 8)
2943   {
2944     std::cout << "Error: wrong syntax! See usage:\n";
2945     theDI.PrintHelp (theArgVec[0]);
2946     return 1;
2947   }
2948
2949   ViewerTest_DefaultBackground.FillMethod =
2950     theArgNb == 4 ? Aspect_GFM_NONE
2951                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2952
2953   if (theArgNb == 4)
2954   {
2955     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2956     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2957     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2958     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2959   }
2960   else
2961   {
2962     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2963     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2964     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2965     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2966
2967     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2968     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2969     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2970     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2971   }
2972
2973   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2974        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2975   {
2976     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2977     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2978     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2979                                          ViewerTest_DefaultBackground.GradientColor2,
2980                                          ViewerTest_DefaultBackground.FillMethod);
2981   }
2982
2983   return 0;
2984 }
2985
2986 //==============================================================================
2987 //function : VScale
2988 //purpose  : View Scaling
2989 //==============================================================================
2990
2991 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2992 {
2993   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2994   if ( V3dView.IsNull() ) return 1;
2995
2996   if ( argc != 4 ) {
2997     di << argv[0] << "Invalid number of arguments\n";
2998     return 1;
2999   }
3000   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3001   return 0;
3002 }
3003 //==============================================================================
3004 //function : VZBuffTrihedron
3005 //purpose  :
3006 //==============================================================================
3007
3008 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3009                             Standard_Integer  theArgNb,
3010                             const char**      theArgVec)
3011 {
3012   Handle(V3d_View) aView = ViewerTest::CurrentView();
3013   if (aView.IsNull())
3014   {
3015     std::cout << "Error: no active viewer!\n";
3016     return 1;
3017   }
3018
3019   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3020
3021   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3022   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3023   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3024   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3025   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3026   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3027   Standard_Real                 aScale        = 0.1;
3028   Standard_Real                 aSizeRatio    = 0.8;
3029   Standard_Real                 anArrowDiam   = 0.05;
3030   Standard_Integer              aNbFacets     = 12;
3031   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3032   {
3033     Standard_CString        anArg = theArgVec[anArgIter];
3034     TCollection_AsciiString aFlag (anArg);
3035     aFlag.LowerCase();
3036     if (anUpdateTool.parseRedrawMode (aFlag))
3037     {
3038       continue;
3039     }
3040     else if (aFlag == "-on")
3041     {
3042       continue;
3043     }
3044     else if (aFlag == "-off")
3045     {
3046       aView->TriedronErase();
3047       return 0;
3048     }
3049     else if (aFlag == "-pos"
3050           || aFlag == "-position"
3051           || aFlag == "-corner")
3052     {
3053       if (++anArgIter >= theArgNb)
3054       {
3055         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3056         return 1;
3057       }
3058
3059       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3060       aPosName.LowerCase();
3061       if (aPosName == "center")
3062       {
3063         aPosition = Aspect_TOTP_CENTER;
3064       }
3065       else if (aPosName == "left_lower"
3066             || aPosName == "lower_left"
3067             || aPosName == "leftlower"
3068             || aPosName == "lowerleft")
3069       {
3070         aPosition = Aspect_TOTP_LEFT_LOWER;
3071       }
3072       else if (aPosName == "left_upper"
3073             || aPosName == "upper_left"
3074             || aPosName == "leftupper"
3075             || aPosName == "upperleft")
3076       {
3077         aPosition = Aspect_TOTP_LEFT_UPPER;
3078       }
3079       else if (aPosName == "right_lower"
3080             || aPosName == "lower_right"
3081             || aPosName == "rightlower"
3082             || aPosName == "lowerright")
3083       {
3084         aPosition = Aspect_TOTP_RIGHT_LOWER;
3085       }
3086       else if (aPosName == "right_upper"
3087             || aPosName == "upper_right"
3088             || aPosName == "rightupper"
3089             || aPosName == "upperright")
3090       {
3091         aPosition = Aspect_TOTP_RIGHT_UPPER;
3092       }
3093       else
3094       {
3095         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3096         return 1;
3097       }
3098     }
3099     else if (aFlag == "-type")
3100     {
3101       if (++anArgIter >= theArgNb)
3102       {
3103         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3104         return 1;
3105       }
3106
3107       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3108       aTypeName.LowerCase();
3109       if (aTypeName == "wireframe"
3110        || aTypeName == "wire")
3111       {
3112         aVisType = V3d_WIREFRAME;
3113       }
3114       else if (aTypeName == "zbuffer"
3115             || aTypeName == "shaded")
3116       {
3117         aVisType = V3d_ZBUFFER;
3118       }
3119       else
3120       {
3121         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3122       }
3123     }
3124     else if (aFlag == "-scale")
3125     {
3126       if (++anArgIter >= theArgNb)
3127       {
3128         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3129         return 1;
3130       }
3131
3132       aScale = Draw::Atof (theArgVec[anArgIter]);
3133     }
3134     else if (aFlag == "-size"
3135           || aFlag == "-sizeratio")
3136     {
3137       if (++anArgIter >= theArgNb)
3138       {
3139         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3140         return 1;
3141       }
3142
3143       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3144     }
3145     else if (aFlag == "-arrowdiam"
3146           || aFlag == "-arrowdiameter")
3147     {
3148       if (++anArgIter >= theArgNb)
3149       {
3150         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3151         return 1;
3152       }
3153
3154       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3155     }
3156     else if (aFlag == "-nbfacets")
3157     {
3158       if (++anArgIter >= theArgNb)
3159       {
3160         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3161         return 1;
3162       }
3163
3164       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3165     }
3166     else if (aFlag == "-colorlabel"
3167           || aFlag == "-colorlabels")
3168     {
3169       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3170                                                            theArgVec + anArgIter + 1,
3171                                                            aLabelsColor);
3172       if (aNbParsed == 0)
3173       {
3174         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3175         return 1;
3176       }
3177       anArgIter += aNbParsed;
3178     }
3179     else if (aFlag == "-colorarrowx")
3180     {
3181       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3182                                                            theArgVec + anArgIter + 1,
3183                                                            anArrowColorX);
3184       if (aNbParsed == 0)
3185       {
3186         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3187         return 1;
3188       }
3189       anArgIter += aNbParsed;
3190     }
3191     else if (aFlag == "-colorarrowy")
3192     {
3193       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3194                                                            theArgVec + anArgIter + 1,
3195                                                            anArrowColorY);
3196       if (aNbParsed == 0)
3197       {
3198         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3199         return 1;
3200       }
3201       anArgIter += aNbParsed;
3202     }
3203     else if (aFlag == "-colorarrowz")
3204     {
3205       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3206                                                            theArgVec + anArgIter + 1,
3207                                                            anArrowColorZ);
3208       if (aNbParsed == 0)
3209       {
3210         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3211         return 1;
3212       }
3213       anArgIter += aNbParsed;
3214     }
3215     else
3216     {
3217       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3218       return 1;
3219     }
3220   }
3221
3222   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3223                                aSizeRatio, anArrowDiam, aNbFacets);
3224   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3225   aView->ZFitAll();
3226   return 0;
3227 }
3228
3229 //==============================================================================
3230 //function : VRotate
3231 //purpose  : Camera Rotating
3232 //==============================================================================
3233
3234 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3235 {
3236   Handle(V3d_View) aView = ViewerTest::CurrentView();
3237   if (aView.IsNull())
3238   {
3239     std::cout << "No active view!\n";
3240     return 1;
3241   }
3242
3243   Standard_Boolean hasFlags = Standard_False;
3244   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3245   {
3246     Standard_CString        anArg (theArgVec[anArgIter]);
3247     TCollection_AsciiString aFlag (anArg);
3248     aFlag.LowerCase();
3249     if (aFlag == "-mousestart"
3250      || aFlag == "-mousefrom")
3251     {
3252       hasFlags = Standard_True;
3253       if (anArgIter + 2 >= theArgNb)
3254       {
3255         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3256         return 1;
3257       }
3258
3259       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3260       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3261       aView->StartRotation (anX, anY);
3262     }
3263     else if (aFlag == "-mousemove")
3264     {
3265       hasFlags = Standard_True;
3266       if (anArgIter + 2 >= theArgNb)
3267       {
3268         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3269         return 1;
3270       }
3271
3272       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3273       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3274       aView->Rotation (anX, anY);
3275     }
3276     else if (theArgNb != 4
3277           && theArgNb != 7)
3278     {
3279       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3280       return 1;
3281     }
3282   }
3283
3284   if (hasFlags)
3285   {
3286     return 0;
3287   }
3288   else if (theArgNb == 4)
3289   {
3290     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3291     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3292     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3293     aView->Rotate (anAX, anAY, anAZ);
3294     return 0;
3295   }
3296   else if (theArgNb == 7)
3297   {
3298     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3299     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3300     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3301
3302     Standard_Real anX = Draw::Atof (theArgVec[4]);
3303     Standard_Real anY = Draw::Atof (theArgVec[5]);
3304     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3305
3306     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3307     return 0;
3308   }
3309
3310   std::cout << "Error: Invalid number of arguments\n";
3311   return 1;
3312 }
3313
3314 //==============================================================================
3315 //function : VZoom
3316 //purpose  : View zoom in / out (relative to current zoom)
3317 //==============================================================================
3318
3319 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3320   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3321   if ( V3dView.IsNull() ) {
3322     return 1;
3323   }
3324
3325   if ( argc == 2 ) {
3326     Standard_Real coef = Draw::Atof(argv[1]);
3327     if ( coef <= 0.0 ) {
3328       di << argv[1] << "Invalid value\n";
3329       return 1;
3330     }
3331     V3dView->SetZoom( Draw::Atof(argv[1]) );
3332     return 0;
3333   } else {
3334     di << argv[0] << " Invalid number of arguments\n";
3335     return 1;
3336   }
3337 }
3338
3339 //==============================================================================
3340 //function : VPan
3341 //purpose  : View panning (in pixels)
3342 //==============================================================================
3343
3344 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3345   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3346   if ( V3dView.IsNull() ) return 1;
3347
3348   if ( argc == 3 ) {
3349     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3350     return 0;
3351   } else {
3352     di << argv[0] << " Invalid number of arguments\n";
3353     return 1;
3354   }
3355 }
3356
3357 //==============================================================================
3358 //function : VPlace
3359 //purpose  : Place the point (in pixels) at the center of the window
3360 //==============================================================================
3361 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3362 {
3363   Handle(V3d_View) aView = ViewerTest::CurrentView();
3364   if (aView.IsNull())
3365   {
3366     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3367     return 1;
3368   }
3369
3370   if (theArgNb != 3)
3371   {
3372     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3373     return 1;
3374   }
3375
3376   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3377
3378   return 0;
3379 }
3380
3381 //==============================================================================
3382 //function : VExport
3383 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3384 //==============================================================================
3385
3386 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3387 {
3388   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3389   if (V3dView.IsNull())
3390     return 1;
3391
3392   if (argc == 1)
3393   {
3394     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3395     return 1;
3396   }
3397
3398   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3399   TCollection_AsciiString aFormatStr;
3400
3401   TCollection_AsciiString aFileName (argv[1]);
3402   Standard_Integer aLen = aFileName.Length();
3403
3404   if (argc > 2)
3405   {
3406     aFormatStr = TCollection_AsciiString (argv[2]);
3407   }
3408   else if (aLen >= 4)
3409   {
3410     if (aFileName.Value (aLen - 2) == '.')
3411     {
3412       aFormatStr = aFileName.ToCString() + aLen - 2;
3413     }
3414     else if (aFileName.Value (aLen - 3) == '.')
3415     {
3416       aFormatStr = aFileName.ToCString() + aLen - 3;
3417     }
3418     else
3419     {
3420       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3421       return 1;
3422     }
3423   }
3424   else
3425   {
3426     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3427     return 1;
3428   }
3429
3430   aFormatStr.UpperCase();
3431   if (aFormatStr == "PS")
3432     anExpFormat = Graphic3d_EF_PostScript;
3433   else if (aFormatStr == "EPS")
3434     anExpFormat = Graphic3d_EF_EnhPostScript;
3435   else if (aFormatStr == "TEX")
3436     anExpFormat = Graphic3d_EF_TEX;
3437   else if (aFormatStr == "PDF")
3438     anExpFormat = Graphic3d_EF_PDF;
3439   else if (aFormatStr == "SVG")
3440     anExpFormat = Graphic3d_EF_SVG;
3441   else if (aFormatStr == "PGF")
3442     anExpFormat = Graphic3d_EF_PGF;
3443   else if (aFormatStr == "EMF")
3444     anExpFormat = Graphic3d_EF_EMF;
3445   else
3446   {
3447     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3448     return 1;
3449   }
3450
3451   Standard_DISABLE_DEPRECATION_WARNINGS
3452   try
3453   {
3454     if (!V3dView->Export (argv[1], anExpFormat))
3455     {
3456       di << "Error: export of image to " << aFormatStr << " failed!\n";
3457     }
3458   }
3459   catch (Standard_Failure const& anException)
3460   {
3461     di << "Error: export of image to " << aFormatStr << " failed";
3462     di << " (exception: " << anException.GetMessageString() << ")";
3463   }
3464   Standard_ENABLE_DEPRECATION_WARNINGS
3465   return 0;
3466 }
3467
3468 static int VColorScale (Draw_Interpretor& theDI,
3469                         Standard_Integer  theArgNb,
3470                         const char**      theArgVec)
3471 {
3472   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3473   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3474   if (aContext.IsNull())
3475   {
3476     std::cout << "Error: no active view!\n";
3477     return 1;
3478   }
3479   if (theArgNb <= 1)
3480   {
3481     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3482     return 1;
3483   }
3484
3485   Handle(AIS_ColorScale) aColorScale;
3486   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3487   {
3488     // find existing object
3489     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3490     if (aColorScale.IsNull())
3491     {
3492       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3493       return 1;
3494     }
3495   }
3496
3497   if (theArgNb <= 2)
3498   {
3499     if (aColorScale.IsNull())
3500     {
3501       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3502       return 1;
3503     }
3504
3505     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3506           << "Min range: "            << aColorScale->GetMin() << "\n"
3507           << "Max range: "            << aColorScale->GetMax() << "\n"
3508           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3509           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3510           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3511           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3512           << "Label position: ";
3513     switch (aColorScale->GetLabelPosition())
3514     {
3515       case Aspect_TOCSP_NONE:
3516         theDI << "None\n";
3517         break;
3518       case Aspect_TOCSP_LEFT:
3519         theDI << "Left\n";
3520         break;
3521       case Aspect_TOCSP_RIGHT:
3522         theDI << "Right\n";
3523         break;
3524       case Aspect_TOCSP_CENTER:
3525         theDI << "Center\n";
3526         break;
3527     }
3528     return 0;
3529   }
3530
3531   if (aColorScale.IsNull())
3532   {
3533     aColorScale = new AIS_ColorScale();
3534     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3535     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3536   }
3537
3538   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3539   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3540   {
3541     Standard_CString        anArg = theArgVec[anArgIter];
3542     TCollection_AsciiString aFlag (anArg);
3543     aFlag.LowerCase();
3544     if (anUpdateTool.parseRedrawMode (aFlag))
3545     {
3546       continue;
3547     }
3548     else if (aFlag == "-range")
3549     {
3550       if (anArgIter + 3 >= theArgNb)
3551       {
3552         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3553         return 1;
3554       }
3555
3556       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3557       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3558       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3559       if (!aRangeMin.IsRealValue()
3560        || !aRangeMax.IsRealValue())
3561       {
3562         std::cout << "Error: the range values should be real!\n";
3563         return 1;
3564       }
3565       else if (!aNbIntervals.IsIntegerValue())
3566       {
3567         std::cout << "Error: the number of intervals should be integer!\n";
3568         return 1;
3569       }
3570
3571       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3572       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3573     }
3574     else if (aFlag == "-font")
3575     {
3576       if (anArgIter + 1 >= theArgNb)
3577       {
3578         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3579         return 1;
3580       }
3581       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3582       if (!aFontArg.IsIntegerValue())
3583       {
3584         std::cout << "Error: HeightFont value should be integer!\n";
3585         return 1;
3586       }
3587
3588       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3589       anArgIter += 1;
3590     }
3591     else if (aFlag == "-textpos")
3592     {
3593       if (anArgIter + 1 >= theArgNb)
3594       {
3595         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3596         return 1;
3597       }
3598
3599       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3600       aTextPosArg.LowerCase();
3601       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3602       if (aTextPosArg == "none")
3603       {
3604         aLabPosition = Aspect_TOCSP_NONE;
3605       }
3606       else if (aTextPosArg == "left")
3607       {
3608         aLabPosition = Aspect_TOCSP_LEFT;
3609       }
3610       else if (aTextPosArg == "right")
3611       {
3612         aLabPosition = Aspect_TOCSP_RIGHT;
3613       }
3614       else if (aTextPosArg == "center")
3615       {
3616         aLabPosition = Aspect_TOCSP_CENTER;
3617       }
3618       else
3619       {
3620         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3621         return 1;
3622       }
3623       aColorScale->SetLabelPosition (aLabPosition);
3624     }
3625     else if (aFlag == "-logarithmic"
3626           || aFlag == "-log")
3627     {
3628       if (anArgIter + 1 >= theArgNb)
3629       {
3630         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3631         return 1;
3632       }
3633
3634       Standard_Boolean IsLog;
3635       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3636       {
3637         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3638         return 1;
3639       }
3640       aColorScale->SetLogarithmic (IsLog);
3641     }
3642     else if (aFlag == "-huerange"
3643           || aFlag == "-hue")
3644     {
3645       if (anArgIter + 2 >= theArgNb)
3646       {
3647         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3648         return 1;
3649       }
3650
3651       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3652       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3653       aColorScale->SetHueRange (aHueMin, aHueMax);
3654     }
3655     else if (aFlag == "-colorrange")
3656     {
3657       Quantity_Color aColorMin, aColorMax;
3658       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3659                                                             theArgVec + (anArgIter + 1),
3660                                                             aColorMin);
3661       anArgIter += aNbParsed1;
3662       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3663                                                             theArgVec + (anArgIter + 1),
3664                                                             aColorMax);
3665       anArgIter += aNbParsed2;
3666       if (aNbParsed1 == 0
3667        || aNbParsed2 == 0)
3668       {
3669         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3670         return 1;
3671       }
3672
3673       aColorScale->SetColorRange (aColorMin, aColorMax);
3674     }
3675     else if (aFlag == "-reversed"
3676           || aFlag == "-inverted"
3677           || aFlag == "-topdown"
3678           || aFlag == "-bottomup")
3679     {
3680       Standard_Boolean toEnable = Standard_True;
3681       if (anArgIter + 1 < theArgNb
3682        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3683       {
3684         ++anArgIter;
3685       }
3686       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3687     }
3688     else if (aFlag == "-smooth"
3689           || aFlag == "-smoothtransition")
3690     {
3691       Standard_Boolean toEnable = Standard_True;
3692       if (anArgIter + 1 < theArgNb
3693        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3694       {
3695         ++anArgIter;
3696       }
3697       aColorScale->SetSmoothTransition (toEnable);
3698     }
3699     else if (aFlag == "-xy")
3700     {
3701       if (anArgIter + 2 >= theArgNb)
3702       {
3703         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3704         return 1;
3705       }
3706
3707       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3708       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3709       if (!anX.IsIntegerValue()
3710        || !anY.IsIntegerValue())
3711       {
3712         std::cout << "Error: coordinates should be integer values!\n";
3713         return 1;
3714       }
3715
3716       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3717     }
3718     else if (aFlag == "-width"
3719           || aFlag == "-w"
3720           || aFlag == "-breadth")
3721     {
3722       if (anArgIter + 1 >= theArgNb)
3723       {
3724         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3725         return 1;
3726       }
3727
3728       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3729       if (!aBreadth.IsIntegerValue())
3730       {
3731         std::cout << "Error: a width should be an integer value!\n";
3732         return 1;
3733       }
3734       aColorScale->SetBreadth (aBreadth.IntegerValue());
3735     }
3736     else if (aFlag == "-height"
3737           || aFlag == "-h")
3738     {
3739       if (anArgIter + 1 >= theArgNb)
3740       {
3741         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3742         return 1;
3743       }
3744
3745       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3746       if (!aHeight.IsIntegerValue())
3747       {
3748         std::cout << "Error: a width should be an integer value!\n";
3749         return 1;
3750       }
3751       aColorScale->SetHeight (aHeight.IntegerValue());
3752     }
3753     else if (aFlag == "-color")
3754     {
3755       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3756       {
3757         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3758         return 1;
3759       }
3760       else if (anArgIter + 2 >= theArgNb)
3761       {
3762         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3763         return 1;
3764       }
3765
3766       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3767       if (!anInd.IsIntegerValue())
3768       {
3769         std::cout << "Error: Index value should be integer!\n";
3770         return 1;
3771       }
3772       const Standard_Integer anIndex = anInd.IntegerValue();
3773       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3774       {
3775         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3776         return 1;
3777       }
3778
3779       Quantity_Color aColor;
3780       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3781                                                            theArgVec + (anArgIter + 1),
3782                                                            aColor);
3783       if (aNbParsed == 0)
3784       {
3785         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3786         return 1;
3787       }
3788       aColorScale->SetIntervalColor (aColor, anIndex);
3789       aColorScale->SetColorType (Aspect_TOCSD_USER);
3790       anArgIter += aNbParsed;
3791     }
3792     else if (aFlag == "-label")
3793     {
3794       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3795       {
3796         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3797         return 1;
3798       }
3799       else if (anArgIter + 2 >= theArgNb)
3800       {
3801         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3802         return 1;
3803       }
3804
3805       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3806       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
3807       {
3808         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
3809         return 1;
3810       }
3811
3812       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3813       aColorScale->SetLabel     (aText, anIndex);
3814       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3815       anArgIter += 2;
3816     }
3817     else if (aFlag == "-labelat"
3818           || aFlag == "-labat"
3819           || aFlag == "-labelatborder"
3820           || aFlag == "-labatborder"
3821           || aFlag == "-labelatcenter"
3822           || aFlag == "-labatcenter")
3823     {
3824       Standard_Boolean toEnable = Standard_True;
3825       if (aFlag == "-labelat"
3826        || aFlag == "-labat")
3827       {
3828         Standard_Integer aLabAtBorder = -1;
3829         if (++anArgIter >= theArgNb)
3830         {
3831           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
3832           anAtBorder.LowerCase();
3833           if (anAtBorder == "border")
3834           {
3835             aLabAtBorder = 1;
3836           }
3837           else if (anAtBorder == "center")
3838           {
3839             aLabAtBorder = 0;
3840           }
3841         }
3842         if (aLabAtBorder == -1)
3843         {
3844           std::cout << "Syntax error at argument '" << anArg << "'!\n";
3845           return 1;
3846         }
3847         toEnable = (aLabAtBorder == 1);
3848       }
3849       else if (anArgIter + 1 < theArgNb
3850             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3851       {
3852         ++anArgIter;
3853       }
3854       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
3855                                   || aFlag == "-labatcenter"
3856                                    ? !toEnable
3857                                    :  toEnable);
3858     }
3859     else if (aFlag == "-colors")
3860     {
3861       Aspect_SequenceOfColor aSeq;
3862       for (;;)
3863       {
3864         Quantity_Color aColor;
3865         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3866                                                              theArgVec + (anArgIter + 1),
3867                                                              aColor);
3868         if (aNbParsed == 0)
3869         {
3870           break;
3871         }
3872         anArgIter += aNbParsed;
3873         aSeq.Append (aColor);
3874       }
3875       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
3876       {
3877         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3878                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
3879         return 1;
3880       }
3881
3882       aColorScale->SetColors    (aSeq);
3883       aColorScale->SetColorType (Aspect_TOCSD_USER);
3884     }
3885     else if (aFlag == "-labels"
3886           || aFlag == "-freelabels")
3887     {
3888       if (anArgIter + 1 >= theArgNb)
3889       {
3890         std::cout << "Syntax error at argument '" << anArg << "'!\n";
3891         return 1;
3892       }
3893
3894       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
3895                                  ? aColorScale->GetNumberOfIntervals() + 1
3896                                  : aColorScale->GetNumberOfIntervals();
3897       if (aFlag == "-freelabels")
3898       {
3899         ++anArgIter;
3900         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
3901       }
3902       if (anArgIter + aNbLabels >= theArgNb)
3903       {
3904         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
3905         return 1;
3906       }
3907
3908       TColStd_SequenceOfExtendedString aSeq;
3909       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
3910       {
3911         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
3912       }
3913       aColorScale->SetLabels (aSeq);
3914       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3915     }
3916     else if (aFlag == "-title")
3917     {
3918       if (anArgIter + 1 >= theArgNb)
3919       {
3920         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3921         return 1;
3922       }
3923
3924       Standard_Boolean isTwoArgs = Standard_False;
3925       if (anArgIter + 2 < theArgNb)
3926       {
3927         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3928         aSecondArg.LowerCase();
3929       Standard_DISABLE_DEPRECATION_WARNINGS
3930         if (aSecondArg == "none")
3931         {
3932           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
3933           isTwoArgs = Standard_True;
3934         }
3935         else if (aSecondArg == "left")
3936         {
3937           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
3938           isTwoArgs = Standard_True;
3939         }
3940         else if (aSecondArg == "right")
3941         {
3942           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
3943           isTwoArgs = Standard_True;
3944         }
3945         else if (aSecondArg == "center")
3946         {
3947           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
3948           isTwoArgs = Standard_True;
3949         }
3950       Standard_ENABLE_DEPRECATION_WARNINGS
3951       }
3952
3953       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
3954       if (isTwoArgs)
3955       {
3956         anArgIter += 1;
3957       }
3958       anArgIter += 1;
3959     }
3960     else if (aFlag == "-demoversion"
3961           || aFlag == "-demo")
3962     {
3963       aColorScale->SetPosition (0, 0);
3964       aColorScale->SetTextHeight (16);
3965       aColorScale->SetRange (0.0, 100.0);
3966       aColorScale->SetNumberOfIntervals (10);
3967       aColorScale->SetBreadth (0);
3968       aColorScale->SetHeight  (0);
3969       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
3970       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
3971       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
3972     }
3973     else if (aFlag == "-findcolor")
3974     {
3975       if (anArgIter + 1 >= theArgNb)
3976       {
3977         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3978         return 1;
3979       }
3980
3981       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3982
3983       if (!anArg1.IsRealValue())
3984       {
3985         std::cout << "Error: the value should be real!\n";
3986         return 1;
3987       }
3988
3989       Quantity_Color aColor;
3990       aColorScale->FindColor (anArg1.RealValue(), aColor);
3991       theDI << Quantity_Color::StringName (aColor.Name());
3992       return 0;
3993     }
3994     else
3995     {
3996       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3997       return 1;
3998     }
3999   }
4000
4001   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4002   aView->Window()->Size (aWinWidth, aWinHeight);
4003   if (aColorScale->GetBreadth() == 0)
4004   {
4005     aColorScale->SetBreadth (aWinWidth);
4006   }
4007   if (aColorScale->GetHeight() == 0)
4008   {
4009     aColorScale->SetHeight (aWinHeight);
4010   }
4011   aColorScale->SetToUpdate();
4012   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4013   return 0;
4014 }
4015
4016 //==============================================================================
4017 //function : VGraduatedTrihedron
4018 //purpose  : Displays or hides a graduated trihedron
4019 //==============================================================================
4020 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4021                                   Quantity_Color& theColor)
4022 {
4023   Quantity_NameOfColor aColorName;
4024   TCollection_AsciiString aVal = theValue;
4025   aVal.UpperCase();
4026   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4027   {
4028     return Standard_False;
4029   }
4030   theColor = Quantity_Color (aColorName);
4031   return Standard_True;
4032 }
4033
4034 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4035 {
4036   if (theArgNum < 2)
4037   {
4038     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4039               << theArgs[0] <<"' for more information.\n";
4040     return 1;  //TCL_ERROR
4041   }
4042
4043   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4044   TCollection_AsciiString aParseKey;
4045   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4046   {
4047     TCollection_AsciiString anArg (theArgs [anArgIt]);
4048
4049     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4050     {
4051       aParseKey = anArg;
4052       aParseKey.Remove (1);
4053       aParseKey.LowerCase();
4054       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4055       continue;
4056     }
4057
4058     if (aParseKey.IsEmpty())
4059     {
4060       continue;
4061     }
4062
4063     aMapOfArgs(aParseKey)->Append (anArg);
4064   }
4065
4066   // Check parameters
4067   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4068        aMapIt.More(); aMapIt.Next())
4069   {
4070     const TCollection_AsciiString& aKey = aMapIt.Key();
4071     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4072
4073     // Bool key, without arguments
4074     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4075         && anArgs->IsEmpty())
4076     {
4077       continue;
4078     }
4079
4080     // One argument
4081     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4082           && anArgs->Length() == 1)
4083     {
4084       continue;
4085     }
4086
4087     // On/off arguments
4088     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4089         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4090         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4091         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4092         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4093     {
4094       continue;
4095     }
4096
4097     // One string argument
4098     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4099           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4100           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4101     {
4102       continue;
4103     }
4104
4105     // One integer argument
4106     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4107           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4108           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4109           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4110          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4111     {
4112       continue;
4113     }
4114
4115     // One real argument
4116     if ( aKey.IsEqual ("arrowlength")
4117          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4118     {
4119       continue;
4120     }
4121
4122     // Two string arguments
4123     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4124          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4125     {
4126       continue;
4127     }
4128
4129     TCollection_AsciiString aLowerKey;
4130     aLowerKey  = "-";
4131     aLowerKey += aKey;
4132     aLowerKey.LowerCase();
4133     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4134     std::cout << "Type help for more information.\n";
4135     return 1;
4136   }
4137
4138   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4139   if (anAISContext.IsNull())
4140   {
4141     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4142     return 1;
4143   }
4144
4145   Standard_Boolean toDisplay = Standard_True;
4146   Quantity_Color aColor;
4147   Graphic3d_GraduatedTrihedron aTrihedronData;
4148   // Process parameters
4149   Handle(TColStd_HSequenceOfAsciiString) aValues;
4150   if (aMapOfArgs.Find ("off", aValues))
4151   {
4152     toDisplay = Standard_False;
4153   }
4154
4155   // AXES NAMES
4156   if (aMapOfArgs.Find ("xname", aValues))
4157   {
4158     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4159   }
4160   if (aMapOfArgs.Find ("yname", aValues))
4161   {
4162     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4163   }
4164   if (aMapOfArgs.Find ("zname", aValues))
4165   {
4166     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4167   }
4168   if (aMapOfArgs.Find ("xdrawname", aValues))
4169   {
4170     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4171   }
4172   if (aMapOfArgs.Find ("ydrawname", aValues))
4173   {
4174     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4175   }
4176   if (aMapOfArgs.Find ("zdrawname", aValues))
4177   {
4178     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4179   }
4180   if (aMapOfArgs.Find ("xnameoffset", aValues))
4181   {
4182     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4183   }
4184   if (aMapOfArgs.Find ("ynameoffset", aValues))
4185   {
4186     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4187   }
4188   if (aMapOfArgs.Find ("znameoffset", aValues))
4189   {
4190     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4191   }
4192
4193   // COLORS
4194   if (aMapOfArgs.Find ("xnamecolor", aValues))
4195   {
4196     if (!GetColor (aValues->Value(1), aColor))
4197     {
4198       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4199       return 1;
4200     }
4201     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4202   }
4203   if (aMapOfArgs.Find ("ynamecolor", aValues))
4204   {
4205     if (!GetColor (aValues->Value(1), aColor))
4206     {
4207       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4208       return 1;
4209     }
4210     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4211   }
4212   if (aMapOfArgs.Find ("znamecolor", aValues))
4213   {
4214     if (!GetColor (aValues->Value(1), aColor))
4215     {
4216       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4217       return 1;
4218     }
4219     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4220   }
4221   if (aMapOfArgs.Find ("xcolor", aValues))
4222   {
4223     if (!GetColor (aValues->Value(1), aColor))
4224     {
4225       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4226       return 1;
4227     }
4228     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4229   }
4230   if (aMapOfArgs.Find ("ycolor", aValues))
4231   {
4232     if (!GetColor (aValues->Value(1), aColor))
4233     {
4234       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4235       return 1;
4236     }
4237     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4238   }
4239   if (aMapOfArgs.Find ("zcolor", aValues))
4240   {
4241     if (!GetColor (aValues->Value(1), aColor))
4242     {
4243       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4244       return 1;
4245     }
4246     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4247   }
4248
4249   // TICKMARKS
4250   if (aMapOfArgs.Find ("xticks", aValues))
4251   {
4252     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4253   }
4254   if (aMapOfArgs.Find ("yticks", aValues))
4255   {
4256     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4257   }
4258   if (aMapOfArgs.Find ("zticks", aValues))
4259   {
4260     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4261   }
4262   if (aMapOfArgs.Find ("xticklength", aValues))
4263   {
4264     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4265   }
4266   if (aMapOfArgs.Find ("yticklength", aValues))
4267   {
4268     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4269   }
4270   if (aMapOfArgs.Find ("zticklength", aValues))
4271   {
4272     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4273   }
4274   if (aMapOfArgs.Find ("xdrawticks", aValues))
4275   {
4276     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4277   }
4278   if (aMapOfArgs.Find ("ydrawticks", aValues))
4279   {
4280     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4281   }
4282   if (aMapOfArgs.Find ("zdrawticks", aValues))
4283   {
4284     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4285   }
4286
4287   // VALUES
4288   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4289   {
4290     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4291   }
4292   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4293   {
4294     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4295   }
4296   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4297   {
4298     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4299   }
4300   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4301   {
4302     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4303   }
4304   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4305   {
4306     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4307   }
4308   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4309   {
4310     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4311   }
4312
4313   // ARROWS
4314   if (aMapOfArgs.Find ("arrowlength", aValues))
4315   {
4316     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4317   }
4318
4319   // FONTS
4320   if (aMapOfArgs.Find ("namefont", aValues))
4321   {
4322     aTrihedronData.SetNamesFont (aValues->Value(1));
4323   }
4324   if (aMapOfArgs.Find ("valuesfont", aValues))
4325   {
4326     aTrihedronData.SetValuesFont (aValues->Value(1));
4327   }
4328
4329   if (aMapOfArgs.Find ("drawgrid", aValues))
4330   {
4331     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4332   }
4333   if (aMapOfArgs.Find ("drawaxes", aValues))
4334   {
4335     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4336   }
4337
4338   // The final step: display of erase trihedron
4339   if (toDisplay)
4340   {
4341     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4342   }
4343   else
4344   {
4345     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4346   }
4347
4348   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4349   ViewerTest::CurrentView()->Redraw();
4350
4351   return 0;
4352 }
4353
4354 //==============================================================================
4355 //function : VTile
4356 //purpose  :
4357 //==============================================================================
4358 static int VTile (Draw_Interpretor& theDI,
4359                   Standard_Integer  theArgNb,
4360                   const char**      theArgVec)
4361 {
4362   Handle(V3d_View) aView = ViewerTest::CurrentView();
4363   if (aView.IsNull())
4364   {
4365     std::cerr << "Error: no active viewer.\n";
4366     return 1;
4367   }
4368
4369   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4370   if (theArgNb < 2)
4371   {
4372     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4373           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4374           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4375     return 0;
4376   }
4377
4378   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4379   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4380   {
4381     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4382     anArg.LowerCase();
4383     if (anArg == "-lowerleft"
4384      || anArg == "-upperleft")
4385     {
4386       if (anArgIter + 3 < theArgNb)
4387       {
4388         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4389         return 1;
4390       }
4391       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4392       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4393       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4394     }
4395     else if (anArg == "-total"
4396           || anArg == "-totalsize"
4397           || anArg == "-viewsize")
4398     {
4399       if (anArgIter + 3 < theArgNb)
4400       {
4401         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4402         return 1;
4403       }
4404       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4405       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4406       if (aTile.TotalSize.x() < 1
4407        || aTile.TotalSize.y() < 1)
4408       {
4409         std::cerr << "Error: total size is incorrect.\n";
4410         return 1;
4411       }
4412     }
4413     else if (anArg == "-tilesize")
4414     {
4415       if (anArgIter + 3 < theArgNb)
4416       {
4417         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4418         return 1;
4419       }
4420
4421       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4422       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4423       if (aTile.TileSize.x() < 1
4424        || aTile.TileSize.y() < 1)
4425       {
4426         std::cerr << "Error: tile size is incorrect.\n";
4427         return 1;
4428       }
4429     }
4430     else if (anArg == "-unset")
4431     {
4432       aView->Camera()->SetTile (Graphic3d_CameraTile());
4433       aView->Redraw();
4434       return 0;
4435     }
4436   }
4437
4438   if (aTile.TileSize.x() < 1
4439    || aTile.TileSize.y() < 1)
4440   {
4441     std::cerr << "Error: tile size is undefined.\n";
4442     return 1;
4443   }
4444   else if (aTile.TotalSize.x() < 1
4445         || aTile.TotalSize.y() < 1)
4446   {
4447     std::cerr << "Error: total size is undefined.\n";
4448     return 1;
4449   }
4450
4451   aView->Camera()->SetTile (aTile);
4452   aView->Redraw();
4453   return 0;
4454 }
4455
4456 //! Format ZLayer ID.
4457 inline const char* formZLayerId (const Standard_Integer theLayerId)
4458 {
4459   switch (theLayerId)
4460   {
4461     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4462     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4463     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4464     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4465     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4466     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4467   }
4468   return "";
4469 }
4470
4471 //! Print the ZLayer information.
4472 inline void printZLayerInfo (Draw_Interpretor& theDI,
4473                              const Graphic3d_ZLayerSettings& theLayer)
4474 {
4475   if (!theLayer.Name().IsEmpty())
4476   {
4477     theDI << "  Name: " << theLayer.Name() << "\n";
4478   }
4479   if (theLayer.IsImmediate())
4480   {
4481     theDI << "  Immediate: TRUE\n";
4482   }
4483   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4484   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4485   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4486   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4487   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4488   {
4489     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4490   }
4491 }
4492
4493 //==============================================================================
4494 //function : VZLayer
4495 //purpose  : Test z layer operations for v3d viewer
4496 //==============================================================================
4497 static int VZLayer (Draw_Interpretor& theDI,
4498                     Standard_Integer  theArgNb,
4499                     const char**      theArgVec)
4500 {
4501   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4502   if (aContextAIS.IsNull())
4503   {
4504     std::cout << "No active viewer!\n";
4505     return 1;
4506   }
4507
4508   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4509   if (theArgNb < 2)
4510   {
4511     TColStd_SequenceOfInteger aLayers;
4512     aViewer->GetAllZLayers (aLayers);
4513     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4514     {
4515       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4516       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4517       printZLayerInfo (theDI, aSettings);
4518     }
4519     return 1;
4520   }
4521
4522   Standard_Integer anArgIter = 1;
4523   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4524   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4525   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4526   {
4527     ++anArgIter;
4528   }
4529
4530   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4531   if (aFirstArg.IsIntegerValue())
4532   {
4533     ++anArgIter;
4534     aLayerId = aFirstArg.IntegerValue();
4535   }
4536   else
4537   {
4538     aFirstArg.LowerCase();
4539     if (aFirstArg == "default"
4540      || aFirstArg == "def")
4541     {
4542       aLayerId = Graphic3d_ZLayerId_Default;
4543       ++anArgIter;
4544     }
4545     else if (aFirstArg == "top")
4546     {
4547       aLayerId = Graphic3d_ZLayerId_Top;
4548       ++anArgIter;
4549     }
4550     else if (aFirstArg == "topmost")
4551     {
4552       aLayerId = Graphic3d_ZLayerId_Topmost;
4553       ++anArgIter;
4554     }
4555     else if (aFirstArg == "overlay"
4556           || aFirstArg == "toposd")
4557     {
4558       aLayerId = Graphic3d_ZLayerId_TopOSD;
4559       ++anArgIter;
4560     }
4561     else if (aFirstArg == "underlay"
4562           || aFirstArg == "botosd")
4563     {
4564       aLayerId = Graphic3d_ZLayerId_BotOSD;
4565       ++anArgIter;
4566     }
4567     else
4568     {
4569       TColStd_SequenceOfInteger aLayers;
4570       aViewer->GetAllZLayers (aLayers);
4571       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4572       {
4573         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4574         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4575         {
4576           aLayerId = aLayeriter.Value();
4577           ++anArgIter;
4578           break;
4579         }
4580       }
4581     }
4582   }
4583
4584   for (; anArgIter < theArgNb; ++anArgIter)
4585   {
4586     // perform operation
4587     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4588     anArg.LowerCase();
4589     if (anUpdateTool.parseRedrawMode (anArg))
4590     {
4591       //
4592     }
4593     else if (anArg == "-add"
4594           || anArg == "add")
4595     {
4596       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4597       if (!aViewer->AddZLayer (aLayerId))
4598       {
4599         std::cout << "Error: can not add a new z layer!\n";
4600         return 0;
4601       }
4602
4603       theDI << aLayerId;
4604     }
4605     else if (anArg == "-del"
4606           || anArg == "-delete"
4607           || anArg == "del")
4608     {
4609       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4610       {
4611         if (++anArgIter >= theArgNb)
4612         {
4613           std::cout << "Syntax error: id of z layer to remove is missing\n";
4614           return 1;
4615         }
4616
4617         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4618       }
4619
4620       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4621        || aLayerId == Graphic3d_ZLayerId_Default
4622        || aLayerId == Graphic3d_ZLayerId_Top
4623        || aLayerId == Graphic3d_ZLayerId_Topmost
4624        || aLayerId == Graphic3d_ZLayerId_TopOSD
4625        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4626       {
4627         std::cout << "Syntax error: standard Z layer can not be removed\n";
4628         return 1;
4629       }
4630
4631       // move all object displayed in removing layer to default layer
4632       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4633            anObjIter.More(); anObjIter.Next())
4634       {
4635         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4636         if (aPrs.IsNull()
4637          || aPrs->ZLayer() != aLayerId)
4638         {
4639           continue;
4640         }
4641         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4642       }
4643
4644       if (!aViewer->RemoveZLayer (aLayerId))
4645       {
4646         std::cout << "Z layer can not be removed!\n";
4647       }
4648       else
4649       {
4650         theDI << aLayerId << " ";
4651       }
4652     }
4653     else if (anArg == "-get"
4654           || anArg == "get")
4655     {
4656       TColStd_SequenceOfInteger aLayers;
4657       aViewer->GetAllZLayers (aLayers);
4658       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4659       {
4660         theDI << aLayeriter.Value() << " ";
4661       }
4662
4663       theDI << "\n";
4664     }
4665     else if (anArg == "-name")
4666     {
4667       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4668       {
4669         std::cout << "Syntax error: id of Z layer is missing\n";
4670         return 1;
4671       }
4672
4673       if (++anArgIter >= theArgNb)
4674       {
4675         std::cout << "Syntax error: name is missing\n";
4676         return 1;
4677       }
4678
4679       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4680       aSettings.SetName (theArgVec[anArgIter]);
4681       aViewer->SetZLayerSettings (aLayerId, aSettings);
4682     }
4683     else if (anArg == "-origin")
4684     {
4685       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4686       {
4687         std::cout << "Syntax error: id of Z layer is missing\n";
4688         return 1;
4689       }
4690
4691       if (anArgIter + 2 >= theArgNb)
4692       {
4693         std::cout << "Syntax error: origin coordinates are missing\n";
4694         return 1;
4695       }
4696
4697       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4698       gp_XYZ anOrigin;
4699       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4700       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4701       anOrigin.SetZ (0.0);
4702       if (anArgIter + 3 < theArgNb)
4703       {
4704         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4705         anArgIter += 3;
4706       }
4707       else
4708       {
4709         anArgIter += 2;
4710       }
4711       aSettings.SetOrigin (anOrigin);
4712       aViewer->SetZLayerSettings (aLayerId, aSettings);
4713     }
4714     else if (anArg == "-settings"
4715           || anArg == "settings")
4716     {
4717       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4718       {
4719         if (++anArgIter >= theArgNb)
4720         {
4721           std::cout << "Syntax error: id of Z layer is missing\n";
4722           return 1;
4723         }
4724
4725         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4726       }
4727
4728       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4729       printZLayerInfo (theDI, aSettings);
4730     }
4731     else if (anArg == "-enable"
4732           || anArg == "enable"
4733           || anArg == "-disable"
4734           || anArg == "disable")
4735     {
4736       const Standard_Boolean toEnable = anArg == "-enable"
4737                                      || anArg == "enable";
4738       if (++anArgIter >= theArgNb)
4739       {
4740         std::cout << "Syntax error: option name is missing\n";
4741         return 1;
4742       }
4743
4744       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4745       aSubOp.LowerCase();
4746       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4747       {
4748         if (++anArgIter >= theArgNb)
4749         {
4750           std::cout << "Syntax error: id of Z layer is missing\n";
4751           return 1;
4752         }
4753
4754         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4755       }
4756
4757       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4758       if (aSubOp == "depthtest"
4759        || aSubOp == "test")
4760       {
4761         aSettings.SetEnableDepthTest (toEnable);
4762       }
4763       else if (aSubOp == "depthwrite"
4764             || aSubOp == "write")
4765       {
4766         aSettings.SetEnableDepthWrite (toEnable);
4767       }
4768       else if (aSubOp == "depthclear"
4769             || aSubOp == "clear")
4770       {
4771         aSettings.SetClearDepth (toEnable);
4772       }
4773       else if (aSubOp == "depthoffset"
4774             || aSubOp == "offset")
4775       {
4776         Graphic3d_PolygonOffset aParams;
4777         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4778         if (toEnable)
4779         {
4780           if (anArgIter + 2 >= theArgNb)
4781           {
4782             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4783             return 1;
4784           }
4785
4786           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4787           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4788         }
4789         aSettings.SetPolygonOffset (aParams);
4790       }
4791       else if (aSubOp == "positiveoffset"
4792             || aSubOp == "poffset")
4793       {
4794         if (toEnable)
4795         {
4796           aSettings.SetDepthOffsetPositive();
4797         }
4798         else
4799         {
4800           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4801         }
4802       }
4803       else if (aSubOp == "negativeoffset"
4804             || aSubOp == "noffset")
4805       {
4806         if (toEnable)
4807         {
4808           aSettings.SetDepthOffsetNegative();
4809         }
4810         else
4811         {
4812           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4813         }
4814       }
4815       else if (aSubOp == "textureenv")
4816       {
4817         aSettings.SetEnvironmentTexture (toEnable);
4818       }
4819
4820       aViewer->SetZLayerSettings (aLayerId, aSettings);
4821     }
4822     else
4823     {
4824       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4825       return 1;
4826     }
4827   }
4828
4829   return 0;
4830 }
4831
4832 // The interactive presentation of 2d layer item
4833 // for "vlayerline" command it provides a presentation of
4834 // line with user-defined linewidth, linetype and transparency.
4835 class V3d_LineItem : public AIS_InteractiveObject
4836 {
4837 public:
4838   // CASCADE RTTI
4839   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4840
4841   // constructor
4842   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4843                                Standard_Real X2, Standard_Real Y2,
4844                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4845                                Standard_Real theWidth    = 0.5,
4846                                Standard_Real theTransp   = 1.0);
4847
4848   private:
4849
4850   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4851                 const Handle(Prs3d_Presentation)& thePresentation,
4852                 const Standard_Integer theMode) Standard_OVERRIDE;
4853
4854   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4855                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4856   {}
4857
4858 private:
4859
4860   Standard_Real       myX1, myY1, myX2, myY2;
4861   Aspect_TypeOfLine   myType;
4862   Standard_Real       myWidth;
4863 };
4864
4865 // default constructor for line item
4866 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4867                            Standard_Real X2, Standard_Real Y2,
4868                            Aspect_TypeOfLine theType,
4869                            Standard_Real theWidth,
4870                            Standard_Real theTransp) :
4871   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4872   myType(theType), myWidth(theWidth)
4873 {
4874   SetTransparency (1-theTransp);
4875 }
4876
4877 // render line
4878 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4879                             const Handle(Prs3d_Presentation)& thePresentation,
4880                             const Standard_Integer /*theMode*/)
4881 {
4882   thePresentation->Clear();
4883   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4884   Standard_Integer aWidth, aHeight;
4885   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4886   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4887   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4888   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4889   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4890   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4891   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4892   aGroup->AddPrimitiveArray (aPrim);
4893 }
4894
4895 //=============================================================================
4896 //function : VLayerLine
4897 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4898 //         : linewidth, transparency coefficient
4899 //============================================================================
4900 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4901 {
4902   // get the active view
4903   Handle(V3d_View) aView = ViewerTest::CurrentView();
4904   if (aView.IsNull())
4905   {
4906     di << "Call vinit before!\n";
4907     return 1;
4908   }
4909   else if (argc < 5)
4910   {
4911     di << "Use: " << argv[0];
4912     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4913     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4914     di << "              0 - solid  \n";
4915     di << "              1 - dashed \n";
4916     di << "              2 - dot    \n";
4917     di << "              3 - dashdot\n";
4918     di << " transparency : { 0.0 - 1.0 } \n";
4919     di << "                  0.0 - transparent\n";
4920     di << "                  1.0 - visible    \n";
4921     return 1;
4922   }
4923
4924   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4925   // get the input params
4926   Standard_Real X1 = Draw::Atof(argv[1]);
4927   Standard_Real Y1 = Draw::Atof(argv[2]);
4928   Standard_Real X2 = Draw::Atof(argv[3]);
4929   Standard_Real Y2 = Draw::Atof(argv[4]);
4930
4931   Standard_Real aWidth = 0.5;
4932   Standard_Real aTransparency = 1.0;
4933
4934   // has width
4935   if (argc > 5)
4936     aWidth = Draw::Atof(argv[5]);
4937
4938   // select appropriate line type
4939   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
4940   if (argc > 6
4941   && !ViewerTest::ParseLineType (argv[6], aLineType))
4942   {
4943     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
4944     return 1;
4945   }
4946
4947   // has transparency
4948   if (argc > 7)
4949   {
4950     aTransparency = Draw::Atof(argv[7]);
4951     if (aTransparency < 0 || aTransparency > 1.0)
4952       aTransparency = 1.0;
4953   }
4954
4955   static Handle (V3d_LineItem) aLine;
4956   if (!aLine.IsNull())
4957   {
4958     aContext->Erase (aLine, Standard_False);
4959   }
4960   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4961                             aLineType, aWidth,
4962                             aTransparency);
4963
4964   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4965   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4966   aLine->SetToUpdate();
4967   aContext->Display (aLine, Standard_True);
4968
4969   return 0;
4970 }
4971
4972
4973 //==============================================================================
4974 //function : VGrid
4975 //purpose  :
4976 //==============================================================================
4977
4978 static int VGrid (Draw_Interpretor& /*theDI*/,
4979                   Standard_Integer  theArgNb,
4980                   const char**      theArgVec)
4981 {
4982   // get the active view
4983   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4984   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4985   if (aView.IsNull() || aViewer.IsNull())
4986   {
4987     std::cerr << "No active view. Please call vinit.\n";
4988     return 1;
4989   }
4990
4991   Aspect_GridType     aType = aViewer->GridType();
4992   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4993   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4994   Standard_Integer anIter = 1;
4995   for (; anIter < theArgNb; ++anIter)
4996   {
4997     const char* aValue = theArgVec[anIter];
4998     if (anUpdateTool.parseRedrawMode (aValue))
4999     {
5000       continue;
5001     }
5002     else if (*aValue == 'r')
5003     {
5004       aType = Aspect_GT_Rectangular;
5005     }
5006     else if (*aValue == 'c')
5007     {
5008       aType = Aspect_GT_Circular;
5009     }
5010     else if (*aValue == 'l')
5011     {
5012       aMode = Aspect_GDM_Lines;
5013     }
5014     else if (*aValue == 'p')
5015     {
5016       aMode = Aspect_GDM_Points;
5017     }
5018     else if (strcmp (aValue, "off" ) == 0)
5019     {
5020       aViewer->DeactivateGrid();
5021       return 0;
5022     }
5023     else
5024     {
5025       break;
5026     }
5027   }
5028
5029   Standard_Integer aTail = (theArgNb - anIter);
5030   if (aTail == 0)
5031   {
5032     aViewer->ActivateGrid (aType, aMode);
5033     return 0;
5034   }
5035   else if (aTail != 2 && aTail != 5)
5036   {
5037     std::cerr << "Incorrect arguments number! Usage:\n"
5038               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5039     return 1;
5040   }
5041
5042   Standard_Real anOriginX, anOriginY, aRotAngle;
5043   if (aType == Aspect_GT_Rectangular)
5044   {
5045     Standard_Real aRStepX, aRStepY;
5046     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5047
5048     anOriginX = Draw::Atof (theArgVec[anIter++]);
5049     anOriginY = Draw::Atof (theArgVec[anIter++]);
5050     if (aTail == 5)
5051     {
5052       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5053       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5054       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5055     }
5056     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5057     aViewer->ActivateGrid (aType, aMode);
5058   }
5059   else if (aType == Aspect_GT_Circular)
5060   {
5061     Standard_Real aRadiusStep;
5062     Standard_Integer aDivisionNumber;
5063     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5064
5065     anOriginX = Draw::Atof (theArgVec[anIter++]);
5066     anOriginY = Draw::Atof (theArgVec[anIter++]);
5067     if (aTail == 5)
5068     {
5069       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5070       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5071       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5072     }
5073
5074     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5075     aViewer->ActivateGrid (aType, aMode);
5076   }
5077
5078   return 0;
5079 }
5080
5081 //==============================================================================
5082 //function : VPriviledgedPlane
5083 //purpose  :
5084 //==============================================================================
5085
5086 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5087                               Standard_Integer  theArgNb,
5088                               const char**      theArgVec)
5089 {
5090   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5091   {
5092     std::cerr << "Error: wrong number of arguments! See usage:\n";
5093     theDI.PrintHelp (theArgVec[0]);
5094     return 1;
5095   }
5096
5097   // get the active viewer
5098   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5099   if (aViewer.IsNull())
5100   {
5101     std::cerr << "Error: no active viewer. Please call vinit.\n";
5102     return 1;
5103   }
5104
5105   if (theArgNb == 1)
5106   {
5107     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5108     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5109     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5110     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5111     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5112           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5113           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5114     return 0;
5115   }
5116
5117   Standard_Integer anArgIdx = 1;
5118   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5119   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5120   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5121   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5122   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5123   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5124
5125   gp_Ax3 aPriviledgedPlane;
5126   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5127   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5128   if (theArgNb > 7)
5129   {
5130     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5131     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5132     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5133     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5134     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5135   }
5136   else
5137   {
5138     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5139   }
5140
5141   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5142
5143   return 0;
5144 }
5145
5146 //==============================================================================
5147 //function : VConvert
5148 //purpose  :
5149 //==============================================================================
5150
5151 static int VConvert (Draw_Interpretor& theDI,
5152                      Standard_Integer  theArgNb,
5153                      const char**      theArgVec)
5154 {
5155   // get the active view
5156   Handle(V3d_View) aView = ViewerTest::CurrentView();
5157   if (aView.IsNull())
5158   {
5159     std::cerr << "Error: no active view. Please call vinit.\n";
5160     return 1;
5161   }
5162
5163   enum { Model, Ray, View, Window, Grid } aMode = Model;
5164
5165   // access coordinate arguments
5166   TColStd_SequenceOfReal aCoord;
5167   Standard_Integer anArgIdx = 1;
5168   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5169   {
5170     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5171     if (!anArg.IsRealValue())
5172     {
5173       break;
5174     }
5175     aCoord.Append (anArg.RealValue());
5176   }
5177
5178   // non-numeric argument too early
5179   if (aCoord.IsEmpty())
5180   {
5181     std::cerr << "Error: wrong number of arguments! See usage:\n";
5182     theDI.PrintHelp (theArgVec[0]);
5183     return 1;
5184   }
5185
5186   // collect all other arguments and options
5187   for (; anArgIdx < theArgNb; ++anArgIdx)
5188   {
5189     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5190     anArg.LowerCase();
5191     if      (anArg == "window") aMode = Window;
5192     else if (anArg == "view")   aMode = View;
5193     else if (anArg == "grid")   aMode = Grid;
5194     else if (anArg == "ray")    aMode = Ray;
5195     else
5196     {
5197       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5198       theDI.PrintHelp (theArgVec[0]);
5199       return 1;
5200     }
5201   }
5202
5203   // complete input checks
5204   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5205       (aCoord.Length() == 2 && theArgNb > 4) ||
5206       (aCoord.Length() == 3 && theArgNb > 5))
5207   {
5208     std::cerr << "Error: wrong number of arguments! See usage:\n";
5209     theDI.PrintHelp (theArgVec[0]);
5210     return 1;
5211   }
5212
5213   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5214   Standard_Integer aXYp[2] = {0, 0};
5215
5216   // convert one-dimensional coordinate
5217   if (aCoord.Length() == 1)
5218   {
5219     switch (aMode)
5220     {
5221       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5222       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5223       default:
5224         std::cerr << "Error: wrong arguments! See usage:\n";
5225         theDI.PrintHelp (theArgVec[0]);
5226         return 1;
5227     }
5228   }
5229
5230   // convert 2D coordinates from projection or view reference space
5231   if (aCoord.Length() == 2)
5232   {
5233     switch (aMode)
5234     {
5235       case Model :
5236         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5237         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5238         return 0;
5239
5240       case View :
5241         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5242         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5243         return 0;
5244
5245       case Window :
5246         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5247         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5248         return 0;
5249
5250       case Grid :
5251         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5252         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5253         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5254         return 0;
5255
5256       case Ray :
5257         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5258                                 (Standard_Integer) aCoord (2),
5259                                 aXYZ[0], aXYZ[1], aXYZ[2],
5260                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5261         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5262         return 0;
5263
5264       default:
5265         std::cerr << "Error: wrong arguments! See usage:\n";
5266         theDI.PrintHelp (theArgVec[0]);
5267         return 1;
5268     }
5269   }
5270
5271   // convert 3D coordinates from view reference space
5272   else if (aCoord.Length() == 3)
5273   {
5274     switch (aMode)
5275     {
5276       case Window :
5277         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5278         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5279         return 0;
5280
5281       case Grid :
5282         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5283         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5284         return 0;
5285
5286       default:
5287         std::cerr << "Error: wrong arguments! See usage:\n";
5288         theDI.PrintHelp (theArgVec[0]);
5289         return 1;
5290     }
5291   }
5292
5293   return 0;
5294 }
5295
5296 //==============================================================================
5297 //function : VFps
5298 //purpose  :
5299 //==============================================================================
5300
5301 static int VFps (Draw_Interpretor& theDI,
5302                  Standard_Integer  theArgNb,
5303                  const char**      theArgVec)
5304 {
5305   // get the active view
5306   Handle(V3d_View) aView = ViewerTest::CurrentView();
5307   if (aView.IsNull())
5308   {
5309     std::cerr << "No active view. Please call vinit.\n";
5310     return 1;
5311   }
5312
5313   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5314   if (aFramesNb <= 0)
5315   {
5316     std::cerr << "Incorrect arguments!\n";
5317     return 1;
5318   }
5319
5320   // the time is meaningless for first call
5321   // due to async OpenGl rendering
5322   aView->Redraw();
5323
5324   // redraw view in loop to estimate average values
5325   OSD_Timer aTimer;
5326   aTimer.Start();
5327   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5328   {
5329     aView->Redraw();
5330   }
5331   aTimer.Stop();
5332   Standard_Real aCpu;
5333   const Standard_Real aTime = aTimer.ElapsedTime();
5334   aTimer.OSD_Chronometer::Show (aCpu);
5335
5336   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5337   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5338
5339   // return statistics
5340   theDI << "FPS: " << aFpsAver << "\n"
5341         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5342
5343   // compute additional statistics in ray-tracing mode
5344   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5345
5346   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5347   {
5348     Standard_Integer aSizeX;
5349     Standard_Integer aSizeY;
5350
5351     aView->Window()->Size (aSizeX, aSizeY);
5352
5353     // 1 shadow ray and 1 secondary ray pew each bounce
5354     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5355
5356     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5357   }
5358
5359   return 0;
5360 }
5361
5362 //==============================================================================
5363 //function : VGlDebug
5364 //purpose  :
5365 //==============================================================================
5366
5367 static int VGlDebug (Draw_Interpretor& theDI,
5368                      Standard_Integer  theArgNb,
5369                      const char**      theArgVec)
5370 {
5371   Handle(OpenGl_GraphicDriver) aDriver;
5372   Handle(V3d_View) aView = ViewerTest::CurrentView();
5373   if (!aView.IsNull())
5374   {
5375     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5376   }
5377   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5378   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5379
5380   if (theArgNb < 2)
5381   {
5382     TCollection_AsciiString aDebActive, aSyncActive;
5383     if (aCaps == NULL)
5384     {
5385       aCaps = aDefCaps;
5386     }
5387     else
5388     {
5389       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5390                                                                   "GL_ARB_debug_output");
5391       aDebActive = isActive ? " (active)" : " (inactive)";
5392       if (isActive)
5393       {
5394         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5395         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5396       }
5397     }
5398
5399     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5400           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5401           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5402           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5403     return 0;
5404   }
5405
5406   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5407   {
5408     Standard_CString        anArg     = theArgVec[anArgIter];
5409     TCollection_AsciiString anArgCase (anArg);
5410     anArgCase.LowerCase();
5411     Standard_Boolean toEnableDebug = Standard_True;
5412     if (anArgCase == "-glsl"
5413      || anArgCase == "-glslwarn"
5414      || anArgCase == "-glslwarns"
5415      || anArgCase == "-glslwarnings")
5416     {
5417       Standard_Boolean toShowWarns = Standard_True;
5418       if (++anArgIter < theArgNb
5419       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5420       {
5421         --anArgIter;
5422       }
5423       aDefCaps->glslWarnings = toShowWarns;
5424       if (aCaps != NULL)
5425       {
5426         aCaps->glslWarnings = toShowWarns;
5427       }
5428     }
5429     else if (anArgCase == "-extra"
5430           || anArgCase == "-extramsg"
5431           || anArgCase == "-extramessages")
5432     {
5433       Standard_Boolean toShow = Standard_True;
5434       if (++anArgIter < theArgNb
5435       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5436       {
5437         --anArgIter;
5438       }
5439       aDefCaps->suppressExtraMsg = !toShow;
5440       if (aCaps != NULL)
5441       {
5442         aCaps->suppressExtraMsg = !toShow;
5443       }
5444     }
5445     else if (anArgCase == "-noextra"
5446           || anArgCase == "-noextramsg"
5447           || anArgCase == "-noextramessages")
5448     {
5449       Standard_Boolean toSuppress = Standard_True;
5450       if (++anArgIter < theArgNb
5451       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5452       {
5453         --anArgIter;
5454       }
5455       aDefCaps->suppressExtraMsg = toSuppress;
5456       if (aCaps != NULL)
5457       {
5458         aCaps->suppressExtraMsg = toSuppress;
5459       }
5460     }
5461     else if (anArgCase == "-sync")
5462     {
5463       Standard_Boolean toSync = Standard_True;
5464       if (++anArgIter < theArgNb
5465       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5466       {
5467         --anArgIter;
5468       }
5469       aDefCaps->contextSyncDebug = toSync;
5470       if (toSync)
5471       {
5472         aDefCaps->contextDebug = Standard_True;
5473       }
5474     }
5475     else if (anArgCase == "-debug")
5476     {
5477       if (++anArgIter < theArgNb
5478       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5479       {
5480         --anArgIter;
5481       }
5482       aDefCaps->contextDebug = toEnableDebug;
5483     }
5484     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5485           && (anArgIter + 1 == theArgNb))
5486     {
5487       // simple alias to turn on almost everything
5488       aDefCaps->contextDebug     = toEnableDebug;
5489       aDefCaps->contextSyncDebug = toEnableDebug;
5490       aDefCaps->glslWarnings     = toEnableDebug;
5491     }
5492     else
5493     {
5494       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5495       return 1;
5496     }
5497   }
5498
5499   return 0;
5500 }
5501
5502 //==============================================================================
5503 //function : VVbo
5504 //purpose  :
5505 //==============================================================================
5506
5507 static int VVbo (Draw_Interpretor& theDI,
5508                  Standard_Integer  theArgNb,
5509                  const char**      theArgVec)
5510 {
5511   const Standard_Boolean toSet    = (theArgNb > 1);
5512   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5513   if (toSet)
5514   {
5515     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5516   }
5517
5518   // get the context
5519   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5520   if (aContextAIS.IsNull())
5521   {
5522     if (!toSet)
5523     {
5524       std::cerr << "No active view!\n";
5525     }
5526     return 1;
5527   }
5528   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5529   if (!aDriver.IsNull())
5530   {
5531     if (!toSet)
5532     {
5533       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5534     }
5535     else
5536     {
5537       aDriver->ChangeOptions().vboDisable = toUseVbo;
5538     }
5539   }
5540
5541   return 0;
5542 }
5543
5544 //==============================================================================
5545 //function : VCaps
5546 //purpose  :
5547 //==============================================================================
5548
5549 static int VCaps (Draw_Interpretor& theDI,
5550                   Standard_Integer  theArgNb,
5551                   const char**      theArgVec)
5552 {
5553   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5554   Handle(OpenGl_GraphicDriver)   aDriver;
5555   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5556   if (!aContext.IsNull())
5557   {
5558     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5559     aCaps   = &aDriver->ChangeOptions();
5560   }
5561
5562   if (theArgNb < 2)
5563   {
5564     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5565     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5566     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5567     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5568     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5569     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5570     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5571     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5572     return 0;
5573   }
5574
5575   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5576   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5577   {
5578     Standard_CString        anArg     = theArgVec[anArgIter];
5579     TCollection_AsciiString anArgCase (anArg);
5580     anArgCase.LowerCase();
5581     if (anUpdateTool.parseRedrawMode (anArg))
5582     {
5583       continue;
5584     }
5585     else if (anArgCase == "-vsync"
5586           || anArgCase == "-swapinterval")
5587     {
5588       Standard_Boolean toEnable = Standard_True;
5589       if (++anArgIter < theArgNb
5590       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5591       {
5592         --anArgIter;
5593       }
5594       aCaps->swapInterval = toEnable;
5595     }
5596     else if (anArgCase == "-ffp")
5597     {
5598       Standard_Boolean toEnable = Standard_True;
5599       if (++anArgIter < theArgNb
5600       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5601       {
5602         --anArgIter;
5603       }
5604       aCaps->ffpEnable = toEnable;
5605     }
5606     else if (anArgCase == "-vbo")
5607     {
5608       Standard_Boolean toEnable = Standard_True;
5609       if (++anArgIter < theArgNb
5610       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5611       {
5612         --anArgIter;
5613       }
5614       aCaps->vboDisable = !toEnable;
5615     }
5616     else if (anArgCase == "-sprite"
5617           || anArgCase == "-sprites")
5618     {
5619       Standard_Boolean toEnable = Standard_True;
5620       if (++anArgIter < theArgNb
5621       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5622       {
5623         --anArgIter;
5624       }
5625       aCaps->pntSpritesDisable = !toEnable;
5626     }
5627     else if (anArgCase == "-softmode")
5628     {
5629       Standard_Boolean toEnable = Standard_True;
5630       if (++anArgIter < theArgNb
5631       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5632       {
5633         --anArgIter;
5634       }
5635       aCaps->contextNoAccel = toEnable;
5636     }
5637     else if (anArgCase == "-winbuffer"
5638           || anArgCase == "-windowbuffer"
5639           || anArgCase == "-usewinbuffer"
5640           || anArgCase == "-usewindowbuffer"
5641           || anArgCase == "-usesystembuffer")
5642     {
5643       Standard_Boolean toEnable = Standard_True;
5644       if (++anArgIter < theArgNb
5645       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5646       {
5647         --anArgIter;
5648       }
5649       aCaps->useSystemBuffer = toEnable;
5650     }
5651     else if (anArgCase == "-accel"
5652           || anArgCase == "-acceleration")
5653     {
5654       Standard_Boolean toEnable = Standard_True;
5655       if (++anArgIter < theArgNb
5656       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5657       {
5658         --anArgIter;
5659       }
5660       aCaps->contextNoAccel = !toEnable;
5661     }
5662     else if (anArgCase == "-compat"
5663           || anArgCase == "-compatprofile"
5664           || anArgCase == "-compatible"
5665           || anArgCase == "-compatibleprofile")
5666     {
5667       Standard_Boolean toEnable = Standard_True;
5668       if (++anArgIter < theArgNb
5669       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5670       {
5671         --anArgIter;
5672       }
5673       aCaps->contextCompatible = toEnable;
5674       if (!aCaps->contextCompatible)
5675       {
5676         aCaps->ffpEnable = Standard_False;
5677       }
5678     }
5679     else if (anArgCase == "-core"
5680           || anArgCase == "-coreprofile")
5681     {
5682       Standard_Boolean toEnable = Standard_True;
5683       if (++anArgIter < theArgNb
5684       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5685       {
5686         --anArgIter;
5687       }
5688       aCaps->contextCompatible = !toEnable;
5689       if (!aCaps->contextCompatible)
5690       {
5691         aCaps->ffpEnable = Standard_False;
5692       }
5693     }
5694     else if (anArgCase == "-stereo"
5695           || anArgCase == "-quadbuffer")
5696     {
5697       Standard_Boolean toEnable = Standard_True;
5698       if (++anArgIter < theArgNb
5699       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5700       {
5701         --anArgIter;
5702       }
5703       aCaps->contextStereo = toEnable;
5704     }
5705     else
5706     {
5707       std::cout << "Error: unknown argument '" << anArg << "'\n";
5708       return 1;
5709     }
5710   }
5711   if (aCaps != &ViewerTest_myDefaultCaps)
5712   {
5713     ViewerTest_myDefaultCaps = *aCaps;
5714   }
5715   return 0;
5716 }
5717
5718 //==============================================================================
5719 //function : VMemGpu
5720 //purpose  :
5721 //==============================================================================
5722
5723 static int VMemGpu (Draw_Interpretor& theDI,
5724                     Standard_Integer  theArgNb,
5725                     const char**      theArgVec)
5726 {
5727   // get the context
5728   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5729   if (aContextAIS.IsNull())
5730   {
5731     std::cerr << "No active view. Please call vinit.\n";
5732     return 1;
5733   }
5734
5735   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5736   if (aDriver.IsNull())
5737   {
5738     std::cerr << "Graphic driver not available.\n";
5739     return 1;
5740   }
5741
5742   Standard_Size aFreeBytes = 0;
5743   TCollection_AsciiString anInfo;
5744   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5745   {
5746     std::cerr << "Information not available.\n";
5747     return 1;
5748   }
5749
5750   if (theArgNb > 1 && *theArgVec[1] == 'f')
5751   {
5752     theDI << Standard_Real (aFreeBytes);
5753   }
5754   else
5755   {
5756     theDI << anInfo;
5757   }
5758
5759   return 0;
5760 }
5761
5762 // ==============================================================================
5763 // function : VReadPixel
5764 // purpose  :
5765 // ==============================================================================
5766 static int VReadPixel (Draw_Interpretor& theDI,
5767                        Standard_Integer  theArgNb,
5768                        const char**      theArgVec)
5769 {
5770   // get the active view
5771   Handle(V3d_View) aView = ViewerTest::CurrentView();
5772   if (aView.IsNull())
5773   {
5774     std::cerr << "No active view. Please call vinit.\n";
5775     return 1;
5776   }
5777   else if (theArgNb < 3)
5778   {
5779     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5780     return 1;
5781   }
5782
5783   Image_Format         aFormat     = Image_Format_RGBA;
5784   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
5785
5786   Standard_Integer aWidth, aHeight;
5787   aView->Window()->Size (aWidth, aHeight);
5788   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5789   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5790   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5791   {
5792     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5793     return 1;
5794   }
5795
5796   Standard_Boolean toShowName = Standard_False;
5797   Standard_Boolean toShowHls  = Standard_False;
5798   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5799   {
5800     TCollection_AsciiString aParam (theArgVec[anIter]);
5801     aParam.LowerCase();
5802     if (aParam == "rgb")
5803     {
5804       aFormat     = Image_Format_RGB;
5805       aBufferType = Graphic3d_BT_RGB;
5806     }
5807     else if (aParam == "hls")
5808     {
5809       aFormat     = Image_Format_RGB;
5810       aBufferType = Graphic3d_BT_RGB;
5811       toShowHls   = Standard_True;
5812     }
5813     else if (aParam == "rgbf")
5814     {
5815       aFormat     = Image_Format_RGBF;
5816       aBufferType = Graphic3d_BT_RGB;
5817     }
5818     else if (aParam == "rgba")
5819     {
5820       aFormat     = Image_Format_RGBA;
5821       aBufferType = Graphic3d_BT_RGBA;
5822     }
5823     else if (aParam == "rgbaf")
5824     {
5825       aFormat     = Image_Format_RGBAF;
5826       aBufferType = Graphic3d_BT_RGBA;
5827     }
5828     else if (aParam == "depth")
5829     {
5830       aFormat     = Image_Format_GrayF;
5831       aBufferType = Graphic3d_BT_Depth;
5832     }
5833     else if (aParam == "name")
5834     {
5835       toShowName = Standard_True;
5836     }
5837   }
5838
5839   Image_PixMap anImage;
5840   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5841   {
5842     std::cerr << "Image allocation failed\n";
5843     return 1;
5844   }
5845   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5846   {
5847     std::cerr << "Image dump failed\n";
5848     return 1;
5849   }
5850
5851   Standard_Real anAlpha;
5852   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5853   if (toShowName)
5854   {
5855     if (aBufferType == Graphic3d_BT_RGBA)
5856     {
5857       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5858     }
5859     else
5860     {
5861       theDI << Quantity_Color::StringName (aColor.Name());
5862     }
5863   }
5864   else
5865   {
5866     switch (aBufferType)
5867     {
5868       default:
5869       case Graphic3d_BT_RGB:
5870       {
5871         if (toShowHls)
5872         {
5873           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5874         }
5875         else
5876         {
5877           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5878         }
5879         break;
5880       }
5881       case Graphic3d_BT_RGBA:
5882       {
5883         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5884         break;
5885       }
5886       case Graphic3d_BT_Depth:
5887       {
5888         theDI << aColor.Red();
5889         break;
5890       }
5891     }
5892   }
5893
5894   return 0;
5895 }
5896
5897 //==============================================================================
5898 //function : VDiffImage
5899 //purpose  : The draw-command compares two images.
5900 //==============================================================================
5901
5902 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5903 {
5904   if (theArgNb < 6)
5905   {
5906     theDI << "Not enough arguments.\n";
5907     return 1;
5908   }
5909
5910   // image file names
5911   const char* anImgPathRef = theArgVec[1];
5912   const char* anImgPathNew = theArgVec[2];
5913
5914   // get string tolerance and check its validity
5915   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5916   if (aTolColor < 0.0)
5917     aTolColor = 0.0;
5918   if (aTolColor > 1.0)
5919     aTolColor = 1.0;
5920
5921   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5922   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5923
5924   // image file of difference
5925   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5926
5927   // compare the images
5928   Image_Diff aComparer;
5929   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5930   {
5931     return 1;
5932   }
5933
5934   aComparer.SetColorTolerance (aTolColor);
5935   aComparer.SetBorderFilterOn (isBorderFilterOn);
5936   Standard_Integer aDiffColorsNb = aComparer.Compare();
5937   theDI << aDiffColorsNb << "\n";
5938
5939   // save image of difference
5940   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5941   {
5942     aComparer.SaveDiffImage (aDiffImagePath);
5943   }
5944
5945   return 0;
5946 }
5947
5948 //=======================================================================
5949 //function : VSelect
5950 //purpose  : Emulates different types of selection by mouse:
5951 //           1) single click selection
5952 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5953 //           3) selection with polygon having corners at
5954 //           pixel positions (x1,y1),...,(xn,yn)
5955 //           4) any of these selections with shift button pressed
5956 //=======================================================================
5957 static Standard_Integer VSelect (Draw_Interpretor& di,
5958                                  Standard_Integer argc,
5959                                  const char ** argv)
5960 {
5961   if(argc < 3)
5962   {
5963     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5964     return 1;
5965   }
5966
5967   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5968   if(myAIScontext.IsNull())
5969   {
5970     di << "use 'vinit' command before " << argv[0] << "\n";
5971     return 1;
5972   }
5973
5974   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5975   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5976   TCollection_AsciiString anArg;
5977   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5978   anArg.LowerCase();
5979   if (anArg == "-allowoverlap")
5980   {
5981     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5982       : argc == 7;
5983     if (!isValidated)
5984     {
5985       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5986       return 1;
5987     }
5988
5989     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5990     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5991     aCoordsNb -= 2;
5992   }
5993
5994   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5995   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5996   if(aCoordsNb == 2)
5997   {
5998     if(isShiftSelection)
5999       aCurrentEventManager->ShiftSelect();
6000     else
6001       aCurrentEventManager->Select();
6002   }
6003   else if(aCoordsNb == 4)
6004   {
6005     if(isShiftSelection)
6006       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6007     else
6008       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6009   }
6010   else
6011   {
6012     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6013
6014     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6015       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6016
6017     if(isShiftSelection)
6018       aCurrentEventManager->ShiftSelect(aPolyline);
6019     else
6020       aCurrentEventManager->Select(aPolyline);
6021   }
6022   return 0;
6023 }
6024
6025 //=======================================================================
6026 //function : VMoveTo
6027 //purpose  : Emulates cursor movement to defined pixel position
6028 //=======================================================================
6029 static Standard_Integer VMoveTo (Draw_Interpretor& di,
6030                                 Standard_Integer argc,
6031                                 const char ** argv)
6032 {
6033   if(argc != 3)
6034   {
6035     di << "Usage : " << argv[0] << " x y\n";
6036     return 1;
6037   }
6038
6039   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6040   if(aContext.IsNull())
6041   {
6042     di << "use 'vinit' command before " << argv[0] << "\n";
6043     return 1;
6044   }
6045   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6046   return 0;
6047 }
6048
6049 namespace
6050 {
6051   //! Global map storing all animations registered in ViewerTest.
6052   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6053
6054   //! The animation calling the Draw Harness command.
6055   class ViewerTest_AnimationProc : public AIS_Animation
6056   {
6057   public:
6058
6059     //! Main constructor.
6060     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6061                               Draw_Interpretor* theDI,
6062                               const TCollection_AsciiString& theCommand)
6063     : AIS_Animation (theAnimationName),
6064       myDrawInter(theDI),
6065       myCommand  (theCommand)
6066     {
6067       //
6068     }
6069
6070   protected:
6071
6072     //! Evaluate the command.
6073     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6074     {
6075       TCollection_AsciiString aCmd = myCommand;
6076       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6077       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6078       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6079       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6080       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6081       myDrawInter->Eval (aCmd.ToCString());
6082     }
6083
6084     //! Find the keyword in the command and replace it with value.
6085     //! @return the position of the keyword to pass value
6086     void replace (TCollection_AsciiString&       theCmd,
6087                   const TCollection_AsciiString& theKey,
6088                   const TCollection_AsciiString& theVal)
6089     {
6090       TCollection_AsciiString aCmd (theCmd);
6091       aCmd.LowerCase();
6092       const Standard_Integer aPos = aCmd.Search (theKey);
6093       if (aPos == -1)
6094       {
6095         return;
6096       }
6097
6098       TCollection_AsciiString aPart1, aPart2;
6099       Standard_Integer aPart1To = aPos - 1;
6100       if (aPart1To >= 1
6101        && aPart1To <= theCmd.Length())
6102       {
6103         aPart1 = theCmd.SubString (1, aPart1To);
6104       }
6105
6106       Standard_Integer aPart2From = aPos + theKey.Length();
6107       if (aPart2From >= 1
6108        && aPart2From <= theCmd.Length())
6109       {
6110         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6111       }
6112
6113       theCmd = aPart1 + theVal + aPart2;
6114     }
6115
6116   protected:
6117
6118     Draw_Interpretor*       myDrawInter;
6119     TCollection_AsciiString myCommand;
6120
6121   };
6122
6123   //! Replace the animation with the new one.
6124   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6125                                 Handle(AIS_Animation)&       theAnimation,
6126                                 const Handle(AIS_Animation)& theAnimationNew)
6127   {
6128     theAnimationNew->CopyFrom (theAnimation);
6129     if (!theParentAnimation.IsNull())
6130     {
6131       theParentAnimation->Replace (theAnimation, theAnimationNew);
6132     }
6133     else
6134     {
6135       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6136       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6137     }
6138     theAnimation = theAnimationNew;
6139   }
6140
6141   //! Parse the point.
6142   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6143   {
6144     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6145     if (!anXYZ[0].IsRealValue()
6146      || !anXYZ[1].IsRealValue()
6147      || !anXYZ[2].IsRealValue())
6148     {
6149       return Standard_False;
6150     }
6151
6152     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6153     return Standard_True;
6154   }
6155
6156   //! Parse the quaternion.
6157   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6158   {
6159     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6160     if (!anXYZW[0].IsRealValue()
6161      || !anXYZW[1].IsRealValue()
6162      || !anXYZW[2].IsRealValue()
6163      || !anXYZW[3].IsRealValue())
6164     {
6165       return Standard_False;
6166     }
6167
6168     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6169     return Standard_True;
6170   }
6171
6172 }
6173
6174 //=================================================================================================
6175 //function : VViewParams
6176 //purpose  : Gets or sets AIS View characteristics
6177 //=================================================================================================
6178 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6179 {
6180   Handle(V3d_View) aView = ViewerTest::CurrentView();
6181   if (aView.IsNull())
6182   {
6183     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6184     return 1;
6185   }
6186
6187   Standard_Boolean toSetProj     = Standard_False;
6188   Standard_Boolean toSetUp       = Standard_False;
6189   Standard_Boolean toSetAt       = Standard_False;
6190   Standard_Boolean toSetEye      = Standard_False;
6191   Standard_Boolean toSetScale    = Standard_False;
6192   Standard_Boolean toSetSize     = Standard_False;
6193   Standard_Boolean toSetCenter2d = Standard_False;
6194   Standard_Real    aViewScale = aView->Scale();
6195   Standard_Real    aViewSize  = 1.0;
6196   Graphic3d_Vec2i  aCenter2d;
6197   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6198   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6199   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6200   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6201   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6202   if (theArgsNb == 1)
6203   {
6204     // print all of the available view parameters
6205     char aText[4096];
6206     Sprintf (aText,
6207              "Scale: %g\n"
6208              "Proj:  %12g %12g %12g\n"
6209              "Up:    %12g %12g %12g\n"
6210              "At:    %12g %12g %12g\n"
6211              "Eye:   %12g %12g %12g\n",
6212               aViewScale,
6213               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6214               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6215               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6216               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6217     theDi << aText;
6218     return 0;
6219   }
6220
6221   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6222   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6223   {
6224     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6225     anArg.LowerCase();
6226     if (anUpdateTool.parseRedrawMode (anArg))
6227     {
6228       continue;
6229     }
6230     else if (anArg == "-cmd"
6231           || anArg == "-command"
6232           || anArg == "-args")
6233     {
6234       char aText[4096];
6235       Sprintf (aText,
6236                "-scale %g "
6237                "-proj %g %g %g "
6238                "-up %g %g %g "
6239                "-at %g %g %g\n",
6240                 aViewScale,
6241                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6242                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6243                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6244       theDi << aText;
6245     }
6246     else if (anArg == "-scale"
6247           || anArg == "-size")
6248     {
6249       if (anArgIter + 1 < theArgsNb
6250        && *theArgVec[anArgIter + 1] != '-')
6251       {
6252         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6253         if (aValueArg.IsRealValue())
6254         {
6255           ++anArgIter;
6256           if (anArg == "-scale")
6257           {
6258             toSetScale = Standard_True;
6259             aViewScale = aValueArg.RealValue();
6260           }
6261           else if (anArg == "-size")
6262           {
6263             toSetSize = Standard_True;
6264             aViewSize = aValueArg.RealValue();
6265           }
6266           continue;
6267         }
6268       }
6269       if (anArg == "-scale")
6270       {
6271         theDi << "Scale: " << aView->Scale() << "\n";
6272       }
6273       else if (anArg == "-size")
6274       {
6275         Graphic3d_Vec2d aSizeXY;
6276         aView->Size (aSizeXY.x(), aSizeXY.y());
6277         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6278       }
6279     }
6280     else if (anArg == "-eye"
6281           || anArg == "-at"
6282           || anArg == "-up"
6283           || anArg == "-proj")
6284     {
6285       if (anArgIter + 3 < theArgsNb)
6286       {
6287         gp_XYZ anXYZ;
6288         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6289         {
6290           anArgIter += 3;
6291           if (anArg == "-eye")
6292           {
6293             toSetEye = Standard_True;
6294             aViewEye = anXYZ;
6295           }
6296           else if (anArg == "-at")
6297           {
6298             toSetAt = Standard_True;
6299             aViewAt = anXYZ;
6300           }
6301           else if (anArg == "-up")
6302           {
6303             toSetUp = Standard_True;
6304             aViewUp = anXYZ;
6305           }
6306           else if (anArg == "-proj")
6307           {
6308             toSetProj = Standard_True;
6309             aViewProj = anXYZ;
6310           }
6311           continue;
6312         }
6313       }
6314
6315       if (anArg == "-eye")
6316       {
6317         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6318       }
6319       else if (anArg == "-at")
6320       {
6321         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6322       }
6323       else if (anArg == "-up")
6324       {
6325         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6326       }
6327       else if (anArg == "-proj")
6328       {
6329         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6330       }
6331     }
6332     else if (anArg == "-center")
6333     {
6334       if (anArgIter + 2 < theArgsNb)
6335       {
6336         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6337         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6338         if (anX.IsIntegerValue()
6339          && anY.IsIntegerValue())
6340         {
6341           toSetCenter2d = Standard_True;
6342           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6343         }
6344       }
6345     }
6346     else
6347     {
6348       std::cout << "Syntax error at '" << anArg << "'\n";
6349       return 1;
6350     }
6351   }
6352
6353   // change view parameters in proper order
6354   if (toSetScale)
6355   {
6356     aView->SetScale (aViewScale);
6357   }
6358   if (toSetSize)
6359   {
6360     aView->SetSize (aViewSize);
6361   }
6362   if (toSetEye)
6363   {
6364     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6365   }
6366   if (toSetAt)
6367   {
6368     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6369   }
6370   if (toSetProj)
6371   {
6372     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6373   }
6374   if (toSetUp)
6375   {
6376     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6377   }
6378   if (toSetCenter2d)
6379   {
6380     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6381   }
6382
6383   return 0;
6384 }
6385
6386 //==============================================================================
6387 //function : VAnimation
6388 //purpose  :
6389 //==============================================================================
6390 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6391                                     Standard_Integer  theArgNb,
6392                                     const char**      theArgVec)
6393 {
6394   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6395   if (theArgNb < 2)
6396   {
6397     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6398          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6399     {
6400       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6401     }
6402     return 0;
6403   }
6404   if (aCtx.IsNull())
6405   {
6406     std::cout << "Error: no active view\n";
6407     return 1;
6408   }
6409
6410   Standard_Integer anArgIter = 1;
6411   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6412   if (aNameArg.IsEmpty())
6413   {
6414     std::cout << "Syntax error: animation name is not defined.\n";
6415     return 1;
6416   }
6417
6418   TCollection_AsciiString aNameArgLower = aNameArg;
6419   aNameArgLower.LowerCase();
6420   if (aNameArgLower == "-reset"
6421    || aNameArgLower == "-clear")
6422   {
6423     ViewerTest_AnimationTimelineMap.Clear();
6424     return 0;
6425   }
6426   else if (aNameArg.Value (1) == '-')
6427   {
6428     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6429     return 1;
6430   }
6431
6432   const char* aNameSplitter = "/";
6433   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6434   if (aSplitPos == -1)
6435   {
6436     aNameSplitter = ".";
6437     aSplitPos = aNameArg.Search (aNameSplitter);
6438   }
6439
6440   // find existing or create a new animation by specified name within syntax "parent.child".
6441   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6442   for (; !aNameArg.IsEmpty();)
6443   {
6444     TCollection_AsciiString aNameParent;
6445     if (aSplitPos != -1)
6446     {
6447       if (aSplitPos == aNameArg.Length())
6448       {
6449         std::cout << "Syntax error: animation name is not defined.\n";
6450         return 1;
6451       }
6452
6453       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6454       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6455
6456       aSplitPos = aNameArg.Search (aNameSplitter);
6457     }
6458     else
6459     {
6460       aNameParent = aNameArg;
6461       aNameArg.Clear();
6462     }
6463
6464     if (anAnimation.IsNull())
6465     {
6466       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6467       {
6468         anAnimation = new AIS_Animation (aNameParent);
6469         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6470       }
6471       aRootAnimation = anAnimation;
6472     }
6473     else
6474     {
6475       aParentAnimation = anAnimation;
6476       anAnimation = aParentAnimation->Find (aNameParent);
6477       if (anAnimation.IsNull())
6478       {
6479         anAnimation = new AIS_Animation (aNameParent);
6480         aParentAnimation->Add (anAnimation);
6481       }
6482     }
6483   }
6484
6485   if (anArgIter >= theArgNb)
6486   {
6487     // just print the list of children
6488     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
6489     {
6490       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
6491     }
6492     return 0;
6493   }
6494
6495   // animation parameters
6496   Standard_Boolean toPlay = Standard_False;
6497   Standard_Real aPlaySpeed     = 1.0;
6498   Standard_Real aPlayStartTime = anAnimation->StartPts();
6499   Standard_Real aPlayDuration  = anAnimation->Duration();
6500   Standard_Integer aFpsNum     = 0;
6501   Standard_Integer aFpsDen     = 1;
6502   Standard_Boolean isFreeCamera = Standard_False;
6503   Standard_Boolean isLockLoop   = Standard_False;
6504   Handle(V3d_View) aView = ViewerTest::CurrentView();
6505   for (; anArgIter < theArgNb; ++anArgIter)
6506   {
6507     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6508     anArg.LowerCase();
6509     // general options
6510     if (anArg == "-reset"
6511      || anArg == "-clear")
6512     {
6513       anAnimation->Clear();
6514     }
6515     else if (anArg == "-remove"
6516           || anArg == "-del"
6517           || anArg == "-delete")
6518     {
6519       if (!aParentAnimation.IsNull())
6520       {
6521         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
6522       }
6523       else
6524       {
6525         aParentAnimation->Remove (anAnimation);
6526       }
6527     }
6528     // playback options
6529     else if (anArg == "-play")
6530     {
6531       toPlay = Standard_True;
6532       if (++anArgIter < theArgNb)
6533       {
6534         if (*theArgVec[anArgIter] == '-')
6535         {
6536           --anArgIter;
6537           continue;
6538         }
6539         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
6540
6541         if (++anArgIter < theArgNb)
6542         {
6543           if (*theArgVec[anArgIter] == '-')
6544           {
6545             --anArgIter;
6546             continue;
6547           }
6548           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6549         }
6550       }
6551     }
6552     else if (anArg == "-resume")
6553     {
6554       toPlay = Standard_True;
6555       aPlayStartTime = anAnimation->ElapsedTime();
6556       if (++anArgIter < theArgNb)
6557       {
6558         if (*theArgVec[anArgIter] == '-')
6559         {
6560           --anArgIter;
6561           continue;
6562         }
6563
6564         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6565       }
6566     }
6567     else if (anArg == "-playspeed"
6568           || anArg == "-speed")
6569     {
6570       if (++anArgIter >= theArgNb)
6571       {
6572         std::cout << "Syntax error at " << anArg << ".\n";
6573         return 1;
6574       }
6575       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
6576     }
6577     else if (anArg == "-lock"
6578           || anArg == "-lockloop"
6579           || anArg == "-playlockloop")
6580     {
6581       isLockLoop = Standard_True;
6582     }
6583     else if (anArg == "-freecamera"
6584           || anArg == "-playfreecamera"
6585           || anArg == "-freelook")
6586     {
6587       isFreeCamera = Standard_True;
6588     }
6589     else if (anArg == "-fps")
6590     {
6591       if (++anArgIter >= theArgNb)
6592       {
6593         std::cout << "Syntax error at " << anArg << ".\n";
6594         return 1;
6595       }
6596
6597       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
6598       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
6599       if (aSplitIndex == 0)
6600       {
6601         aFpsNum = aFpsArg.IntegerValue();
6602       }
6603       else
6604       {
6605         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
6606         aFpsArg.Split (aFpsArg.Length() - 1);
6607         const TCollection_AsciiString aNumStr = aFpsArg;
6608         aFpsNum = aNumStr.IntegerValue();
6609         aFpsDen = aDenStr.IntegerValue();
6610         if (aFpsDen < 1)
6611         {
6612           std::cout << "Syntax error at " << anArg << ".\n";
6613           return 1;
6614         }
6615       }
6616     }
6617     // animation definition options
6618     else if (anArg == "-start"
6619           || anArg == "-starttime"
6620           || anArg == "-startpts")
6621     {
6622       if (++anArgIter >= theArgNb)
6623       {
6624         std::cout << "Syntax error at " << anArg << ".\n";
6625         return 1;
6626       }
6627
6628       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
6629       aRootAnimation->UpdateTotalDuration();
6630     }
6631     else if (anArg == "-end"
6632           || anArg == "-endtime"
6633           || anArg == "-endpts")
6634     {
6635       if (++anArgIter >= theArgNb)
6636       {
6637         std::cout << "Syntax error at " << anArg << ".\n";
6638         return 1;
6639       }
6640
6641       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
6642       aRootAnimation->UpdateTotalDuration();
6643     }
6644     else if (anArg == "-dur"
6645           || anArg == "-duration")
6646     {
6647       if (++anArgIter >= theArgNb)
6648       {
6649         std::cout << "Syntax error at " << anArg << ".\n";
6650         return 1;
6651       }
6652
6653       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
6654       aRootAnimation->UpdateTotalDuration();
6655     }
6656     else if (anArg == "-command"
6657           || anArg == "-cmd"
6658           || anArg == "-invoke"
6659           || anArg == "-eval"
6660           || anArg == "-proc")
6661     {
6662       if (++anArgIter >= theArgNb)
6663       {
6664         std::cout << "Syntax error at " << anArg << ".\n";
6665         return 1;
6666       }
6667
6668       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
6669       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
6670     }
6671     else if (anArg == "-objecttrsf"
6672           || anArg == "-objectransformation"
6673           || anArg == "-objtransformation"
6674           || anArg == "-objtrsf"
6675           || anArg == "-object"
6676           || anArg == "-obj")
6677     {
6678       if (++anArgIter >= theArgNb)
6679       {
6680         std::cout << "Syntax error at " << anArg << ".\n";
6681         return 1;
6682       }
6683
6684       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
6685       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
6686       if (!aMapOfAIS.IsBound2 (anObjName))
6687       {
6688         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
6689         return 1;
6690       }
6691
6692       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
6693       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
6694       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
6695       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
6696       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
6697       Standard_Boolean isTrsfSet = Standard_False;
6698       Standard_Integer aTrsfArgIter = anArgIter + 1;
6699       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
6700       {
6701         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
6702         aTrsfArg.LowerCase();
6703         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
6704         if (aTrsfArg.StartsWith ("-rotation")
6705          || aTrsfArg.StartsWith ("-rot"))
6706         {
6707           isTrsfSet = Standard_True;
6708           if (aTrsfArgIter + 4 >= theArgNb
6709           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
6710           {
6711             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6712             return 1;
6713           }
6714           aTrsfArgIter += 4;
6715         }
6716         else if (aTrsfArg.StartsWith ("-location")
6717               || aTrsfArg.StartsWith ("-loc"))
6718         {
6719           isTrsfSet = Standard_True;
6720           if (aTrsfArgIter + 3 >= theArgNb
6721           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
6722           {
6723             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6724             return 1;
6725           }
6726           aTrsfArgIter += 3;
6727         }
6728         else if (aTrsfArg.StartsWith ("-scale"))
6729         {
6730           isTrsfSet = Standard_True;
6731           if (++aTrsfArgIter >= theArgNb)
6732           {
6733             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6734             return 1;
6735           }
6736
6737           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
6738           if (!aScaleStr.IsRealValue())
6739           {
6740             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6741             return 1;
6742           }
6743           aScales[anIndex] = aScaleStr.RealValue();
6744         }
6745         else
6746         {
6747           anArgIter = aTrsfArgIter - 1;
6748           break;
6749         }
6750       }
6751       if (!isTrsfSet)
6752       {
6753         std::cout << "Syntax error at " << anArg << ".\n";
6754         return 1;
6755       }
6756       else if (aTrsfArgIter >= theArgNb)
6757       {
6758         anArgIter = theArgNb;
6759       }
6760
6761       aTrsfs[0].SetRotation        (aRotQuats[0]);
6762       aTrsfs[1].SetRotation        (aRotQuats[1]);
6763       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
6764       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
6765       aTrsfs[0].SetScaleFactor     (aScales[0]);
6766       aTrsfs[1].SetScaleFactor     (aScales[1]);
6767
6768       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
6769       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
6770     }
6771     else if (anArg == "-viewtrsf"
6772           || anArg == "-view")
6773     {
6774       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
6775       if (aCamAnimation.IsNull())
6776       {
6777         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
6778         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
6779       }
6780
6781       Handle(Graphic3d_Camera) aCams[2] =
6782       {
6783         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
6784         new Graphic3d_Camera (aCamAnimation->View()->Camera())
6785       };
6786
6787       Standard_Boolean isTrsfSet = Standard_False;
6788       Standard_Integer aViewArgIter = anArgIter + 1;
6789       for (; aViewArgIter < theArgNb; ++aViewArgIter)
6790       {
6791         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
6792         aViewArg.LowerCase();
6793         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
6794         if (aViewArg.StartsWith ("-scale"))
6795         {
6796           isTrsfSet = Standard_True;
6797           if (++aViewArgIter >= theArgNb)
6798           {
6799             std::cout << "Syntax error at " << anArg << ".\n";
6800             return 1;
6801           }
6802
6803           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
6804           if (!aScaleStr.IsRealValue())
6805           {
6806             std::cout << "Syntax error at " << aViewArg << ".\n";
6807             return 1;
6808           }
6809           Standard_Real aScale = aScaleStr.RealValue();
6810           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
6811           aCams[anIndex]->SetScale (aScale);
6812         }
6813         else if (aViewArg.StartsWith ("-eye")
6814               || aViewArg.StartsWith ("-center")
6815               || aViewArg.StartsWith ("-at")
6816               || aViewArg.StartsWith ("-up"))
6817         {
6818           isTrsfSet = Standard_True;
6819           gp_XYZ anXYZ;
6820           if (aViewArgIter + 3 >= theArgNb
6821           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
6822           {
6823             std::cout << "Syntax error at " << aViewArg << ".\n";
6824             return 1;
6825           }
6826           aViewArgIter += 3;
6827
6828           if (aViewArg.StartsWith ("-eye"))
6829           {
6830             aCams[anIndex]->SetEye (anXYZ);
6831           }
6832           else if (aViewArg.StartsWith ("-center")
6833                 || aViewArg.StartsWith ("-at"))
6834           {
6835             aCams[anIndex]->SetCenter (anXYZ);
6836           }
6837           else if (aViewArg.StartsWith ("-up"))
6838           {
6839             aCams[anIndex]->SetUp (anXYZ);
6840           }
6841         }
6842         else
6843         {
6844           anArgIter = aViewArgIter - 1;
6845           break;
6846         }
6847       }
6848       if (!isTrsfSet)
6849       {
6850         std::cout << "Syntax error at " << anArg << ".\n";
6851         return 1;
6852       }
6853       else if (aViewArgIter >= theArgNb)
6854       {
6855         anArgIter = theArgNb;
6856       }
6857
6858       aCamAnimation->SetCameraStart(aCams[0]);
6859       aCamAnimation->SetCameraEnd  (aCams[1]);
6860     }
6861     else
6862     {
6863       std::cout << "Syntax error at " << anArg << ".\n";
6864       return 1;
6865     }
6866   }
6867
6868   if (!toPlay)
6869   {
6870     return 0;
6871   }
6872
6873   // Start animation timeline and process frame updating.
6874   TheIsAnimating = Standard_True;
6875   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
6876   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
6877   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
6878   if (isFreeCamera)
6879   {
6880     aView->Camera()->Copy (aCameraBack);
6881   }
6882
6883   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
6884   if (aFpsNum <= 0)
6885   {
6886     while (!anAnimation->IsStopped())
6887     {
6888       aCameraBack->Copy (aView->Camera());
6889       const Standard_Real aPts = anAnimation->UpdateTimer();
6890       if (isFreeCamera)
6891       {
6892         aView->Camera()->Copy (aCameraBack);
6893       }
6894
6895       if (aPts >= anUpperPts)
6896       {
6897         anAnimation->Pause();
6898         break;
6899       }
6900
6901       if (aView->IsInvalidated())
6902       {
6903         aView->Redraw();
6904       }
6905       else
6906       {
6907         aView->RedrawImmediate();
6908       }
6909
6910       if (!isLockLoop)
6911       {
6912         // handle user events
6913         theDI.Eval ("after 1 set waiter 1");
6914         theDI.Eval ("vwait waiter");
6915       }
6916       if (!TheIsAnimating)
6917       {
6918         anAnimation->Pause();
6919         theDI << aPts;
6920         break;
6921       }
6922     }
6923
6924     if (aView->IsInvalidated())
6925     {
6926       aView->Redraw();
6927     }
6928     else
6929     {
6930       aView->RedrawImmediate();
6931     }
6932   }
6933   else
6934   {
6935     OSD_Timer aPerfTimer;
6936     aPerfTimer.Start();
6937
6938     // Manage frame-rated animation here
6939     Standard_Real aPts = aPlayStartTime;
6940     int64_t aNbFrames = 0;
6941     for (; aPts <= anUpperPts;)
6942     {
6943       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
6944       aPts = aPlayStartTime + aRecPts;
6945       ++aNbFrames;
6946       if (!anAnimation->Update (aPts))
6947       {
6948         break;
6949       }
6950
6951       aView->Redraw();
6952     }
6953
6954     aPerfTimer.Stop();
6955     anAnimation->Stop();
6956     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
6957     theDI << "Average FPS: " << aRecFps << "\n"
6958           << "Nb. Frames: "  << Standard_Real(aNbFrames);
6959
6960     aView->Redraw();
6961   }
6962
6963   aView->SetImmediateUpdate (wasImmediateUpdate);
6964   TheIsAnimating = Standard_False;
6965   return 0;
6966 }
6967
6968
6969 //=======================================================================
6970 //function : VChangeSelected
6971 //purpose  : Adds the shape to selection or remove one from it
6972 //=======================================================================
6973 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6974                                 Standard_Integer argc,
6975                                 const char ** argv)
6976 {
6977   if(argc != 2)
6978   {
6979     di<<"Usage : " << argv[0] << " shape \n";
6980     return 1;
6981   }
6982   //get AIS_Shape:
6983   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6984   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6985   TCollection_AsciiString aName(argv[1]);
6986   Handle(AIS_InteractiveObject) anAISObject;
6987
6988   if(!aMap.IsBound2(aName))
6989   {
6990     di<<"Use 'vdisplay' before";
6991     return 1;
6992   }
6993   else
6994   {
6995     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6996     if(anAISObject.IsNull()){
6997       di<<"No interactive object \n";
6998       return 1;
6999     }
7000
7001     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
7002   }
7003   return 0;
7004 }
7005
7006 //=======================================================================
7007 //function : VNbSelected
7008 //purpose  : Returns number of selected objects
7009 //=======================================================================
7010 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7011                                 Standard_Integer argc,
7012                                 const char ** argv)
7013 {
7014   if(argc != 1)
7015   {
7016     di << "Usage : " << argv[0] << "\n";
7017     return 1;
7018   }
7019   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7020   if(aContext.IsNull())
7021   {
7022     di << "use 'vinit' command before " << argv[0] << "\n";
7023     return 1;
7024   }
7025   di << aContext->NbSelected() << "\n";
7026   return 0;
7027 }
7028
7029 //=======================================================================
7030 //function : VPurgeDisplay
7031 //purpose  : Switches altialiasing on or off
7032 //=======================================================================
7033 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7034                                 Standard_Integer argc,
7035                                 const char ** argv)
7036 {
7037   if (argc > 1)
7038   {
7039     di << "Usage : " << argv[0] << "\n";
7040     return 1;
7041   }
7042   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7043   if (aContext.IsNull())
7044   {
7045     di << "use 'vinit' command before " << argv[0] << "\n";
7046     return 1;
7047   }
7048
7049   di << aContext->PurgeDisplay() << "\n";
7050   return 0;
7051 }
7052
7053 //=======================================================================
7054 //function : VSetViewSize
7055 //purpose  :
7056 //=======================================================================
7057 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7058                                 Standard_Integer argc,
7059                                 const char ** argv)
7060 {
7061   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7062   if(aContext.IsNull())
7063   {
7064     di << "use 'vinit' command before " << argv[0] << "\n";
7065     return 1;
7066   }
7067   if(argc != 2)
7068   {
7069     di<<"Usage : " << argv[0] << " Size\n";
7070     return 1;
7071   }
7072   Standard_Real aSize = Draw::Atof (argv[1]);
7073   if (aSize <= 0.)
7074   {
7075     di<<"Bad Size value  : " << aSize << "\n";
7076     return 1;
7077   }
7078
7079   Handle(V3d_View) aView = ViewerTest::CurrentView();
7080   aView->SetSize(aSize);
7081   return 0;
7082 }
7083
7084 //=======================================================================
7085 //function : VMoveView
7086 //purpose  :
7087 //=======================================================================
7088 static Standard_Integer VMoveView (Draw_Interpretor& di,
7089                                 Standard_Integer argc,
7090                                 const char ** argv)
7091 {
7092   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7093   if(aContext.IsNull())
7094   {
7095     di << "use 'vinit' command before " << argv[0] << "\n";
7096     return 1;
7097   }
7098   if(argc < 4 || argc > 5)
7099   {
7100     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7101     return 1;
7102   }
7103   Standard_Real Dx = Draw::Atof (argv[1]);
7104   Standard_Real Dy = Draw::Atof (argv[2]);
7105   Standard_Real Dz = Draw::Atof (argv[3]);
7106   Standard_Boolean aStart = Standard_True;
7107   if (argc == 5)
7108   {
7109       aStart = (Draw::Atoi (argv[4]) > 0);
7110   }
7111
7112   Handle(V3d_View) aView = ViewerTest::CurrentView();
7113   aView->Move(Dx,Dy,Dz,aStart);
7114   return 0;
7115 }
7116
7117 //=======================================================================
7118 //function : VTranslateView
7119 //purpose  :
7120 //=======================================================================
7121 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7122                                 Standard_Integer argc,
7123                                 const char ** argv)
7124 {
7125   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7126   if(aContext.IsNull())
7127   {
7128     di << "use 'vinit' command before " << argv[0] << "\n";
7129     return 1;
7130   }
7131   if(argc < 4 || argc > 5)
7132   {
7133     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7134     return 1;
7135   }
7136   Standard_Real Dx = Draw::Atof (argv[1]);
7137   Standard_Real Dy = Draw::Atof (argv[2]);
7138   Standard_Real Dz = Draw::Atof (argv[3]);
7139   Standard_Boolean aStart = Standard_True;
7140   if (argc == 5)
7141   {
7142       aStart = (Draw::Atoi (argv[4]) > 0);
7143   }
7144
7145   Handle(V3d_View) aView = ViewerTest::CurrentView();
7146   aView->Translate(Dx,Dy,Dz,aStart);
7147   return 0;
7148 }
7149
7150 //=======================================================================
7151 //function : VTurnView
7152 //purpose  :
7153 //=======================================================================
7154 static Standard_Integer VTurnView (Draw_Interpretor& di,
7155                                 Standard_Integer argc,
7156                                 const char ** argv)
7157 {
7158   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7159   if(aContext.IsNull()) {
7160     di << "use 'vinit' command before " << argv[0] << "\n";
7161     return 1;
7162   }
7163   if(argc < 4 || argc > 5){
7164     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7165     return 1;
7166   }
7167   Standard_Real Ax = Draw::Atof (argv[1]);
7168   Standard_Real Ay = Draw::Atof (argv[2]);
7169   Standard_Real Az = Draw::Atof (argv[3]);
7170   Standard_Boolean aStart = Standard_True;
7171   if (argc == 5)
7172   {
7173       aStart = (Draw::Atoi (argv[4]) > 0);
7174   }
7175
7176   Handle(V3d_View) aView = ViewerTest::CurrentView();
7177   aView->Turn(Ax,Ay,Az,aStart);
7178   return 0;
7179 }
7180
7181 //==============================================================================
7182 //function : VTextureEnv
7183 //purpose  : ENables or disables environment mapping
7184 //==============================================================================
7185 class OCC_TextureEnv : public Graphic3d_TextureEnv
7186 {
7187 public:
7188   OCC_TextureEnv(const Standard_CString FileName);
7189   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7190   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7191                             const Standard_Boolean theModulateFlag,
7192                             const Graphic3d_TypeOfTextureFilter theFilter,
7193                             const Standard_ShortReal theXScale,
7194                             const Standard_ShortReal theYScale,
7195                             const Standard_ShortReal theXShift,
7196                             const Standard_ShortReal theYShift,
7197                             const Standard_ShortReal theAngle);
7198   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7199 };
7200 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7201
7202 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7203   : Graphic3d_TextureEnv(theFileName)
7204 {
7205 }
7206
7207 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7208   : Graphic3d_TextureEnv(theTexId)
7209 {
7210 }
7211
7212 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7213                                           const Standard_Boolean theModulateFlag,
7214                                           const Graphic3d_TypeOfTextureFilter theFilter,
7215                                           const Standard_ShortReal theXScale,
7216                                           const Standard_ShortReal theYScale,
7217                                           const Standard_ShortReal theXShift,
7218                                           const Standard_ShortReal theYShift,
7219                                           const Standard_ShortReal theAngle)
7220 {
7221   myParams->SetRepeat     (theRepeatFlag);
7222   myParams->SetModulate   (theModulateFlag);
7223   myParams->SetFilter     (theFilter);
7224   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7225   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7226   myParams->SetRotation   (theAngle);
7227 }
7228
7229 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7230 {
7231   // get the active view
7232   Handle(V3d_View) aView = ViewerTest::CurrentView();
7233   if (aView.IsNull())
7234   {
7235     std::cerr << "No active view. Please call vinit.\n";
7236     return 1;
7237   }
7238
7239   // Checking the input arguments
7240   Standard_Boolean anEnableFlag = Standard_False;
7241   Standard_Boolean isOk         = theArgNb >= 2;
7242   if (isOk)
7243   {
7244     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7245     anEnableFlag = anEnableOpt.IsEqual("on");
7246     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7247   }
7248   if (anEnableFlag)
7249   {
7250     isOk = (theArgNb == 3 || theArgNb == 11);
7251     if (isOk)
7252     {
7253       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7254       isOk = (!aTextureOpt.IsIntegerValue() ||
7255              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7256
7257       if (isOk && theArgNb == 11)
7258       {
7259         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7260                                 aModulateOpt(theArgVec[4]),
7261                                 aFilterOpt  (theArgVec[5]),
7262                                 aSScaleOpt  (theArgVec[6]),
7263                                 aTScaleOpt  (theArgVec[7]),
7264                                 aSTransOpt  (theArgVec[8]),
7265                                 aTTransOpt  (theArgVec[9]),
7266                                 anAngleOpt  (theArgVec[10]);
7267         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7268                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7269                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7270                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7271                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7272                 anAngleOpt.IsRealValue());
7273       }
7274     }
7275   }
7276
7277   if (!isOk)
7278   {
7279     std::cerr << "Usage :" << std::endl;
7280     std::cerr << theArgVec[0] << " off" << std::endl;
7281     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;
7282     return 1;
7283   }
7284
7285   if (anEnableFlag)
7286   {
7287     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7288     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7289                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7290                                      new OCC_TextureEnv(theArgVec[2]);
7291
7292     if (theArgNb == 11)
7293     {
7294       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7295       aTexEnv->SetTextureParameters(
7296         aRepeatOpt.  IsEqual("repeat"),
7297         aModulateOpt.IsEqual("modulate"),
7298         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7299                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7300                                                                            Graphic3d_TOTF_TRILINEAR,
7301         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7302         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7303         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7304         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7305         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7306         );
7307     }
7308     aView->SetTextureEnv(aTexEnv);
7309   }
7310   else // Disabling environment mapping
7311   {
7312     Handle(Graphic3d_TextureEnv) aTexture;
7313     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7314   }
7315
7316   aView->Redraw();
7317   return 0;
7318 }
7319
7320 namespace
7321 {
7322   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7323
7324   //! Remove registered clipping plane from all views and objects.
7325   static void removePlane (MapOfPlanes& theRegPlanes,
7326                            const TCollection_AsciiString& theName)
7327   {
7328     Handle(Graphic3d_ClipPlane) aClipPlane;
7329     if (!theRegPlanes.Find (theName, aClipPlane))
7330     {
7331       std::cout << "Warning: no such plane.\n";
7332       return;
7333     }
7334
7335     theRegPlanes.UnBind (theName);
7336     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7337          anIObjIt.More(); anIObjIt.Next())
7338     {
7339       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7340       aPrs->RemoveClipPlane (aClipPlane);
7341     }
7342
7343     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
7344          aViewIt.More(); aViewIt.Next())
7345     {
7346       const Handle(V3d_View)& aView = aViewIt.Key2();
7347       aView->RemoveClipPlane(aClipPlane);
7348     }
7349
7350     ViewerTest::RedrawAllViews();
7351   }
7352 }
7353
7354 //===============================================================================================
7355 //function : VClipPlane
7356 //purpose  :
7357 //===============================================================================================
7358 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7359 {
7360   // use short-cut for created clip planes map of created (or "registered by name") clip planes
7361   static MapOfPlanes aRegPlanes;
7362
7363   if (theArgsNb < 2)
7364   {
7365     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
7366     {
7367       theDi << aPlaneIter.Key() << " ";
7368     }
7369     return 0;
7370   }
7371
7372   TCollection_AsciiString aCommand (theArgVec[1]);
7373   aCommand.LowerCase();
7374   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
7375   if (anActiveView.IsNull())
7376   {
7377     std::cout << "Error: no active view.\n";
7378     return 1;
7379   }
7380
7381   // print maximum number of planes for current viewer
7382   if (aCommand == "-maxplanes"
7383    || aCommand == "maxplanes")
7384   {
7385     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
7386           << " plane slots provided by driver.\n";
7387     return 0;
7388   }
7389
7390   // create / delete plane instance
7391   if (aCommand == "-create"
7392    || aCommand == "create"
7393    || aCommand == "-delete"
7394    || aCommand == "delete"
7395    || aCommand == "-clone"
7396    || aCommand == "clone")
7397   {
7398     if (theArgsNb < 3)
7399     {
7400       std::cout << "Syntax error: plane name is required.\n";
7401       return 1;
7402     }
7403
7404     Standard_Boolean toCreate = aCommand == "-create"
7405                              || aCommand == "create";
7406     Standard_Boolean toClone  = aCommand == "-clone"
7407                              || aCommand == "clone";
7408     Standard_Boolean toDelete = aCommand == "-delete"
7409                              || aCommand == "delete";
7410     TCollection_AsciiString aPlane (theArgVec[2]);
7411
7412     if (toCreate)
7413     {
7414       if (aRegPlanes.IsBound (aPlane))
7415       {
7416         std::cout << "Warning: existing plane has been overridden.\n";
7417         toDelete = true;
7418       }
7419       else
7420       {
7421         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7422         return 0;
7423       }
7424     }
7425     else if (toClone) // toClone
7426     {
7427       if (!aRegPlanes.IsBound (aPlane))
7428       {
7429         std::cout << "Error: no such plane.\n";
7430         return 1;
7431       }
7432       else if (theArgsNb < 4)
7433       {
7434         std::cout << "Syntax error: enter name for new plane.\n";
7435         return 1;
7436       }
7437
7438       TCollection_AsciiString aClone (theArgVec[3]);
7439       if (aRegPlanes.IsBound (aClone))
7440       {
7441         std::cout << "Error: plane name is in use.\n";
7442         return 1;
7443       }
7444
7445       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
7446
7447       aRegPlanes.Bind (aClone, aClipPlane->Clone());
7448       return 0;
7449     }
7450
7451     if (toDelete)
7452     {
7453       if (aPlane == "ALL"
7454        || aPlane == "all"
7455        || aPlane == "*")
7456       {
7457         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
7458         {
7459           aPlane = aPlaneIter.Key();
7460           removePlane (aRegPlanes, aPlane);
7461           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
7462         }
7463       }
7464       else
7465       {
7466         removePlane (aRegPlanes, aPlane);
7467       }
7468     }
7469
7470     if (toCreate)
7471     {
7472       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7473     }
7474     return 0;
7475   }
7476
7477   // set / unset plane command
7478   if (aCommand == "set"
7479    || aCommand == "unset")
7480   {
7481     if (theArgsNb < 5)
7482     {
7483       std::cout << "Syntax error: need more arguments.\n";
7484       return 1;
7485     }
7486
7487     // redirect to new syntax
7488     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
7489     anArgVec.SetValue (1, theArgVec[0]);
7490     anArgVec.SetValue (2, theArgVec[2]);
7491     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
7492     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
7493     {
7494       anArgVec.SetValue (anIt, theArgVec[anIt]);
7495     }
7496
7497     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
7498   }
7499
7500   // change plane command
7501   TCollection_AsciiString aPlaneName;
7502   Handle(Graphic3d_ClipPlane) aClipPlane;
7503   Standard_Integer anArgIter = 0;
7504   if (aCommand == "-change"
7505    || aCommand == "change")
7506   {
7507     // old syntax support
7508     if (theArgsNb < 3)
7509     {
7510       std::cout << "Syntax error: need more arguments.\n";
7511       return 1;
7512     }
7513
7514     anArgIter  = 3;
7515     aPlaneName = theArgVec[2];
7516     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
7517     {
7518       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
7519       return 1;
7520     }
7521   }
7522   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
7523   {
7524     anArgIter  = 2;
7525     aPlaneName = theArgVec[1];
7526   }
7527   else
7528   {
7529     anArgIter  = 2;
7530     aPlaneName = theArgVec[1];
7531     aClipPlane = new Graphic3d_ClipPlane();
7532     aRegPlanes.Bind (aPlaneName, aClipPlane);
7533     theDi << "Created new plane " << aPlaneName << ".\n";
7534   }
7535
7536   if (theArgsNb - anArgIter < 1)
7537   {
7538     std::cout << "Syntax error: need more arguments.\n";
7539     return 1;
7540   }
7541
7542   for (; anArgIter < theArgsNb; ++anArgIter)
7543   {
7544     const char**     aChangeArgs   = theArgVec + anArgIter;
7545     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
7546     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
7547     aChangeArg.LowerCase();
7548
7549     Standard_Boolean toEnable = Standard_True;
7550     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
7551     {
7552       aClipPlane->SetOn (toEnable);
7553     }
7554     else if (aChangeArg == "-equation"
7555           || aChangeArg == "equation")
7556     {
7557       if (aNbChangeArgs < 5)
7558       {
7559         std::cout << "Syntax error: need more arguments.\n";
7560         return 1;
7561       }
7562
7563       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
7564       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
7565       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
7566       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
7567       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
7568       anArgIter += 4;
7569     }
7570     else if (aChangeArg == "-capping"
7571           || aChangeArg == "capping")
7572     {
7573       if (aNbChangeArgs < 2)
7574       {
7575         std::cout << "Syntax error: need more arguments.\n";
7576         return 1;
7577       }
7578
7579       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7580       {
7581         aClipPlane->SetCapping (toEnable);
7582         anArgIter += 1;
7583       }
7584       else
7585       {
7586         // just skip otherwise (old syntax)
7587       }
7588     }
7589     else if (aChangeArg == "-useobjectmaterial"
7590           || aChangeArg == "-useobjectmat"
7591           || aChangeArg == "-useobjmat"
7592           || aChangeArg == "-useobjmaterial")
7593     {
7594       if (aNbChangeArgs < 2)
7595       {
7596         std::cout << "Syntax error: need more arguments.\n";
7597         return 1;
7598       }
7599
7600       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7601       {
7602         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
7603         anArgIter += 1;
7604       }
7605     }
7606     else if (aChangeArg == "-useobjecttexture"
7607           || aChangeArg == "-useobjecttex"
7608           || aChangeArg == "-useobjtexture"
7609           || aChangeArg == "-useobjtex")
7610     {
7611       if (aNbChangeArgs < 2)
7612       {
7613         std::cout << "Syntax error: need more arguments.\n";
7614         return 1;
7615       }
7616
7617       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7618       {
7619         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
7620         anArgIter += 1;
7621       }
7622     }
7623     else if (aChangeArg == "-useobjectshader"
7624           || aChangeArg == "-useobjshader")
7625     {
7626       if (aNbChangeArgs < 2)
7627       {
7628         std::cout << "Syntax error: need more arguments.\n";
7629         return 1;
7630       }
7631
7632       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7633       {
7634         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
7635         anArgIter += 1;
7636       }
7637     }
7638     else if (aChangeArg == "-color"
7639           || aChangeArg == "color")
7640     {
7641       Quantity_Color aColor;
7642       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
7643                                                            aChangeArgs + 1,
7644                                                            aColor);
7645       if (aNbParsed == 0)
7646       {
7647         std::cout << "Syntax error: need more arguments.\n";
7648         return 1;
7649       }
7650
7651       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
7652       aMat.SetAmbientColor (aColor);
7653       aMat.SetDiffuseColor (aColor);
7654       aClipPlane->SetCappingMaterial (aMat);
7655       anArgIter += aNbParsed;
7656     }
7657     else if (aChangeArg == "-texname"
7658           || aChangeArg == "texname")
7659     {
7660       if (aNbChangeArgs < 2)
7661       {
7662         std::cout << "Syntax error: need more arguments.\n";
7663         return 1;
7664       }
7665
7666       TCollection_AsciiString aTextureName (aChangeArgs[1]);
7667       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
7668       if (!aTexture->IsDone())
7669       {
7670         aClipPlane->SetCappingTexture (NULL);
7671       }
7672       else
7673       {
7674         aTexture->EnableModulate();
7675         aTexture->EnableRepeat();
7676         aClipPlane->SetCappingTexture (aTexture);
7677       }
7678       anArgIter += 1;
7679     }
7680     else if (aChangeArg == "-texscale"
7681           || aChangeArg == "texscale")
7682     {
7683       if (aClipPlane->CappingTexture().IsNull())
7684       {
7685         std::cout << "Error: no texture is set.\n";
7686         return 1;
7687       }
7688
7689       if (aNbChangeArgs < 3)
7690       {
7691         std::cout << "Syntax error: need more arguments.\n";
7692         return 1;
7693       }
7694
7695       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7696       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7697       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
7698       anArgIter += 2;
7699     }
7700     else if (aChangeArg == "-texorigin"
7701           || aChangeArg == "texorigin") // texture origin
7702     {
7703       if (aClipPlane->CappingTexture().IsNull())
7704       {
7705         std::cout << "Error: no texture is set.\n";
7706         return 1;
7707       }
7708
7709       if (aNbChangeArgs < 3)
7710       {
7711         std::cout << "Syntax error: need more arguments.\n";
7712         return 1;
7713       }
7714
7715       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7716       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7717
7718       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
7719       anArgIter += 2;
7720     }
7721     else if (aChangeArg == "-texrotate"
7722           || aChangeArg == "texrotate") // texture rotation
7723     {
7724       if (aClipPlane->CappingTexture().IsNull())
7725       {
7726         std::cout << "Error: no texture is set.\n";
7727         return 1;
7728       }
7729
7730       if (aNbChangeArgs < 2)
7731       {
7732         std::cout << "Syntax error: need more arguments.\n";
7733         return 1;
7734       }
7735
7736       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7737       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
7738       anArgIter += 1;
7739     }
7740     else if (aChangeArg == "-hatch"
7741           || aChangeArg == "hatch")
7742     {
7743       if (aNbChangeArgs < 2)
7744       {
7745         std::cout << "Syntax error: need more arguments.\n";
7746         return 1;
7747       }
7748
7749       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
7750       aHatchStr.LowerCase();
7751       if (aHatchStr == "on")
7752       {
7753         aClipPlane->SetCappingHatchOn();
7754       }
7755       else if (aHatchStr == "off")
7756       {
7757         aClipPlane->SetCappingHatchOff();
7758       }
7759       else
7760       {
7761         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
7762       }
7763       anArgIter += 1;
7764     }
7765     else if (aChangeArg == "-delete"
7766           || aChangeArg == "delete")
7767     {
7768       removePlane (aRegPlanes, aPlaneName);
7769       return 0;
7770     }
7771     else if (aChangeArg == "-set"
7772           || aChangeArg == "-unset")
7773     {
7774       // set / unset plane command
7775       Standard_Boolean toSet = aChangeArg == "-set";
7776       Standard_Integer anIt = 1;
7777       for (; anIt < aNbChangeArgs; ++anIt)
7778       {
7779         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
7780         if (anEntityName.IsEmpty()
7781          || anEntityName.Value (1) == '-')
7782         {
7783           break;
7784         }
7785         else if (ViewerTest_myViews.IsBound1 (anEntityName))
7786         {
7787           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
7788           if (toSet)
7789           {
7790             aView->AddClipPlane (aClipPlane);
7791           }
7792           else
7793           {
7794             aView->RemoveClipPlane (aClipPlane);
7795           }
7796           continue;
7797         }
7798         else if (GetMapOfAIS().IsBound2 (anEntityName))
7799         {
7800           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
7801           if (toSet)
7802           {
7803             aIObj->AddClipPlane (aClipPlane);
7804           }
7805           else
7806           {
7807             aIObj->RemoveClipPlane (aClipPlane);
7808           }
7809         }
7810         else
7811         {
7812           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
7813           return 1;
7814         }
7815       }
7816
7817       if (anIt == 1)
7818       {
7819         // apply to active view
7820         if (toSet)
7821         {
7822           anActiveView->AddClipPlane (aClipPlane);
7823         }
7824         else
7825         {
7826           anActiveView->RemoveClipPlane (aClipPlane);
7827         }
7828       }
7829       else
7830       {
7831         anArgIter = anArgIter + anIt - 1;
7832       }
7833     }
7834     else
7835     {
7836       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
7837       return 1;
7838     }
7839   }
7840
7841   ViewerTest::RedrawAllViews();
7842   return 0;
7843 }
7844
7845 //===============================================================================================
7846 //function : VZRange
7847 //purpose  :
7848 //===============================================================================================
7849 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7850 {
7851   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7852
7853   if (aCurrentView.IsNull())
7854   {
7855     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7856     return 1;
7857   }
7858
7859   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
7860
7861   if (theArgsNb < 2)
7862   {
7863     theDi << "ZNear: " << aCamera->ZNear() << "\n";
7864     theDi << "ZFar: " << aCamera->ZFar() << "\n";
7865     return 0;
7866   }
7867
7868   if (theArgsNb == 3)
7869   {
7870     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
7871     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
7872
7873     if (aNewZNear >= aNewZFar)
7874     {
7875       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
7876       return 1;
7877     }
7878
7879     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
7880     {
7881       std::cout << theArgVec[0] << ": invalid arguments: ";
7882       std::cout << "znear, zfar should be positive for perspective camera.\n";
7883       return 1;
7884     }
7885
7886     aCamera->SetZRange (aNewZNear, aNewZFar);
7887   }
7888   else
7889   {
7890     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7891     return 1;
7892   }
7893
7894   aCurrentView->Redraw();
7895
7896   return 0;
7897 }
7898
7899 //===============================================================================================
7900 //function : VAutoZFit
7901 //purpose  :
7902 //===============================================================================================
7903 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7904 {
7905   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7906
7907   if (aCurrentView.IsNull())
7908   {
7909     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7910     return 1;
7911   }
7912
7913   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
7914
7915   if (theArgsNb > 3)
7916   {
7917     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7918     return 1;
7919   }
7920
7921   if (theArgsNb < 2)
7922   {
7923     theDi << "Auto z-fit mode: \n"
7924           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
7925           << "Scale: " << aScale << "\n";
7926     return 0;
7927   }
7928
7929   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
7930
7931   if (theArgsNb >= 3)
7932   {
7933     aScale = Draw::Atoi (theArgVec[2]);
7934   }
7935
7936   aCurrentView->SetAutoZFitMode (isOn, aScale);
7937   aCurrentView->AutoZFit();
7938   aCurrentView->Redraw();
7939
7940   return 0;
7941 }
7942
7943 //! Auxiliary function to print projection type
7944 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
7945 {
7946   switch (theProjType)
7947   {
7948     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
7949     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
7950     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
7951     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
7952     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
7953   }
7954   return "UNKNOWN";
7955 }
7956
7957 //===============================================================================================
7958 //function : VCamera
7959 //purpose  :
7960 //===============================================================================================
7961 static int VCamera (Draw_Interpretor& theDI,
7962                     Standard_Integer  theArgsNb,
7963                     const char**      theArgVec)
7964 {
7965   Handle(V3d_View) aView = ViewerTest::CurrentView();
7966   if (aView.IsNull())
7967   {
7968     std::cout << "Error: no active view.\n";
7969     return 1;
7970   }
7971
7972   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7973   if (theArgsNb < 2)
7974   {
7975     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7976     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7977     theDI << "Distance:   " << aCamera->Distance() << "\n";
7978     theDI << "IOD:        " << aCamera->IOD() << "\n";
7979     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7980     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7981     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7982     return 0;
7983   }
7984
7985   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7986   {
7987     Standard_CString        anArg = theArgVec[anArgIter];
7988     TCollection_AsciiString anArgCase (anArg);
7989     anArgCase.LowerCase();
7990     if (anArgCase == "-proj"
7991      || anArgCase == "-projection"
7992      || anArgCase == "-projtype"
7993      || anArgCase == "-projectiontype")
7994     {
7995       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7996     }
7997     else if (anArgCase == "-ortho"
7998           || anArgCase == "-orthographic")
7999     {
8000       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8001     }
8002     else if (anArgCase == "-persp"
8003           || anArgCase == "-perspective"
8004           || anArgCase == "-perspmono"
8005           || anArgCase == "-perspectivemono"
8006           || anArgCase == "-mono")
8007     {
8008       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8009     }
8010     else if (anArgCase == "-stereo"
8011           || anArgCase == "-stereoscopic"
8012           || anArgCase == "-perspstereo"
8013           || anArgCase == "-perspectivestereo")
8014     {
8015       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8016     }
8017     else if (anArgCase == "-left"
8018           || anArgCase == "-lefteye"
8019           || anArgCase == "-monoleft"
8020           || anArgCase == "-monolefteye"
8021           || anArgCase == "-perpsleft"
8022           || anArgCase == "-perpslefteye")
8023     {
8024       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8025     }
8026     else if (anArgCase == "-right"
8027           || anArgCase == "-righteye"
8028           || anArgCase == "-monoright"
8029           || anArgCase == "-monorighteye"
8030           || anArgCase == "-perpsright")
8031     {
8032       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8033     }
8034     else if (anArgCase == "-dist"
8035           || anArgCase == "-distance")
8036     {
8037       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8038       if (anArgValue != NULL
8039       && *anArgValue != '-')
8040       {
8041         ++anArgIter;
8042         aCamera->SetDistance (Draw::Atof (anArgValue));
8043         continue;
8044       }
8045       theDI << aCamera->Distance() << " ";
8046     }
8047     else if (anArgCase == "-iod")
8048     {
8049       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8050       if (anArgValue != NULL
8051       && *anArgValue != '-')
8052       {
8053         ++anArgIter;
8054         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8055         continue;
8056       }
8057       theDI << aCamera->IOD() << " ";
8058     }
8059     else if (anArgCase == "-iodtype")
8060     {
8061       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8062       TCollection_AsciiString anValueCase (anArgValue);
8063       anValueCase.LowerCase();
8064       if (anValueCase == "abs"
8065        || anValueCase == "absolute")
8066       {
8067         ++anArgIter;
8068         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8069         continue;
8070       }
8071       else if (anValueCase == "rel"
8072             || anValueCase == "relative")
8073       {
8074         ++anArgIter;
8075         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8076         continue;
8077       }
8078       else if (*anArgValue != '-')
8079       {
8080         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8081         return 1;
8082       }
8083       switch (aCamera->GetIODType())
8084       {
8085         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8086         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8087       }
8088     }
8089     else if (anArgCase == "-zfocus")
8090     {
8091       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8092       if (anArgValue != NULL
8093       && *anArgValue != '-')
8094       {
8095         ++anArgIter;
8096         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8097         continue;
8098       }
8099       theDI << aCamera->ZFocus() << " ";
8100     }
8101     else if (anArgCase == "-zfocustype")
8102     {
8103       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8104       TCollection_AsciiString anValueCase (anArgValue);
8105       anValueCase.LowerCase();
8106       if (anValueCase == "abs"
8107        || anValueCase == "absolute")
8108       {
8109         ++anArgIter;
8110         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8111         continue;
8112       }
8113       else if (anValueCase == "rel"
8114             || anValueCase == "relative")
8115       {
8116         ++anArgIter;
8117         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8118         continue;
8119       }
8120       else if (*anArgValue != '-')
8121       {
8122         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8123         return 1;
8124       }
8125       switch (aCamera->ZFocusType())
8126       {
8127         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8128         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8129       }
8130     }
8131     else if (anArgCase == "-fov"
8132           || anArgCase == "-fovy")
8133     {
8134       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8135       if (anArgValue != NULL
8136       && *anArgValue != '-')
8137       {
8138         ++anArgIter;
8139         aCamera->SetFOVy (Draw::Atof (anArgValue));
8140         continue;
8141       }
8142       theDI << aCamera->FOVy() << " ";
8143     }
8144     else
8145     {
8146       std::cout << "Error: unknown argument '" << anArg << "'\n";
8147       return 1;
8148     }
8149   }
8150
8151   aView->AutoZFit();
8152   aView->Redraw();
8153
8154   return 0;
8155 }
8156
8157 //! Parse stereo output mode
8158 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8159                                          Graphic3d_StereoMode& theMode)
8160 {
8161   TCollection_AsciiString aFlag (theArg);
8162   aFlag.LowerCase();
8163   if (aFlag == "quadbuffer")
8164   {
8165     theMode = Graphic3d_StereoMode_QuadBuffer;
8166   }
8167   else if (aFlag == "anaglyph")
8168   {
8169     theMode = Graphic3d_StereoMode_Anaglyph;
8170   }
8171   else if (aFlag == "row"
8172         || aFlag == "rowinterlaced")
8173   {
8174     theMode = Graphic3d_StereoMode_RowInterlaced;
8175   }
8176   else if (aFlag == "col"
8177         || aFlag == "colinterlaced"
8178         || aFlag == "columninterlaced")
8179   {
8180     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8181   }
8182   else if (aFlag == "chess"
8183         || aFlag == "chessboard")
8184   {
8185     theMode = Graphic3d_StereoMode_ChessBoard;
8186   }
8187   else if (aFlag == "sbs"
8188         || aFlag == "sidebyside")
8189   {
8190     theMode = Graphic3d_StereoMode_SideBySide;
8191   }
8192   else if (aFlag == "ou"
8193         || aFlag == "overunder")
8194   {
8195     theMode = Graphic3d_StereoMode_OverUnder;
8196   }
8197   else if (aFlag == "pageflip"
8198         || aFlag == "softpageflip")
8199   {
8200     theMode = Graphic3d_StereoMode_SoftPageFlip;
8201   }
8202   else
8203   {
8204     return Standard_False;
8205   }
8206   return Standard_True;
8207 }
8208
8209 //! Parse anaglyph filter
8210 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8211                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8212 {
8213   TCollection_AsciiString aFlag (theArg);
8214   aFlag.LowerCase();
8215   if (aFlag == "redcyansimple")
8216   {
8217     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8218   }
8219   else if (aFlag == "redcyan"
8220         || aFlag == "redcyanoptimized")
8221   {
8222     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8223   }
8224   else if (aFlag == "yellowbluesimple")
8225   {
8226     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8227   }
8228   else if (aFlag == "yellowblue"
8229         || aFlag == "yellowblueoptimized")
8230   {
8231     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8232   }
8233   else if (aFlag == "greenmagenta"
8234         || aFlag == "greenmagentasimple")
8235   {
8236     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8237   }
8238   else
8239   {
8240     return Standard_False;
8241   }
8242   return Standard_True;
8243 }
8244
8245 //==============================================================================
8246 //function : VStereo
8247 //purpose  :
8248 //==============================================================================
8249
8250 static int VStereo (Draw_Interpretor& theDI,
8251                     Standard_Integer  theArgNb,
8252                     const char**      theArgVec)
8253 {
8254   Handle(V3d_View) aView = ViewerTest::CurrentView();
8255   if (theArgNb < 2)
8256   {
8257     if (aView.IsNull())
8258     {
8259       std::cout << "Error: no active viewer!\n";
8260       return 0;
8261     }
8262
8263     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8264     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8265     if (isActive)
8266     {
8267       TCollection_AsciiString aMode;
8268       switch (aView->RenderingParams().StereoMode)
8269       {
8270         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8271         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8272         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8273         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8274         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8275         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8276         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8277         case Graphic3d_StereoMode_Anaglyph  :
8278           aMode = "anaglyph";
8279           switch (aView->RenderingParams().AnaglyphFilter)
8280           {
8281             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8282             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8283             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8284             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8285             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8286             default: break;
8287           }
8288         default: break;
8289       }
8290       theDI << "Mode " << aMode << "\n";
8291     }
8292     return 0;
8293   }
8294
8295   Handle(Graphic3d_Camera) aCamera;
8296   Graphic3d_RenderingParams*   aParams   = NULL;
8297   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8298   if (!aView.IsNull())
8299   {
8300     aParams   = &aView->ChangeRenderingParams();
8301     aMode     = aParams->StereoMode;
8302     aCamera   = aView->Camera();
8303   }
8304
8305   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8306   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8307   {
8308     Standard_CString        anArg = theArgVec[anArgIter];
8309     TCollection_AsciiString aFlag (anArg);
8310     aFlag.LowerCase();
8311     if (anUpdateTool.parseRedrawMode (aFlag))
8312     {
8313       continue;
8314     }
8315     else if (aFlag == "0"
8316           || aFlag == "off")
8317     {
8318       if (++anArgIter < theArgNb)
8319       {
8320         std::cout << "Error: wrong number of arguments!\n";
8321         return 1;
8322       }
8323
8324       if (!aCamera.IsNull()
8325        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8326       {
8327         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8328       }
8329       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8330       return 0;
8331     }
8332     else if (aFlag == "1"
8333           || aFlag == "on")
8334     {
8335       if (++anArgIter < theArgNb)
8336       {
8337         std::cout << "Error: wrong number of arguments!\n";
8338         return 1;
8339       }
8340
8341       if (!aCamera.IsNull())
8342       {
8343         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8344       }
8345       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8346       return 0;
8347     }
8348     else if (aFlag == "-reverse"
8349           || aFlag == "-reversed"
8350           || aFlag == "-swap")
8351     {
8352       Standard_Boolean toEnable = Standard_True;
8353       if (++anArgIter < theArgNb
8354       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8355       {
8356         --anArgIter;
8357       }
8358       aParams->ToReverseStereo = toEnable;
8359     }
8360     else if (aFlag == "-noreverse"
8361           || aFlag == "-noswap")
8362     {
8363       Standard_Boolean toDisable = Standard_True;
8364       if (++anArgIter < theArgNb
8365       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
8366       {
8367         --anArgIter;
8368       }
8369       aParams->ToReverseStereo = !toDisable;
8370     }
8371     else if (aFlag == "-mode"
8372           || aFlag == "-stereomode")
8373     {
8374       if (++anArgIter >= theArgNb
8375       || !parseStereoMode (theArgVec[anArgIter], aMode))
8376       {
8377         std::cout << "Error: syntax error at '" << anArg << "'\n";
8378         return 1;
8379       }
8380
8381       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8382       {
8383         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8384       }
8385     }
8386     else if (aFlag == "-anaglyph"
8387           || aFlag == "-anaglyphfilter")
8388     {
8389       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8390       if (++anArgIter >= theArgNb
8391       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
8392       {
8393         std::cout << "Error: syntax error at '" << anArg << "'\n";
8394         return 1;
8395       }
8396
8397       aMode = Graphic3d_StereoMode_Anaglyph;
8398       aParams->AnaglyphFilter = aFilter;
8399     }
8400     else if (parseStereoMode (anArg, aMode)) // short syntax
8401     {
8402       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8403       {
8404         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8405       }
8406     }
8407     else
8408     {
8409       std::cout << "Error: syntax error at '" << anArg << "'\n";
8410       return 1;
8411     }
8412   }
8413
8414   if (!aView.IsNull())
8415   {
8416     aParams->StereoMode = aMode;
8417     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8418   }
8419   return 0;
8420 }
8421
8422 //===============================================================================================
8423 //function : VDefaults
8424 //purpose  :
8425 //===============================================================================================
8426 static int VDefaults (Draw_Interpretor& theDi,
8427                       Standard_Integer  theArgsNb,
8428                       const char**      theArgVec)
8429 {
8430   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
8431   if (aCtx.IsNull())
8432   {
8433     std::cerr << "No active viewer!\n";
8434     return 1;
8435   }
8436
8437   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
8438   if (theArgsNb < 2)
8439   {
8440     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
8441     {
8442       theDi << "DeflType:           relative\n"
8443             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
8444     }
8445     else
8446     {
8447       theDi << "DeflType:           absolute\n"
8448             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
8449     }
8450     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
8451     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
8452     return 0;
8453   }
8454
8455   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8456   {
8457     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8458     anArg.UpperCase();
8459     if (anArg == "-ABSDEFL"
8460      || anArg == "-ABSOLUTEDEFLECTION"
8461      || anArg == "-DEFL"
8462      || anArg == "-DEFLECTION")
8463     {
8464       if (++anArgIter >= theArgsNb)
8465       {
8466         std::cout << "Error: wrong syntax at " << anArg << "\n";
8467         return 1;
8468       }
8469       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
8470       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
8471     }
8472     else if (anArg == "-RELDEFL"
8473           || anArg == "-RELATIVEDEFLECTION"
8474           || anArg == "-DEVCOEFF"
8475           || anArg == "-DEVIATIONCOEFF"
8476           || anArg == "-DEVIATIONCOEFFICIENT")
8477     {
8478       if (++anArgIter >= theArgsNb)
8479       {
8480         std::cout << "Error: wrong syntax at " << anArg << "\n";
8481         return 1;
8482       }
8483       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
8484       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
8485     }
8486     else if (anArg == "-ANGDEFL"
8487           || anArg == "-ANGULARDEFL"
8488           || anArg == "-ANGULARDEFLECTION")
8489     {
8490       if (++anArgIter >= theArgsNb)
8491       {
8492         std::cout << "Error: wrong syntax at " << anArg << "\n";
8493         return 1;
8494       }
8495       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
8496       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
8497     }
8498     else if (anArg == "-AUTOTR"
8499           || anArg == "-AUTOTRIANG"
8500           || anArg == "-AUTOTRIANGULATION")
8501     {
8502       if (++anArgIter >= theArgsNb)
8503       {
8504         std::cout << "Error: wrong syntax at " << anArg << "\n";
8505         return 1;
8506       }
8507       TCollection_AsciiString aValue (theArgVec[anArgIter]);
8508       aValue.LowerCase();
8509       if (aValue == "on"
8510        || aValue == "1")
8511       {
8512         aDefParams->SetAutoTriangulation (Standard_True);
8513       }
8514       else if (aValue == "off"
8515             || aValue == "0")
8516       {
8517         aDefParams->SetAutoTriangulation (Standard_False);
8518       }
8519     }
8520     else
8521     {
8522       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
8523     }
8524   }
8525
8526   return 0;
8527 }
8528
8529 //! Auxiliary method
8530 inline void addLight (const Handle(V3d_Light)& theLightNew,
8531                       const Standard_Boolean   theIsGlobal)
8532 {
8533   if (theLightNew.IsNull())
8534   {
8535     return;
8536   }
8537
8538   if (theIsGlobal)
8539   {
8540     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
8541   }
8542   else
8543   {
8544     ViewerTest::CurrentView()->SetLightOn (theLightNew);
8545   }
8546 }
8547
8548 //! Auxiliary method
8549 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
8550 {
8551   TCollection_AsciiString anArgNextCase (theArgNext);
8552   anArgNextCase.UpperCase();
8553   if (anArgNextCase.Length() > 5
8554    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
8555   {
8556     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
8557   }
8558   else
8559   {
8560     return theArgNext.IntegerValue();
8561   }
8562 }
8563
8564 //===============================================================================================
8565 //function : VLight
8566 //purpose  :
8567 //===============================================================================================
8568 static int VLight (Draw_Interpretor& theDi,
8569                    Standard_Integer  theArgsNb,
8570                    const char**      theArgVec)
8571 {
8572   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8573   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8574   if (aView.IsNull()
8575    || aViewer.IsNull())
8576   {
8577     std::cerr << "No active viewer!\n";
8578     return 1;
8579   }
8580
8581   Standard_Real anXYZ[3]   = {};
8582   Standard_Real anAtten[2] = {};
8583   if (theArgsNb < 2)
8584   {
8585     // print lights info
8586     Standard_Integer aLightId = 0;
8587     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
8588     {
8589       Handle(V3d_Light) aLight = aLightIter.Value();
8590       const Quantity_Color aColor = aLight->Color();
8591       theDi << "Light" << aLightId << "\n";
8592       switch (aLight->Type())
8593       {
8594         case V3d_AMBIENT:
8595         {
8596           theDi << "  Type:       Ambient\n";
8597           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8598           break;
8599         }
8600         case V3d_DIRECTIONAL:
8601         {
8602           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
8603           theDi << "  Type:       Directional\n";
8604           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8605           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8606           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8607           if (!aLightDir.IsNull())
8608           {
8609             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8610             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8611             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8612             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8613           }
8614           break;
8615         }
8616         case V3d_POSITIONAL:
8617         {
8618           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
8619           theDi << "  Type:       Positional\n";
8620           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8621           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8622           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8623           if (!aLightPos.IsNull())
8624           {
8625             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8626             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8627             aLightPos->Attenuation (anAtten[0], anAtten[1]);
8628             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8629           }
8630           break;
8631         }
8632         case V3d_SPOT:
8633         {
8634           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
8635           theDi << "  Type:       Spot\n";
8636           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8637           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8638           if (!aLightSpot.IsNull())
8639           {
8640             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8641             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8642             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8643             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8644             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8645             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8646             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
8647             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
8648           }
8649           break;
8650         }
8651         default:
8652         {
8653           theDi << "  Type:       UNKNOWN\n";
8654           break;
8655         }
8656       }
8657       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
8658     }
8659   }
8660
8661   Handle(V3d_Light) aLightNew;
8662   Handle(V3d_Light) aLightOld;
8663   Standard_Boolean  isGlobal = Standard_True;
8664   Standard_Boolean  toCreate = Standard_False;
8665   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8666   {
8667     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
8668     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
8669     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
8670     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
8671     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
8672
8673     TCollection_AsciiString aName, aValue;
8674     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
8675     TCollection_AsciiString anArgCase (anArg);
8676     anArgCase.UpperCase();
8677     if (anArgCase.IsEqual ("NEW")
8678      || anArgCase.IsEqual ("ADD")
8679      || anArgCase.IsEqual ("CREATE"))
8680     {
8681       toCreate = Standard_True;
8682     }
8683     else if (anArgCase.IsEqual ("GLOB")
8684           || anArgCase.IsEqual ("GLOBAL"))
8685     {
8686       isGlobal = Standard_True;
8687     }
8688     else if (anArgCase.IsEqual ("LOC")
8689           || anArgCase.IsEqual ("LOCAL"))
8690     {
8691       isGlobal = Standard_False;
8692     }
8693     else if (anArgCase.IsEqual ("DEF")
8694           || anArgCase.IsEqual ("DEFAULTS"))
8695     {
8696       toCreate = Standard_False;
8697       aViewer->SetDefaultLights();
8698     }
8699     else if (anArgCase.IsEqual ("CLR")
8700           || anArgCase.IsEqual ("CLEAR"))
8701     {
8702       toCreate = Standard_False;
8703       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
8704       {
8705         Handle(V3d_Light) aLight = aLightIter.Value();
8706         aViewer->DelLight (aLight);
8707         aLightIter = aView->ActiveLightIterator();
8708       }
8709     }
8710     else if (anArgCase.IsEqual ("AMB")
8711           || anArgCase.IsEqual ("AMBIENT")
8712           || anArgCase.IsEqual ("AMBLIGHT"))
8713     {
8714       addLight (aLightNew, isGlobal);
8715       if (!toCreate)
8716       {
8717         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8718         return 1;
8719       }
8720       toCreate  = Standard_False;
8721       aLightNew = new V3d_AmbientLight (aViewer);
8722     }
8723     else if (anArgCase.IsEqual ("DIRECTIONAL")
8724           || anArgCase.IsEqual ("DIRLIGHT"))
8725     {
8726       addLight (aLightNew, isGlobal);
8727       if (!toCreate)
8728       {
8729         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8730         return 1;
8731       }
8732       toCreate  = Standard_False;
8733       aLightNew = new V3d_DirectionalLight (aViewer);
8734     }
8735     else if (anArgCase.IsEqual ("SPOT")
8736           || anArgCase.IsEqual ("SPOTLIGHT"))
8737     {
8738       addLight (aLightNew, isGlobal);
8739       if (!toCreate)
8740       {
8741         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8742         return 1;
8743       }
8744       toCreate  = Standard_False;
8745       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
8746     }
8747     else if (anArgCase.IsEqual ("POSLIGHT")
8748           || anArgCase.IsEqual ("POSITIONAL"))
8749     {
8750       addLight (aLightNew, isGlobal);
8751       if (!toCreate)
8752       {
8753         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8754         return 1;
8755       }
8756       toCreate  = Standard_False;
8757       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
8758     }
8759     else if (anArgCase.IsEqual ("CHANGE"))
8760     {
8761       addLight (aLightNew, isGlobal);
8762       aLightNew.Nullify();
8763       if (++anArgIt >= theArgsNb)
8764       {
8765         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8766         return 1;
8767       }
8768
8769       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
8770       Standard_Integer aLightIt = 0;
8771       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8772       {
8773         if (aLightIt == aLightId)
8774         {
8775           aLightOld = aLightIter.Value();
8776           break;
8777         }
8778       }
8779
8780       if (aLightOld.IsNull())
8781       {
8782         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
8783         return 1;
8784       }
8785     }
8786     else if (anArgCase.IsEqual ("DEL")
8787           || anArgCase.IsEqual ("DELETE"))
8788     {
8789       Handle(V3d_Light) aLightDel;
8790       if (++anArgIt >= theArgsNb)
8791       {
8792         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8793         return 1;
8794       }
8795
8796       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8797       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
8798       Standard_Integer aLightIt = 0;
8799       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8800       {
8801         aLightDel = aLightIter.Value();
8802         if (aLightIt == aLightDelId)
8803         {
8804           break;
8805         }
8806       }
8807       if (!aLightDel.IsNull())
8808       {
8809         aViewer->DelLight (aLightDel);
8810       }
8811     }
8812     else if (anArgCase.IsEqual ("COLOR")
8813           || anArgCase.IsEqual ("COLOUR"))
8814     {
8815       if (++anArgIt >= theArgsNb)
8816       {
8817         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8818         return 1;
8819       }
8820
8821       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8822       anArgNext.UpperCase();
8823       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
8824       if (!aLightCurr.IsNull())
8825       {
8826         aLightCurr->SetColor (aColor);
8827       }
8828     }
8829     else if (anArgCase.IsEqual ("POS")
8830           || anArgCase.IsEqual ("POSITION"))
8831     {
8832       if ((anArgIt + 3) >= theArgsNb)
8833       {
8834         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8835         return 1;
8836       }
8837
8838       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8839       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8840       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8841       if (!aLightDir.IsNull())
8842       {
8843         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8844       }
8845       else if (!aLightPos.IsNull())
8846       {
8847         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8848       }
8849       else if (!aLightSpot.IsNull())
8850       {
8851         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8852       }
8853       else
8854       {
8855         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8856         return 1;
8857       }
8858     }
8859     else if (anArgCase.IsEqual ("DIR")
8860           || anArgCase.IsEqual ("DIRECTION"))
8861     {
8862       if ((anArgIt + 3) >= theArgsNb)
8863       {
8864         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8865         return 1;
8866       }
8867
8868       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8869       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8870       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8871       if (!aLightDir.IsNull())
8872       {
8873         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8874       }
8875       else if (!aLightSpot.IsNull())
8876       {
8877         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8878       }
8879       else
8880       {
8881         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8882         return 1;
8883       }
8884     }
8885     else if (anArgCase.IsEqual ("SM")
8886           || anArgCase.IsEqual ("SMOOTHNESS"))
8887     {
8888       if (++anArgIt >= theArgsNb)
8889       {
8890         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8891         return 1;
8892       }
8893
8894       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
8895
8896       if (fabs (aSmoothness) < Precision::Confusion())
8897       {
8898         aLightCurr->SetIntensity (1.f);
8899       }
8900       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
8901       {
8902         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
8903       }
8904       else
8905       {
8906         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
8907         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
8908       }
8909
8910       if (!aLightPos.IsNull())
8911       {
8912         aLightPos->SetSmoothRadius (aSmoothness);
8913       }
8914       else if (!aLightDir.IsNull())
8915       {
8916         aLightDir->SetSmoothAngle (aSmoothness);
8917       }
8918     }
8919     else if (anArgCase.IsEqual ("INT")
8920           || anArgCase.IsEqual ("INTENSITY"))
8921     {
8922       if (++anArgIt >= theArgsNb)
8923       {
8924         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8925         return 1;
8926       }
8927
8928       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
8929
8930       if (!aLightCurr.IsNull())
8931       {
8932         aLightCurr->SetIntensity (aIntensity);
8933       }
8934     }
8935     else if (anArgCase.IsEqual ("ANG")
8936           || anArgCase.IsEqual ("ANGLE"))
8937     {
8938       if (++anArgIt >= theArgsNb)
8939       {
8940         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8941         return 1;
8942       }
8943
8944       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
8945
8946       if (!aLightSpot.IsNull())
8947       {
8948         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
8949       }
8950     }
8951     else if (anArgCase.IsEqual ("CONSTATTEN")
8952           || anArgCase.IsEqual ("CONSTATTENUATION"))
8953     {
8954       if (++anArgIt >= theArgsNb)
8955       {
8956         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8957         return 1;
8958       }
8959
8960       if (!aLightPos.IsNull())
8961       {
8962         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8963         anAtten[0] = Atof (theArgVec[anArgIt]);
8964         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8965       }
8966       else if (!aLightSpot.IsNull())
8967       {
8968         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8969         anAtten[0] = Atof (theArgVec[anArgIt]);
8970         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8971       }
8972       else
8973       {
8974         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8975         return 1;
8976       }
8977     }
8978     else if (anArgCase.IsEqual ("LINATTEN")
8979           || anArgCase.IsEqual ("LINEARATTEN")
8980           || anArgCase.IsEqual ("LINEARATTENUATION"))
8981     {
8982       if (++anArgIt >= theArgsNb)
8983       {
8984         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8985         return 1;
8986       }
8987
8988       if (!aLightPos.IsNull())
8989       {
8990         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8991         anAtten[1] = Atof (theArgVec[anArgIt]);
8992         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8993       }
8994       else if (!aLightSpot.IsNull())
8995       {
8996         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8997         anAtten[1] = Atof (theArgVec[anArgIt]);
8998         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8999       }
9000       else
9001       {
9002         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9003         return 1;
9004       }
9005     }
9006     else if (anArgCase.IsEqual ("EXP")
9007           || anArgCase.IsEqual ("EXPONENT")
9008           || anArgCase.IsEqual ("SPOTEXP")
9009           || anArgCase.IsEqual ("SPOTEXPONENT"))
9010     {
9011       if (++anArgIt >= theArgsNb)
9012       {
9013         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9014         return 1;
9015       }
9016
9017       if (!aLightSpot.IsNull())
9018       {
9019         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
9020       }
9021       else
9022       {
9023         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9024         return 1;
9025       }
9026     }
9027     else if (anArgCase.IsEqual ("HEAD")
9028           || anArgCase.IsEqual ("HEADLIGHT"))
9029     {
9030       if (++anArgIt >= theArgsNb)
9031       {
9032         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9033         return 1;
9034       }
9035
9036       if (aLightAmb.IsNull()
9037        && !aLightCurr.IsNull())
9038       {
9039         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
9040       }
9041       else
9042       {
9043         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9044         return 1;
9045       }
9046     }
9047     else
9048     {
9049       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9050     }
9051   }
9052
9053   addLight (aLightNew, isGlobal);
9054   aViewer->UpdateLights();
9055
9056   return 0;
9057 }
9058
9059 //=======================================================================
9060 //function : VRenderParams
9061 //purpose  : Enables/disables rendering features
9062 //=======================================================================
9063
9064 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9065                                        Standard_Integer  theArgNb,
9066                                        const char**      theArgVec)
9067 {
9068   Handle(V3d_View) aView = ViewerTest::CurrentView();
9069   if (aView.IsNull())
9070   {
9071     std::cerr << "Error: no active viewer!\n";
9072     return 1;
9073   }
9074
9075   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9076   TCollection_AsciiString aCmdName (theArgVec[0]);
9077   aCmdName.LowerCase();
9078   if (aCmdName == "vraytrace")
9079   {
9080     if (theArgNb == 1)
9081     {
9082       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9083       return 0;
9084     }
9085     else if (theArgNb == 2)
9086     {
9087       TCollection_AsciiString aValue (theArgVec[1]);
9088       aValue.LowerCase();
9089       if (aValue == "on"
9090        || aValue == "1")
9091       {
9092         aParams.Method = Graphic3d_RM_RAYTRACING;
9093         aView->Redraw();
9094         return 0;
9095       }
9096       else if (aValue == "off"
9097             || aValue == "0")
9098       {
9099         aParams.Method = Graphic3d_RM_RASTERIZATION;
9100         aView->Redraw();
9101         return 0;
9102       }
9103       else
9104       {
9105         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9106         return 1;
9107       }
9108     }
9109     else
9110     {
9111       std::cout << "Error: wrong number of arguments\n";
9112       return 1;
9113     }
9114   }
9115
9116   if (theArgNb < 2)
9117   {
9118     theDI << "renderMode:  ";
9119     switch (aParams.Method)
9120     {
9121       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9122       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9123     }
9124     theDI << "\n";
9125     theDI << "transparency:  ";
9126     switch (aParams.TransparencyMethod)
9127     {
9128       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
9129       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
9130                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
9131     }
9132     theDI << "\n";
9133     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9134     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
9135     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9136     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9137     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9138     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9139     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9140     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9141     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9142     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9143     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9144     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9145     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
9146     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
9147     theDI << "shadingModel: ";
9148     switch (aView->ShadingModel())
9149     {
9150       case V3d_COLOR:   theDI << "color";   break;
9151       case V3d_FLAT:    theDI << "flat";    break;
9152       case V3d_GOURAUD: theDI << "gouraud"; break;
9153       case V3d_PHONG:   theDI << "phong";   break;
9154     }
9155     theDI << "\n";
9156     return 0;
9157   }
9158
9159   Standard_Boolean toPrint = Standard_False;
9160   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9161   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9162   {
9163     Standard_CString        anArg (theArgVec[anArgIter]);
9164     TCollection_AsciiString aFlag (anArg);
9165     aFlag.LowerCase();
9166     if (anUpdateTool.parseRedrawMode (aFlag))
9167     {
9168       continue;
9169     }
9170     else if (aFlag == "-echo"
9171           || aFlag == "-print")
9172     {
9173       toPrint = Standard_True;
9174       anUpdateTool.Invalidate();
9175     }
9176     else if (aFlag == "-mode"
9177           || aFlag == "-rendermode"
9178           || aFlag == "-render_mode")
9179     {
9180       if (toPrint)
9181       {
9182         switch (aParams.Method)
9183         {
9184           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9185           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9186         }
9187         continue;
9188       }
9189       else
9190       {
9191         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9192         return 1;
9193       }
9194     }
9195     else if (aFlag == "-ray"
9196           || aFlag == "-raytrace")
9197     {
9198       if (toPrint)
9199       {
9200         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9201         continue;
9202       }
9203
9204       aParams.Method = Graphic3d_RM_RAYTRACING;
9205     }
9206     else if (aFlag == "-rast"
9207           || aFlag == "-raster"
9208           || aFlag == "-rasterization")
9209     {
9210       if (toPrint)
9211       {
9212         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9213         continue;
9214       }
9215
9216       aParams.Method = Graphic3d_RM_RASTERIZATION;
9217     }
9218     else if (aFlag == "-msaa")
9219     {
9220       if (toPrint)
9221       {
9222         theDI << aParams.NbMsaaSamples << " ";
9223         continue;
9224       }
9225       else if (++anArgIter >= theArgNb)
9226       {
9227         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9228         return 1;
9229       }
9230
9231       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9232       if (aNbSamples < 0)
9233       {
9234         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9235         return 1;
9236       }
9237       else
9238       {
9239         aParams.NbMsaaSamples = aNbSamples;
9240       }
9241     }
9242     else if (aFlag == "-oit")
9243     {
9244       if (toPrint)
9245       {
9246         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
9247         {
9248           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
9249         }
9250         else
9251         {
9252           theDI << "off" << " ";
9253         }
9254         continue;
9255       }
9256       else if (++anArgIter >= theArgNb)
9257       {
9258         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9259         return 1;
9260       }
9261
9262       TCollection_AsciiString aParam = theArgVec[anArgIter];
9263       aParam.LowerCase();
9264       if (aParam.IsRealValue())
9265       {
9266         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
9267         if (aWeight < 0.f || aWeight > 1.f)
9268         {
9269           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
9270           return 1;
9271         }
9272
9273         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
9274         aParams.OitDepthFactor     = aWeight;
9275       }
9276       else if (aParam == "off")
9277       {
9278         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
9279       }
9280       else
9281       {
9282         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9283         return 1;
9284       }
9285     }
9286     else if (aFlag == "-rendscale"
9287           || aFlag == "-renderscale"
9288           || aFlag == "-renderresolutionscale")
9289     {
9290       if (toPrint)
9291       {
9292         theDI << aParams.RenderResolutionScale << " ";
9293         continue;
9294       }
9295       else if (++anArgIter >= theArgNb)
9296       {
9297         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9298         return 1;
9299       }
9300
9301       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
9302       if (aScale < 0.01)
9303       {
9304         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
9305         return 1;
9306       }
9307       else
9308       {
9309         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
9310       }
9311     }
9312     else if (aFlag == "-raydepth"
9313           || aFlag == "-ray_depth")
9314     {
9315       if (toPrint)
9316       {
9317         theDI << aParams.RaytracingDepth << " ";
9318         continue;
9319       }
9320       else if (++anArgIter >= theArgNb)
9321       {
9322         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9323         return 1;
9324       }
9325
9326       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9327
9328       // We allow RaytracingDepth be more than 10 in case of GI enabled
9329       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9330       {
9331         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9332         return 1;
9333       }
9334       else
9335       {
9336         aParams.RaytracingDepth = aDepth;
9337       }
9338     }
9339     else if (aFlag == "-shad"
9340           || aFlag == "-shadows")
9341     {
9342       if (toPrint)
9343       {
9344         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
9345         continue;
9346       }
9347
9348       Standard_Boolean toEnable = Standard_True;
9349       if (++anArgIter < theArgNb
9350       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9351       {
9352         --anArgIter;
9353       }
9354       aParams.IsShadowEnabled = toEnable;
9355     }
9356     else if (aFlag == "-refl"
9357           || aFlag == "-reflections")
9358     {
9359       if (toPrint)
9360       {
9361         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
9362         continue;
9363       }
9364
9365       Standard_Boolean toEnable = Standard_True;
9366       if (++anArgIter < theArgNb
9367       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9368       {
9369         --anArgIter;
9370       }
9371       aParams.IsReflectionEnabled = toEnable;
9372     }
9373     else if (aFlag == "-fsaa")
9374     {
9375       if (toPrint)
9376       {
9377         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
9378         continue;
9379       }
9380
9381       Standard_Boolean toEnable = Standard_True;
9382       if (++anArgIter < theArgNb
9383       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9384       {
9385         --anArgIter;
9386       }
9387       aParams.IsAntialiasingEnabled = toEnable;
9388     }
9389     else if (aFlag == "-gleam")
9390     {
9391       if (toPrint)
9392       {
9393         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
9394         continue;
9395       }
9396
9397       Standard_Boolean toEnable = Standard_True;
9398       if (++anArgIter < theArgNb
9399       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9400       {
9401         --anArgIter;
9402       }
9403       aParams.IsTransparentShadowEnabled = toEnable;
9404     }
9405     else if (aFlag == "-gi")
9406     {
9407       if (toPrint)
9408       {
9409         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
9410         continue;
9411       }
9412
9413       Standard_Boolean toEnable = Standard_True;
9414       if (++anArgIter < theArgNb
9415       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9416       {
9417         --anArgIter;
9418       }
9419       aParams.IsGlobalIlluminationEnabled = toEnable;
9420       if (!toEnable)
9421       {
9422         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
9423       }
9424     }
9425     else if (aFlag == "-blockedrng"
9426           || aFlag == "-brng")
9427     {
9428       if (toPrint)
9429       {
9430         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
9431         continue;
9432       }
9433
9434       Standard_Boolean toEnable = Standard_True;
9435       if (++anArgIter < theArgNb
9436         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9437       {
9438         --anArgIter;
9439       }
9440       aParams.CoherentPathTracingMode = toEnable;
9441     }
9442     else if (aFlag == "-maxrad")
9443     {
9444       if (toPrint)
9445       {
9446         theDI << aParams.RadianceClampingValue << " ";
9447         continue;
9448       }
9449       else if (++anArgIter >= theArgNb)
9450       {
9451         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9452         return 1;
9453       }
9454
9455       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
9456       if (!aMaxRadStr.IsRealValue())
9457       {
9458         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9459         return 1;
9460       }
9461
9462       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
9463       if (aMaxRadiance <= 0.0)
9464       {
9465         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
9466         return 1;
9467       }
9468       else
9469       {
9470         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
9471       }
9472     }
9473     else if (aFlag == "-iss")
9474     {
9475       if (toPrint)
9476       {
9477         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
9478         continue;
9479       }
9480
9481       Standard_Boolean toEnable = Standard_True;
9482       if (++anArgIter < theArgNb
9483         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9484       {
9485         --anArgIter;
9486       }
9487       aParams.AdaptiveScreenSampling = toEnable;
9488     }
9489     else if (aFlag == "-issd")
9490     {
9491       if (toPrint)
9492       {
9493         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
9494         continue;
9495       }
9496
9497       Standard_Boolean toEnable = Standard_True;
9498       if (++anArgIter < theArgNb
9499         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9500       {
9501         --anArgIter;
9502       }
9503       aParams.ShowSamplingTiles = toEnable;
9504     }
9505     else if (aFlag == "-nbtiles")
9506     {
9507       if (toPrint)
9508       {
9509         theDI << aParams.NbRayTracingTiles << " ";
9510         continue;
9511       }
9512       else if (++anArgIter >= theArgNb)
9513       {
9514         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9515         return 1;
9516       }
9517
9518       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
9519
9520       if (aNbTiles < 64)
9521       {
9522         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
9523         std::cerr << "Specify value in range [64, 1024].\n";
9524         return 1;
9525       }
9526       else
9527       {
9528         aParams.NbRayTracingTiles = aNbTiles;
9529       }
9530     }
9531     else if (aFlag == "-env")
9532     {
9533       if (toPrint)
9534       {
9535         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
9536         continue;
9537       }
9538
9539       Standard_Boolean toEnable = Standard_True;
9540       if (++anArgIter < theArgNb
9541         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9542       {
9543         --anArgIter;
9544       }
9545       aParams.UseEnvironmentMapBackground = toEnable;
9546     }
9547     else if (aFlag == "-twoside")
9548     {
9549       if (toPrint)
9550       {
9551         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
9552         continue;
9553       }
9554
9555       Standard_Boolean toEnable = Standard_True;
9556       if (++anArgIter < theArgNb
9557         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9558       {
9559         --anArgIter;
9560       }
9561       aParams.TwoSidedBsdfModels = toEnable;
9562     }
9563     else if (aFlag == "-shademodel"
9564           || aFlag == "-shadingmodel"
9565           || aFlag == "-shading")
9566     {
9567       if (toPrint)
9568       {
9569         switch (aView->ShadingModel())
9570         {
9571           case V3d_COLOR:   theDI << "color ";   break;
9572           case V3d_FLAT:    theDI << "flat ";    break;
9573           case V3d_GOURAUD: theDI << "gouraud "; break;
9574           case V3d_PHONG:   theDI << "phong ";   break;
9575         }
9576         continue;
9577       }
9578
9579       if (++anArgIter >= theArgNb)
9580       {
9581         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9582       }
9583
9584       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9585       aMode.LowerCase();
9586       if (aMode == "color"
9587        || aMode == "none")
9588       {
9589         aView->SetShadingModel (V3d_COLOR);
9590       }
9591       else if (aMode == "flat"
9592             || aMode == "facet")
9593       {
9594         aView->SetShadingModel (V3d_FLAT);
9595       }
9596       else if (aMode == "gouraud"
9597             || aMode == "vertex"
9598             || aMode == "vert")
9599       {
9600         aView->SetShadingModel (V3d_GOURAUD);
9601       }
9602       else if (aMode == "phong"
9603             || aMode == "fragment"
9604             || aMode == "frag"
9605             || aMode == "pixel")
9606       {
9607         aView->SetShadingModel (V3d_PHONG);
9608       }
9609       else
9610       {
9611         std::cout << "Error: unknown shading model '" << aMode << "'\n";
9612         return 1;
9613       }
9614     }
9615     else if (aFlag == "-resolution")
9616     {
9617       if (++anArgIter >= theArgNb)
9618       {
9619         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9620         return 1;
9621       }
9622
9623       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
9624       if (aResolution.IsIntegerValue())
9625       {
9626         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
9627       }
9628       else
9629       {
9630         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9631         return 1;
9632       }
9633     }
9634     else if (aFlag == "-rebuildglsl"
9635           || aFlag == "-rebuild")
9636     {
9637       if (toPrint)
9638       {
9639         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
9640         continue;
9641       }
9642
9643       Standard_Boolean toEnable = Standard_True;
9644       if (++anArgIter < theArgNb
9645           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9646       {
9647         --anArgIter;
9648       }
9649       aParams.RebuildRayTracingShaders = toEnable;
9650     }
9651     else if (aFlag == "-exposure")
9652     {
9653       if (++anArgIter >= theArgNb)
9654       {
9655         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9656         return 1;
9657       }
9658
9659       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
9660       if (anExposure.IsRealValue())
9661       {
9662         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
9663       }
9664       else
9665       {
9666         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9667         return 1;
9668       }
9669     }
9670     else if (aFlag == "-whitepoint")
9671     {
9672       if (++anArgIter >= theArgNb)
9673       {
9674         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9675         return 1;
9676       }
9677
9678       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
9679       if (aWhitePoint.IsRealValue())
9680       {
9681         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
9682       }
9683       else
9684       {
9685         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9686         return 1;
9687       }
9688     }
9689     else if (aFlag == "-tonemapping")
9690     {
9691       if (++anArgIter >= theArgNb)
9692       {
9693         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9694         return 1;
9695       }
9696
9697       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9698       aMode.LowerCase();
9699
9700       if (aMode == "disabled")
9701       {
9702         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
9703       }
9704       else if (aMode == "filmic")
9705       {
9706         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
9707       }
9708       else
9709       {
9710         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9711         return 1;
9712       }
9713     }
9714     else
9715     {
9716       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
9717       return 1;
9718     }
9719   }
9720
9721   return 0;
9722 }
9723
9724 //=======================================================================
9725 //function : VProgressiveMode
9726 //purpose  :
9727 //=======================================================================
9728 #if defined(_WIN32)
9729 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
9730                                           Standard_Integer  /*theNbArgs*/,
9731                                           const char**      /*theArgs*/)
9732 {
9733   Handle(V3d_View) aView = ViewerTest::CurrentView();
9734   if (aView.IsNull())
9735   {
9736     std::cerr << "Error: no active viewer!\n";
9737     return 1;
9738   }
9739
9740   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
9741
9742   for (;;)
9743   {
9744     aView->Redraw();
9745
9746     Standard_Boolean toExit = Standard_False;
9747
9748     MSG aMsg;
9749     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
9750     {
9751       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
9752       {
9753         toExit = Standard_True;
9754       }
9755
9756       TranslateMessage (&aMsg);
9757       DispatchMessageW (&aMsg);
9758     }
9759
9760     if (toExit)
9761     {
9762       break;
9763     }
9764   }
9765
9766   return 0;
9767 }
9768 #endif
9769
9770 //=======================================================================
9771 //function : VFrustumCulling
9772 //purpose  : enables/disables view volume's culling.
9773 //=======================================================================
9774 static int VFrustumCulling (Draw_Interpretor& theDI,
9775                             Standard_Integer  theArgNb,
9776                             const char**      theArgVec)
9777 {
9778   Handle(V3d_View) aView = ViewerTest::CurrentView();
9779   if (aView.IsNull())
9780   {
9781     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
9782     return 1;
9783   }
9784
9785   if (theArgNb < 2)
9786   {
9787     theDI << (aView->IsCullingEnabled() ? "on" : "off");
9788     return 0;
9789   }
9790   else if (theArgNb != 2)
9791   {
9792     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
9793     return 1;
9794   }
9795
9796   TCollection_AsciiString aModeStr (theArgVec[1]);
9797   aModeStr.LowerCase();
9798   Standard_Boolean toEnable = 0;
9799   if (aModeStr == "on")
9800   {
9801     toEnable = 1;
9802   }
9803   else if (aModeStr == "off")
9804   {
9805     toEnable = 0;
9806   }
9807   else
9808   {
9809     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9810   }
9811
9812   aView->SetFrustumCulling (toEnable);
9813   aView->Redraw();
9814   return 0;
9815 }
9816
9817 //=======================================================================
9818 //function : VHighlightSelected
9819 //purpose  : 
9820 //=======================================================================
9821 static int VHighlightSelected (Draw_Interpretor& theDI,
9822                                Standard_Integer  theArgNb,
9823                                const char**      theArgVec)
9824 {
9825   if (ViewerTest::GetAISContext().IsNull())
9826   {
9827     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
9828     return 1;
9829   }
9830
9831   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9832
9833   if (theArgNb < 2)
9834   {
9835     theDI << (aContext->ToHilightSelected() ? "on" : "off");
9836     return 0;
9837   }
9838
9839   if (theArgNb != 2)
9840   {
9841     std::cout  << theArgVec[0] << " error : wrong number of parameters."
9842           << "Type 'help" << theArgVec[0] << "' for more information.";
9843     return 1;
9844   }
9845
9846   // Parse parameter
9847   TCollection_AsciiString aMode (theArgVec[1]);
9848   aMode.LowerCase();
9849   Standard_Boolean toEnable = Standard_False;
9850   if (aMode.IsEqual ("on"))
9851   {
9852     toEnable = Standard_True;
9853   }
9854   else if (aMode.IsEqual ("off"))
9855   {
9856     toEnable = Standard_False;
9857   }
9858   else
9859   {
9860     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9861   }
9862
9863   if (toEnable != aContext->ToHilightSelected())
9864   {
9865     aContext->SetToHilightSelected (toEnable);
9866
9867     // Move cursor to null position and  back to process updating of detection
9868     // and highlighting of selected object immediatly.
9869     Standard_Integer aPixX = 0;
9870     Standard_Integer aPixY = 0;
9871     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
9872
9873     anEventManager->GetCurrentPosition (aPixX, aPixY);
9874     anEventManager->MoveTo (0, 0);
9875     anEventManager->MoveTo (aPixX, aPixY);
9876   }
9877
9878   return 0;
9879 }
9880
9881 //=======================================================================
9882 //function : VXRotate
9883 //purpose  :
9884 //=======================================================================
9885 static Standard_Integer VXRotate (Draw_Interpretor& di,
9886                                    Standard_Integer argc,
9887                                    const char ** argv)
9888 {
9889   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9890   if (aContext.IsNull())
9891   {
9892     di << argv[0] << "ERROR : use 'vinit' command before \n";
9893     return 1;
9894   }
9895   
9896   if (argc != 3)
9897   {
9898     di << "ERROR : Usage : " << argv[0] << " name angle\n";
9899     return 1;
9900   }
9901
9902   TCollection_AsciiString aName (argv[1]);
9903   Standard_Real anAngle = Draw::Atof (argv[2]);
9904
9905   // find object
9906   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
9907   Handle(AIS_InteractiveObject) anIObj;
9908   if (!aMap.IsBound2 (aName) )
9909   {
9910     di << "Use 'vdisplay' before\n";
9911     return 1;
9912   }
9913   else
9914   {
9915     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
9916
9917     gp_Trsf aTransform;
9918     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
9919     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
9920
9921     aContext->SetLocation (anIObj, aTransform);
9922     aContext->UpdateCurrentViewer();
9923   }
9924
9925   return 0;
9926 }
9927
9928 //===============================================================================================
9929 //class   : ViewerTest_AISManipulator
9930 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
9931 //===============================================================================================
9932 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9933
9934 class ViewerTest_AISManipulator : public AIS_Manipulator
9935 {
9936 public:
9937
9938   ViewerTest_AISManipulator() : AIS_Manipulator()
9939   {
9940     GetMapOfAISManipulators().Add (this);
9941   }
9942
9943   virtual ~ViewerTest_AISManipulator()
9944   {
9945     GetMapOfAISManipulators().Remove (this);
9946   }
9947
9948   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9949 };
9950
9951 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9952 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9953
9954 //===============================================================================================
9955 //function : VManipulator
9956 //purpose  :
9957 //===============================================================================================
9958 static int VManipulator (Draw_Interpretor& theDi,
9959                          Standard_Integer  theArgsNb,
9960                          const char**      theArgVec)
9961 {
9962   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9963   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9964   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
9965   if (aView.IsNull()
9966    || aViewer.IsNull())
9967   {
9968     std::cerr << "No active viewer!\n";
9969     return 1;
9970   }
9971
9972   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
9973   Standard_Integer anArgIter = 1;
9974   for (; anArgIter < theArgsNb; ++anArgIter)
9975   {
9976     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
9977   }
9978
9979   ViewerTest_CmdParser aCmd;
9980   aCmd.AddDescription ("Manages manipulator for interactive objects:");
9981   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
9982   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
9983   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
9984   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
9985   aCmd.AddOption ("detach",         "...       - detach manipulator");
9986
9987   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
9988   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
9989   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
9990
9991   aCmd.AddOption ("move",   "... x y z - move object");
9992   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
9993   aCmd.AddOption ("scale",  "... factor - scale object");
9994
9995   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
9996   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
9997   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
9998   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
9999   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
10000   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
10001   aCmd.AddOption ("size",              "... size - set size of manipulator");
10002   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
10003
10004   aCmd.Parse (theArgsNb, theArgVec);
10005
10006   if (aCmd.HasOption ("help"))
10007   {
10008     theDi.PrintHelp (theArgVec[0]);
10009     return 0;
10010   }
10011
10012   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
10013
10014   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
10015
10016   if (aName.IsEmpty())
10017   {
10018     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
10019     return 1;
10020   }
10021
10022   // ----------------------------------
10023   // detach existing manipulator object
10024   // ----------------------------------
10025
10026   if (aCmd.HasOption ("detach"))
10027   {
10028     if (!aMapAIS.IsBound2 (aName))
10029     {
10030       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
10031       return 1;
10032     }
10033
10034     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10035     if (aManipulator.IsNull())
10036     {
10037       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10038       return 1;
10039     }
10040
10041     aManipulator->Detach();
10042     aMapAIS.UnBind2 (aName);
10043     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
10044
10045     return 0;
10046   }
10047
10048   // -----------------------------------------------
10049   // find or create manipulator if it does not exist
10050   // -----------------------------------------------
10051
10052   Handle(AIS_Manipulator) aManipulator;
10053   if (!aMapAIS.IsBound2 (aName))
10054   {
10055     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
10056
10057     aManipulator = new ViewerTest_AISManipulator();
10058     aMapAIS.Bind (aManipulator, aName);
10059   }
10060   else
10061   {
10062     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10063     if (aManipulator.IsNull())
10064     {
10065       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10066       return 1;
10067     }
10068   }
10069
10070   // -----------------------------------------
10071   // change properties of manipulator instance
10072   // -----------------------------------------
10073
10074   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
10075   {
10076     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
10077   }
10078   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
10079   {
10080     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
10081   }
10082   if (aCmd.HasOption ("followRotation", 1, Standard_True))
10083   {
10084     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
10085   }
10086   if (aCmd.HasOption ("gap", 1, Standard_True))
10087   {
10088     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
10089   }
10090   if (aCmd.HasOption ("part", 3, Standard_True))
10091   {
10092     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
10093     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
10094     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
10095     if (aMode < 1 || aMode > 3)
10096     {
10097       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
10098       return 1;
10099     }
10100
10101     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
10102   }
10103   if (aCmd.HasOption ("pos", 3, Standard_True))
10104   {
10105     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
10106     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
10107     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
10108
10109     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
10110   }
10111   if (aCmd.HasOption ("size", 1, Standard_True))
10112   {
10113     aManipulator->SetSize (aCmd.ArgFloat ("size"));
10114   }
10115   if (aCmd.HasOption ("zoomable", 1, Standard_True))
10116   {
10117     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
10118
10119     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
10120     {
10121       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
10122       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
10123     }
10124   }
10125
10126   // ---------------------------------------------------
10127   // attach, detach or access manipulator from an object
10128   // ---------------------------------------------------
10129
10130   if (aCmd.HasOption ("attach"))
10131   {
10132     // Find an object and attach manipulator to it
10133     if (!aCmd.HasOption ("attach", 1, Standard_True))
10134     {
10135       return 1;
10136     }
10137
10138     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
10139     if (!aMapAIS.IsBound2 (anObjName))
10140     {
10141       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
10142       return 1;
10143     }
10144
10145     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
10146     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
10147     for (; anIt.More(); anIt.Next())
10148     {
10149       if (anIt.Value()->IsAttached()
10150        && anIt.Value()->Object() == anObject)
10151       {
10152         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
10153         return 1;
10154       }
10155     }
10156
10157     AIS_Manipulator::OptionsForAttach anOptions;
10158     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
10159     {
10160       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
10161     }
10162     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
10163     {
10164       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
10165     }
10166     if (aCmd.HasOption ("enableModes", 1, Standard_True))
10167     {
10168       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
10169     }
10170
10171     aManipulator->Attach (anObject, anOptions);
10172   }
10173
10174   // --------------------------------------
10175   // apply transformation using manipulator
10176   // --------------------------------------
10177
10178   if (aCmd.HasOption ("startTransform", 2, Standard_True))
10179   {
10180     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
10181   }
10182   if (aCmd.HasOption ("transform", 2, Standard_True))
10183   {
10184     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
10185   }
10186   if (aCmd.HasOption ("stopTransform"))
10187   {
10188     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
10189
10190     aManipulator->StopTransform (toApply);
10191   }
10192
10193   gp_Trsf aT;
10194   if (aCmd.HasOption ("move", 3, Standard_True))
10195   {
10196     aT.SetTranslationPart (aCmd.ArgVec ("move"));
10197   }
10198   if (aCmd.HasOption ("rotate", 7, Standard_True))
10199   {
10200     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
10201   }
10202   if (aCmd.HasOption ("scale", 1))
10203   {
10204     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
10205   }
10206
10207   if (aT.Form() != gp_Identity)
10208   {
10209     aManipulator->Transform (aT);
10210   }
10211
10212   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
10213
10214   return 0;
10215 }
10216
10217 //===============================================================================================
10218 //function : VSelectionProperties
10219 //purpose  :
10220 //===============================================================================================
10221 static int VSelectionProperties (Draw_Interpretor& theDi,
10222                                  Standard_Integer  theArgsNb,
10223                                  const char**      theArgVec)
10224 {
10225   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10226   if (aCtx.IsNull())
10227   {
10228     std::cerr << "No active viewer!\n";
10229     return 1;
10230   }
10231
10232   Standard_Boolean toPrint  = theArgsNb == 1;
10233   Standard_Boolean toRedraw = Standard_False;
10234   Standard_Integer anArgIter = 1;
10235   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
10236   if (anArgIter < theArgsNb)
10237   {
10238     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
10239     anArgFirst.LowerCase();
10240     ++anArgIter;
10241     if (anArgFirst == "dynhighlight"
10242      || anArgFirst == "dynhilight"
10243      || anArgFirst == "dynamichighlight"
10244      || anArgFirst == "dynamichilight")
10245     {
10246       aType = Prs3d_TypeOfHighlight_Dynamic;
10247     }
10248     else if (anArgFirst == "localdynhighlight"
10249           || anArgFirst == "localdynhilight"
10250           || anArgFirst == "localdynamichighlight"
10251           || anArgFirst == "localdynamichilight")
10252     {
10253       aType = Prs3d_TypeOfHighlight_LocalDynamic;
10254     }
10255     else if (anArgFirst == "selhighlight"
10256           || anArgFirst == "selhilight"
10257           || anArgFirst == "selectedhighlight"
10258           || anArgFirst == "selectedhilight")
10259     {
10260       aType = Prs3d_TypeOfHighlight_Selected;
10261     }
10262     else if (anArgFirst == "localselhighlight"
10263           || anArgFirst == "localselhilight"
10264           || anArgFirst == "localselectedhighlight"
10265           || anArgFirst == "localselectedhilight")
10266     {
10267       aType = Prs3d_TypeOfHighlight_LocalSelected;
10268     }
10269     else
10270     {
10271       --anArgIter;
10272     }
10273   }
10274   for (; anArgIter < theArgsNb; ++anArgIter)
10275   {
10276     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10277     anArg.LowerCase();
10278     if (anArg == "-help")
10279     {
10280       theDi.PrintHelp (theArgVec[0]);
10281       return 0;
10282     }
10283     else if (anArg == "-print")
10284     {
10285       toPrint = Standard_True;
10286     }
10287     else if (anArg == "-autoactivate")
10288     {
10289       Standard_Boolean toEnable = Standard_True;
10290       if (anArgIter + 1 < theArgsNb
10291        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
10292       {
10293         ++anArgIter;
10294       }
10295       aCtx->SetAutoActivateSelection (toEnable);
10296     }
10297     else if (anArg == "-pickstrategy"
10298           || anArg == "-pickingstrategy")
10299     {
10300       if (++anArgIter >= theArgsNb)
10301       {
10302         std::cout << "Syntax error: type of highlighting is undefined\n";
10303         return 1;
10304       }
10305
10306       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
10307       TCollection_AsciiString aVal (theArgVec[anArgIter]);
10308       aVal.LowerCase();
10309       if (aVal == "first"
10310        || aVal == "firstaccepted"
10311        || aVal == "firstacceptable")
10312       {
10313         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
10314       }
10315       else if (aVal == "topmost"
10316             || aVal == "onlyTopmost")
10317       {
10318         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
10319       }
10320       else
10321       {
10322         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
10323         return 1;
10324       }
10325
10326       aCtx->SetPickingStrategy (aStrategy);
10327     }
10328     else if (anArg == "-pixtol"
10329           && anArgIter + 1 < theArgsNb)
10330     {
10331       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
10332     }
10333     else if ((anArg == "-mode"
10334            || anArg == "-dispmode")
10335           && anArgIter + 1 < theArgsNb)
10336     {
10337       if (aType == Prs3d_TypeOfHighlight_None)
10338       {
10339         std::cout << "Syntax error: type of highlighting is undefined\n";
10340         return 1;
10341       }
10342
10343       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
10344       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10345       aStyle->SetDisplayMode (aDispMode);
10346       toRedraw = Standard_True;
10347     }
10348     else if (anArg == "-layer"
10349           && anArgIter + 1 < theArgsNb)
10350     {
10351       if (aType == Prs3d_TypeOfHighlight_None)
10352       {
10353         std::cout << "Syntax error: type of highlighting is undefined\n";
10354         return 1;
10355       }
10356
10357       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
10358       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
10359       {
10360         TColStd_SequenceOfInteger aLayers;
10361         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
10362         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
10363         {
10364           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
10365           return 1;
10366         }
10367       }
10368
10369       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10370       aStyle->SetZLayer (aNewLayer);
10371       toRedraw = Standard_True;
10372     }
10373     else if (anArg == "-hicolor"
10374           || anArg == "-selcolor"
10375           || anArg == "-color")
10376     {
10377       if (anArg.StartsWith ("-hi"))
10378       {
10379         aType = Prs3d_TypeOfHighlight_Dynamic;
10380       }
10381       else if (anArg.StartsWith ("-sel"))
10382       {
10383         aType = Prs3d_TypeOfHighlight_Selected;
10384       }
10385       else if (aType == Prs3d_TypeOfHighlight_None)
10386       {
10387         std::cout << "Syntax error: type of highlighting is undefined\n";
10388         return 1;
10389       }
10390
10391       Quantity_Color aColor;
10392       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
10393                                                            theArgVec + anArgIter + 1,
10394                                                            aColor);
10395       if (aNbParsed == 0)
10396       {
10397         std::cout << "Syntax error: need more arguments.\n";
10398         return 1;
10399       }
10400       anArgIter += aNbParsed;
10401
10402       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10403       aStyle->SetColor (aColor);
10404       toRedraw = Standard_True;
10405     }
10406     else if ((anArg == "-transp"
10407            || anArg == "-transparency"
10408            || anArg == "-hitransp"
10409            || anArg == "-seltransp"
10410            || anArg == "-hitransplocal"
10411            || anArg == "-seltransplocal")
10412           && anArgIter + 1 < theArgsNb)
10413     {
10414       if (anArg.StartsWith ("-hi"))
10415       {
10416         aType = Prs3d_TypeOfHighlight_Dynamic;
10417       }
10418       else if (anArg.StartsWith ("-sel"))
10419       {
10420         aType = Prs3d_TypeOfHighlight_Selected;
10421       }
10422       else if (aType == Prs3d_TypeOfHighlight_None)
10423       {
10424         std::cout << "Syntax error: type of highlighting is undefined\n";
10425         return 1;
10426       }
10427
10428       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
10429       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10430       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
10431       toRedraw = Standard_True;
10432     }
10433     else if ((anArg == "-mat"
10434            || anArg == "-material")
10435           && anArgIter + 1 < theArgsNb)
10436     {
10437       if (aType == Prs3d_TypeOfHighlight_None)
10438       {
10439         std::cout << "Syntax error: type of highlighting is undefined\n";
10440         return 1;
10441       }
10442
10443       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10444       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
10445       if (aMatName != Graphic3d_NOM_DEFAULT)
10446       {
10447         ++anArgIter;
10448         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
10449         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
10450         Graphic3d_MaterialAspect aMat (aMatName);
10451         aMat.SetColor (aStyle->Color());
10452         aMat.SetTransparency (aStyle->Transparency());
10453         anAspect->SetFrontMaterial (aMat);
10454         anAspect->SetInteriorColor (aStyle->Color());
10455         aStyle->SetBasicFillAreaAspect (anAspect);
10456       }
10457       else
10458       {
10459         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
10460       }
10461       toRedraw = Standard_True;
10462     }
10463     else
10464     {
10465       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
10466     }
10467   }
10468
10469   if (toPrint)
10470   {
10471     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
10472     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
10473     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
10474     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
10475     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
10476     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
10477     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
10478     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
10479     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
10480     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
10481     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
10482     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
10483   }
10484
10485   if (aCtx->NbSelected() != 0 && toRedraw)
10486   {
10487     aCtx->HilightSelected (Standard_True);
10488   }
10489
10490   return 0;
10491 }
10492
10493 //===============================================================================================
10494 //function : VDumpSelectionImage
10495 //purpose  :
10496 //===============================================================================================
10497 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
10498                                 Standard_Integer  theArgsNb,
10499                                 const char**      theArgVec)
10500 {
10501   if (theArgsNb < 2)
10502   {
10503     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
10504     return 1;
10505   }
10506
10507   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
10508   if (aContext.IsNull())
10509   {
10510     std::cout << "Error: no active view.\n";
10511     return 1;
10512   }
10513
10514   TCollection_AsciiString aFile;
10515   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10516   Image_Format anImgFormat = Image_Format_BGR;
10517   Standard_Integer aPickedIndex = 1;
10518   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10519   {
10520     TCollection_AsciiString aParam (theArgVec[anArgIter]);
10521     aParam.LowerCase();
10522     if (aParam == "-type")
10523     {
10524       if (++anArgIter >= theArgsNb)
10525       {
10526         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
10527         return 1;
10528       }
10529
10530       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10531       aValue.LowerCase();
10532       if (aValue == "depth"
10533        || aValue == "normdepth"
10534        || aValue == "normalizeddepth")
10535       {
10536         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10537         anImgFormat = Image_Format_GrayF;
10538       }
10539       if (aValue == "depthinverted"
10540        || aValue == "normdepthinverted"
10541        || aValue == "normalizeddepthinverted"
10542        || aValue == "inverted")
10543       {
10544         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
10545         anImgFormat = Image_Format_GrayF;
10546       }
10547       else if (aValue == "unnormdepth"
10548             || aValue == "unnormalizeddepth")
10549       {
10550         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
10551         anImgFormat = Image_Format_GrayF;
10552       }
10553       else if (aValue == "objectcolor"
10554             || aValue == "object"
10555             || aValue == "color")
10556       {
10557         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
10558       }
10559       else if (aValue == "entitycolor"
10560             || aValue == "entity")
10561       {
10562         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
10563       }
10564       else if (aValue == "ownercolor"
10565             || aValue == "owner")
10566       {
10567         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
10568       }
10569       else if (aValue == "selectionmodecolor"
10570             || aValue == "selectionmode"
10571             || aValue == "selmodecolor"
10572             || aValue == "selmode")
10573       {
10574         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
10575       }
10576     }
10577     else if (aParam == "-picked"
10578           || aParam == "-pickeddepth"
10579           || aParam == "-pickedindex")
10580     {
10581       if (++anArgIter >= theArgsNb)
10582       {
10583         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
10584         return 1;
10585       }
10586
10587       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
10588     }
10589     else if (aFile.IsEmpty())
10590     {
10591       aFile = theArgVec[anArgIter];
10592     }
10593     else
10594     {
10595       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
10596       return 1;
10597     }
10598   }
10599   if (aFile.IsEmpty())
10600   {
10601     std::cout << "Syntax error: image file name is missing.\n";
10602     return 1;
10603   }
10604
10605   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
10606   Standard_Integer aWidth = 0, aHeight = 0;
10607   aView->Window()->Size (aWidth, aHeight);
10608
10609   Image_AlienPixMap aPixMap;
10610   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
10611   {
10612     std::cout << "Error: can't allocate image.\n";
10613     return 1;
10614   }
10615   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
10616   {
10617     std::cout << "Error: can't generate selection image.\n";
10618     return 1;
10619   }
10620   if (!aPixMap.Save (aFile))
10621   {
10622     std::cout << "Error: can't save selection image.\n";
10623     return 0;
10624   }
10625   return 0;
10626 }
10627
10628 //=======================================================================
10629 //function : ViewerCommands
10630 //purpose  :
10631 //=======================================================================
10632
10633 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
10634 {
10635
10636   const char *group = "ZeViewer";
10637   theCommands.Add("vinit",
10638 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10639     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10640 #else
10641     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10642 #endif
10643     " - Creates new View window with specified name view_name.\n"
10644     "By default the new view is created in the viewer and in"
10645     " graphic driver shared with active view.\n"
10646     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
10647     "If driverName isn't specified the driver will be shared with active view.\n"
10648     "If viewerName isn't specified the viewer will be shared with active view.\n"
10649 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10650     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
10651     "is used in creation of graphic driver\n"
10652 #endif
10653     " - l, t: pixel position of left top corner of the window\n"
10654     " - w,h: width and heigth of window respectively.\n"
10655     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
10656     __FILE__,VInit,group);
10657   theCommands.Add("vclose" ,
10658     "[view_id [keep_context=0|1]]\n"
10659     "or vclose ALL - to remove all created views\n"
10660     " - removes view(viewer window) defined by its view_id.\n"
10661     " - keep_context: by default 0; if 1 and the last view is deleted"
10662     " the current context is not removed.",
10663     __FILE__,VClose,group);
10664   theCommands.Add("vactivate" ,
10665     "view_id"
10666     " - activates view(viewer window) defined by its view_id",
10667     __FILE__,VActivate,group);
10668   theCommands.Add("vviewlist",
10669     "vviewlist [format={tree, long}]"
10670     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
10671     " - format: format of result output, if tree the output is a tree view;"
10672     "otherwise it's a list of full view names. By default format = tree",
10673     __FILE__,VViewList,group);
10674   theCommands.Add("vhelp" ,
10675     "vhelp            : display help on the viewer commands",
10676     __FILE__,VHelp,group);
10677   theCommands.Add("vtop" ,
10678     "vtop or <T>      : Top view. Orientation +X+Y" ,
10679     __FILE__,VTop,group);
10680   theCommands.Add("vbottom" ,
10681     "vbottom          : Bottom view. Orientation +X-Y" ,
10682     __FILE__,VBottom,group);
10683   theCommands.Add("vleft" ,
10684     "vleft            : Left view. Orientation -Y+Z" ,
10685     __FILE__,VLeft,group);
10686   theCommands.Add("vright" ,
10687     "vright           : Right view. Orientation +Y+Z" ,
10688     __FILE__,VRight,group);
10689   theCommands.Add("vaxo" ,
10690     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
10691     __FILE__,VAxo,group);
10692   theCommands.Add("vfront" ,
10693     "vfront           : Front view. Orientation +X+Z" ,
10694     __FILE__,VFront,group);
10695   theCommands.Add("vback" ,
10696     "vback            : Back view. Orientation -X+Z" ,
10697     __FILE__,VBack,group);
10698   theCommands.Add("vpick" ,
10699     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
10700     VPick,group);
10701   theCommands.Add("vfit",
10702     "vfit or <F> [-selected] [-noupdate]"
10703     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
10704     __FILE__,VFit,group);
10705   theCommands.Add ("vfitarea",
10706     "vfitarea x1 y1 x2 y2"
10707     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
10708     "\n\t\t: Fit view to show area located between two points"
10709     "\n\t\t: given in world 2D or 3D corrdinates.",
10710     __FILE__, VFitArea, group);
10711   theCommands.Add ("vzfit", "vzfit [scale]\n"
10712     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
10713     "   \"scale\" - specifies factor to scale computed z range.\n",
10714     __FILE__, VZFit, group);
10715   theCommands.Add("vrepaint",
10716             "vrepaint [-immediate]"
10717     "\n\t\t: force redraw",
10718     __FILE__,VRepaint,group);
10719   theCommands.Add("vclear",
10720     "vclear          : vclear"
10721     "\n\t\t: remove all the object from the viewer",
10722     __FILE__,VClear,group);
10723   theCommands.Add("vsetbg",
10724     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
10725     __FILE__,VSetBg,group);
10726   theCommands.Add("vsetbgmode",
10727     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
10728     __FILE__,VSetBgMode,group);
10729   theCommands.Add("vsetgradientbg",
10730     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
10731     __FILE__,VSetGradientBg,group);
10732   theCommands.Add("vsetgrbgmode",
10733     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
10734     __FILE__,VSetGradientBgMode,group);
10735   theCommands.Add("vsetcolorbg",
10736     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
10737     __FILE__,VSetColorBg,group);
10738   theCommands.Add("vsetdefaultbg",
10739     "vsetdefaultbg r g b\n"
10740     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
10741     "\n\t\t: Set default viewer background fill color (flat/gradient).",
10742     __FILE__,VSetDefaultBg,group);
10743   theCommands.Add("vscale",
10744     "vscale          : vscale X Y Z",
10745     __FILE__,VScale,group);
10746   theCommands.Add("vzbufftrihedron",
10747             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
10748     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
10749     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
10750     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
10751     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
10752     "\n\t\t: Displays a trihedron",
10753     __FILE__,VZBuffTrihedron,group);
10754   theCommands.Add("vrotate",
10755     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
10756     "\n                : Option -mouseStart starts rotation according to the mouse position"
10757     "\n                : Option -mouseMove continues rotation with angle computed"
10758     "\n                : from last and new mouse position."
10759     "\n                : vrotate AX AY AZ [X Y Z]",
10760     __FILE__,VRotate,group);
10761   theCommands.Add("vzoom",
10762     "vzoom           : vzoom coef",
10763     __FILE__,VZoom,group);
10764   theCommands.Add("vpan",
10765     "vpan            : vpan dx dy",
10766     __FILE__,VPan,group);
10767   theCommands.Add("vexport",
10768     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
10769     " : exports the view to a vector file of a given format"
10770     " : notice that EMF format requires patched gl2ps",
10771     __FILE__,VExport,group);
10772   theCommands.Add("vcolorscale",
10773     "vcolorscale name [-noupdate|-update] [-demo]"
10774     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
10775     "\n\t\t:       [-font HeightFont=20]"
10776     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
10777     "\n\t\t:       [-smoothTransition {on|off}=off]"
10778     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
10779     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
10780     "\n\t\t:       [-textpos {left|right|center|none}=right]"
10781     "\n\t\t:       [-labelAtBorder {on|off}=on]"
10782     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
10783     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
10784     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
10785     "\n\t\t:       [-xy Left=0 Bottom=0]"
10786     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
10787     "\n\t\t:  -colors   - set colors for all intervals"
10788     "\n\t\t:  -color    - set color for specific interval"
10789     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
10790     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
10791     "\n\t\t:              at border means the value inbetween neighbor intervals,"
10792     "\n\t\t:              at center means the center value within current interval"
10793     "\n\t\t:  -labels   - set labels for all intervals"
10794     "\n\t\t:  -freeLabels - same as -labels but does not require"
10795     "\n\t\t:              matching the number of intervals"
10796     "\n\t\t:  -label    - set label for specific interval"
10797     "\n\t\t:  -title    - set title"
10798     "\n\t\t:  -reversed - setup smooth color transition between intervals"
10799     "\n\t\t:  -smoothTransition - swap colorscale direction"
10800     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
10801     __FILE__, VColorScale, group);
10802   theCommands.Add("vgraduatedtrihedron",
10803     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
10804     "\t[-namefont Name] [-valuesfont Name]\n"
10805     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
10806     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
10807     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
10808     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
10809     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
10810     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
10811     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
10812     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
10813     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
10814     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
10815     " - Displays or erases graduated trihedron"
10816     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
10817     " - namefont - font of axes names. Default: Arial\n"
10818     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
10819     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
10820     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
10821     " - valuesfont - font of axes values. Default: Arial\n"
10822     " - xcolor, ycolor, zcolor - color of axis and values\n"
10823     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
10824     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
10825     __FILE__,VGraduatedTrihedron,group);
10826   theCommands.Add("vtile" ,
10827             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
10828     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
10829     "\n\t\t:  -totalSize the size of virtual bigger viewport"
10830     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
10831     "\n\t\t:  -lowerLeft tile offset as lower left corner"
10832     "\n\t\t:  -upperLeft tile offset as upper left corner",
10833     __FILE__, VTile, group);
10834   theCommands.Add("vzlayer",
10835               "vzlayer [layerId]"
10836       "\n\t\t:         [-add|-delete|-get|-settings]"
10837       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
10838       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
10839       "\n\t\t: ZLayer list management:"
10840       "\n\t\t:   -add      add new z layer to viewer and print its id"
10841       "\n\t\t:   -delete   delete z layer"
10842       "\n\t\t:   -get      print sequence of z layers"
10843       "\n\t\t:   -settings print status of z layer settings"
10844       "\n\t\t:   -disable  disables given setting"
10845       "\n\t\t:   -enable   enables  given setting",
10846     __FILE__,VZLayer,group);
10847   theCommands.Add("vlayerline",
10848     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
10849     __FILE__,VLayerLine,group);
10850   theCommands.Add ("vgrid",
10851     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
10852     " : Mode - rectangular or circular"
10853     " : Type - lines or points",
10854     __FILE__, VGrid, group);
10855   theCommands.Add ("vpriviledgedplane",
10856     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
10857     "\n\t\t:   Ox, Oy, Oz - plane origin"
10858     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
10859     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
10860     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
10861     __FILE__, VPriviledgedPlane, group);
10862   theCommands.Add ("vconvert",
10863     "vconvert v [Mode={window|view}]"
10864     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
10865     "\n\t\t: vconvert x y z [Mode={window|grid}]"
10866     "\n\t\t:   window - convert to window coordinates, pixels"
10867     "\n\t\t:   view   - convert to view projection plane"
10868     "\n\t\t:   grid   - convert to model coordinates, given on grid"
10869     "\n\t\t:   ray    - convert projection ray to model coordiantes"
10870     "\n\t\t: - vconvert v window : convert view to window;"
10871     "\n\t\t: - vconvert v view   : convert window to view;"
10872     "\n\t\t: - vconvert x y window : convert view to window;"
10873     "\n\t\t: - vconvert x y view : convert window to view;"
10874     "\n\t\t: - vconvert x y : convert window to model;"
10875     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
10876     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
10877     "\n\t\t: - vconvert x y z window : convert model to window;"
10878     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
10879     "\n\t\t: Converts the given coordinates to window/view/model space.",
10880     __FILE__, VConvert, group);
10881   theCommands.Add ("vfps",
10882     "vfps [framesNb=100] : estimate average frame rate for active view",
10883     __FILE__, VFps, group);
10884   theCommands.Add ("vgldebug",
10885             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
10886     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
10887     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
10888     "\n\t\t: Debug context can be requested only on Windows"
10889     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
10890     "\n\t\t:  -sync     - request synchronized debug GL context"
10891     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
10892     "\n\t\t:              which are suppressed by default,"
10893     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
10894     "\n\t\t:              which are suppressed by default",
10895     __FILE__, VGlDebug, group);
10896   theCommands.Add ("vvbo",
10897     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
10898     __FILE__, VVbo, group);
10899   theCommands.Add ("vstereo",
10900             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
10901     "\n\t\t:         [-anaglyph Filter]"
10902     "\n\t\t: Control stereo output mode. Available modes for -mode:"
10903     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
10904     "\n\t\t:                     requires driver support."
10905     "\n\t\t:                     Should be called BEFORE vinit!"
10906     "\n\t\t:  anaglyph         - Anaglyph glasses"
10907     "\n\t\t:  rowInterlaced    - row-interlaced display"
10908     "\n\t\t:  columnInterlaced - column-interlaced display"
10909     "\n\t\t:  chessBoard       - chess-board output"
10910     "\n\t\t:  sideBySide       - horizontal pair"
10911     "\n\t\t:  overUnder        - vertical   pair"
10912     "\n\t\t: Available Anaglyph filters for -anaglyph:"
10913     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
10914     "\n\t\t:  greenMagentaSimple",
10915     __FILE__, VStereo, group);
10916   theCommands.Add ("vcaps",
10917             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
10918     "\n\t\t:       [-compatibleProfile {0|1}]"
10919     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
10920     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
10921     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
10922     "\n\t\t: Modify particular graphic driver options:"
10923     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
10924     "\n\t\t:             built-in GLSL programs"
10925     "\n\t\t:            (requires compatible profile)"
10926     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
10927     "\n\t\t:             arrays to GPU memory)"
10928     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
10929     "\n\t\t:  vsync    - switch VSync on or off"
10930     "\n\t\t:  winBuffer - allow using window buffer for rendering"
10931     "\n\t\t: Context creation options:"
10932     "\n\t\t:  softMode          - software OpenGL implementation"
10933     "\n\t\t:  compatibleProfile - backward-compatible profile"
10934     "\n\t\t:  quadbuffer        - QuadBuffer"
10935     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
10936     "\n\t\t: rendering paths producing the same visual result when"
10937     "\n\t\t: possible."
10938     "\n\t\t: Command is intended for testing old hardware compatibility.",
10939     __FILE__, VCaps, group);
10940   theCommands.Add ("vmemgpu",
10941     "vmemgpu [f]: print system-dependent GPU memory information if available;"
10942     " with f option returns free memory in bytes",
10943     __FILE__, VMemGpu, group);
10944   theCommands.Add ("vreadpixel",
10945     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
10946     " : Read pixel value for active view",
10947     __FILE__, VReadPixel, group);
10948   theCommands.Add("diffimage",
10949     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
10950     __FILE__, VDiffImage, group);
10951   theCommands.Add ("vselect",
10952     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
10953     "- emulates different types of selection:\n"
10954     "- 1) single click selection\n"
10955     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
10956     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
10957     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
10958     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
10959     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
10960     " (partial inclusion - overlap - is not allowed by default)\n"
10961     "- 5) any of these selections with shift button pressed",
10962     __FILE__, VSelect, group);
10963   theCommands.Add ("vmoveto",
10964     "vmoveto x y"
10965     "- emulates cursor movement to pixel postion (x,y)",
10966     __FILE__, VMoveTo, group);
10967   theCommands.Add ("vviewparams",
10968               "vviewparams [-args] [-scale [s]]"
10969       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
10970       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
10971       "\n\t\t: Manage current view parameters or prints all"
10972       "\n\t\t: current values when called without argument."
10973       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
10974       "\n\t\t:   -eye  [x y z] prints or sets eye location"
10975       "\n\t\t:   -at   [x y z] prints or sets center of look"
10976       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
10977       "\n\t\t:   -proj [x y z] prints or sets direction of look"
10978       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
10979       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
10980       "\n\t\t:                 or changes the size of its maximum dimension"
10981       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
10982     __FILE__, VViewParams, group);
10983
10984   theCommands.Add("vanimation", "Alias for vanim",
10985     __FILE__, VAnimation, group);
10986
10987   theCommands.Add("vanim",
10988             "List existing animations:"
10989     "\n\t\t:  vanim"
10990     "\n\t\t: Animation playback:"
10991     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
10992     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
10993     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
10994     "\n\t\t:   -freeLook skip camera animations"
10995     "\n\t\t:   -lockLoop disable any interactions"
10996     "\n\t\t:"
10997     "\n\t\t: Animation definition:"
10998     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
10999     "\n\t\t:        [start TimeSec] [duration TimeSec]"
11000     "\n\t\t:"
11001     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
11002     "\n\t\t: specifies nested animations."
11003     "\n\t\t: There is no syntax to explicitly add new animation,"
11004     "\n\t\t: and all non-existing animations within the name will be"
11005     "\n\t\t: implicitly created on first use (including parents)."
11006     "\n\t\t:"
11007     "\n\t\t: Each animation might define the SINGLE action (see below),"
11008     "\n\t\t: like camera transition, object transformation or custom callback."
11009     "\n\t\t: Child animations can be used for defining concurrent actions."
11010     "\n\t\t:"
11011     "\n\t\t: Camera animation:"
11012     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
11013     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
11014     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
11015     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
11016     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
11017     "\n\t\t:   -atX    camera Center positions pair"
11018     "\n\t\t:   -upX    camera Up directions pair"
11019     "\n\t\t:   -scaleX camera Scale factors pair"
11020     "\n\t\t: Object animation:"
11021     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
11022     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
11023     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
11024     "\n\t\t:   -locX   object Location points pair (translation)"
11025     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
11026     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
11027     "\n\t\t: Custom callback:"
11028     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
11029     "\n\t\t:   %Pts        overall animation presentation timestamp"
11030     "\n\t\t:   %LocalPts   local animation timestamp"
11031     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
11032     __FILE__, VAnimation, group);
11033
11034   theCommands.Add("vchangeselected",
11035     "vchangeselected shape"
11036     "- adds to shape to selection or remove one from it",
11037                 __FILE__, VChangeSelected, group);
11038   theCommands.Add ("vnbselected",
11039     "vnbselected"
11040     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
11041   theCommands.Add ("vcamera",
11042               "vcamera [-ortho] [-projtype]"
11043       "\n\t\t:         [-persp]"
11044       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
11045       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
11046       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
11047       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
11048       "\n\t\t: Manage camera parameters."
11049       "\n\t\t: Prints current value when option called without argument."
11050       "\n\t\t: Orthographic camera:"
11051       "\n\t\t:   -ortho      activate orthographic projection"
11052       "\n\t\t: Perspective camera:"
11053       "\n\t\t:   -persp      activate perspective  projection (mono)"
11054       "\n\t\t:   -fovy       field of view in y axis, in degrees"
11055       "\n\t\t:   -distance   distance of eye from camera center"
11056       "\n\t\t: Stereoscopic camera:"
11057       "\n\t\t:   -stereo     perspective  projection (stereo)"
11058       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
11059       "\n\t\t:   -rightEye   perspective  projection (right eye)"
11060       "\n\t\t:   -iod        intraocular distance value"
11061       "\n\t\t:   -iodType    distance type, absolute or relative"
11062       "\n\t\t:   -zfocus     stereographic focus value"
11063       "\n\t\t:   -zfocusType focus type, absolute or relative",
11064     __FILE__, VCamera, group);
11065   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
11066     "- vautozfit [on={1|0}] [scale]\n"
11067     "    Prints or changes parameters of automatic z-fit mode:\n"
11068     "   \"on\" - turns automatic z-fit on or off\n"
11069     "   \"scale\" - specifies factor to scale computed z range.\n",
11070     __FILE__, VAutoZFit, group);
11071   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
11072     "   vzrange                - without parameters shows current values\n"
11073     "   vzrange [znear] [zfar] - applies provided values to view",
11074     __FILE__,VZRange, group);
11075   theCommands.Add ("vpurgedisplay",
11076     "vpurgedisplay"
11077     "- removes structures which don't belong to objects displayed in neutral point",
11078     __FILE__, VPurgeDisplay, group);
11079   theCommands.Add("vsetviewsize",
11080     "vsetviewsize size",
11081     __FILE__,VSetViewSize,group);
11082   theCommands.Add("vmoveview",
11083     "vmoveview Dx Dy Dz [Start = 1|0]",
11084     __FILE__,VMoveView,group);
11085   theCommands.Add("vtranslateview",
11086     "vtranslateview Dx Dy Dz [Start = 1|0)]",
11087     __FILE__,VTranslateView,group);
11088   theCommands.Add("vturnview",
11089     "vturnview Ax Ay Az [Start = 1|0]",
11090     __FILE__,VTurnView,group);
11091   theCommands.Add("vtextureenv",
11092     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
11093     "or user-defined file and optionally applying texture mapping parameters\n"
11094     "                  Usage:\n"
11095     "                  vtextureenv off - disables environment mapping\n"
11096     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
11097     "                              std_texture = (0..7)\n"
11098     "                              rep         = {clamp|repeat}\n"
11099     "                              mod         = {decal|modulate}\n"
11100     "                              flt         = {nearest|bilinear|trilinear}\n"
11101     "                              ss, st      - scale factors for s and t texture coordinates\n"
11102     "                              ts, tt      - translation for s and t texture coordinates\n"
11103     "                              rot         - texture rotation angle in degrees",
11104     __FILE__, VTextureEnv, group);
11105   theCommands.Add("vhlr" ,
11106     "is_enabled={on|off} [show_hidden={1|0}]"
11107     " - Hidden line removal algorithm:"
11108     " - is_enabled: if is on HLR algorithm is applied\n"
11109     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
11110     __FILE__,VHLR,group);
11111   theCommands.Add("vhlrtype" ,
11112     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
11113     " - Changes the type of HLR algorithm using for shapes."
11114     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
11115     "   if equals to polyalgo, polygonal HLR algorithm is applied."
11116     "If shapes are not given HLR algoithm of given type is applied"
11117     " to all shapes in the view\n",
11118     __FILE__,VHLRType,group);
11119   theCommands.Add("vclipplane",
11120               "vclipplane planeName [{0|1}]"
11121       "\n\t\t:   [-equation A B C D]"
11122       "\n\t\t:   [-set|-unset [objects|views]]"
11123       "\n\t\t:   [-maxPlanes]"
11124       "\n\t\t:   [-capping {0|1}]"
11125       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
11126       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
11127       "\n\t\t:       [-texRotate Angle]"
11128       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
11129       "\n\t\t:       [-useObjShader {0|1}]"
11130       "\n\t\t: Clipping planes management:"
11131       "\n\t\t:   -maxPlanes   print plane limit for view"
11132       "\n\t\t:   -delete      delete plane with given name"
11133       "\n\t\t:   {off|on|0|1} turn clipping on/off"
11134       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
11135       "\n\t\t:                applied to active View when list is omitted"
11136       "\n\t\t:   -equation A B C D change plane equation"
11137       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
11138       "\n\t\t: Capping options:"
11139       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
11140       "\n\t\t:   -color R G B          set capping color"
11141       "\n\t\t:   -texName Texture      set capping texture"
11142       "\n\t\t:   -texScale SX SY       set capping tex scale"
11143       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
11144       "\n\t\t:   -texRotate Angle      set capping tex rotation"
11145       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
11146       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
11147       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
11148       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
11149       __FILE__, VClipPlane, group);
11150   theCommands.Add("vdefaults",
11151                "vdefaults [-absDefl value]"
11152        "\n\t\t:           [-devCoeff value]"
11153        "\n\t\t:           [-angDefl value]"
11154        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
11155     , __FILE__, VDefaults, group);
11156   theCommands.Add("vlight",
11157     "tool to manage light sources, without arguments shows list of lights."
11158     "\n    Main commands: "
11159     "\n      'clear' to clear lights"
11160     "\n      '{def}aults' to load deafault lights"
11161     "\n      'add' (or 'new') <type> to add any light source"
11162     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
11163     "\n      'change' <lightId> to edit light source with specified lightId"
11164     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
11165     "\n        {pos}ition X Y Z"
11166     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
11167     "\n        color colorName"
11168     "\n        {head}light 0|1"
11169     "\n        {sm}oothness value"
11170     "\n        {int}ensity value"
11171     "\n        {constAtten}uation value"
11172     "\n        {linearAtten}uation value"
11173     "\n        angle angleDeg"
11174     "\n        {spotexp}onent value"
11175     "\n        local|global"
11176     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
11177     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
11178     __FILE__, VLight, group);
11179   theCommands.Add("vraytrace",
11180             "vraytrace [0|1]"
11181     "\n\t\t: Turns on/off ray-tracing renderer."
11182     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
11183     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
11184     __FILE__, VRenderParams, group);
11185   theCommands.Add("vrenderparams",
11186     "\n    Manages rendering parameters: "
11187     "\n      '-raster'                   Disables GPU ray-tracing"
11188     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
11189     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
11190     "\n      '-rendScale    value        Rendering resolution scale factor"
11191     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
11192     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
11193     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
11194     "\n      '-reflections  on|off'      Enables/disables specular reflections"
11195     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
11196     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
11197     "\n      '-gi           on|off'      Enables/disables global illumination effects"
11198     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
11199     "\n      '-env          on|off'      Enables/disables environment map background"
11200     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
11201     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
11202     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
11203     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
11204     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
11205     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
11206     "\n      '-shadingModel model'       Controls shading model from enumeration"
11207     "\n                                  color, flat, gouraud, phong"
11208     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
11209     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
11210     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
11211     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
11212     "\n    Unlike vcaps, these parameters dramatically change visual properties."
11213     "\n    Command is intended to control presentation quality depending on"
11214     "\n    hardware capabilities and performance.",
11215     __FILE__, VRenderParams, group);
11216   theCommands.Add("vfrustumculling",
11217     "vfrustumculling [toEnable]: enables/disables objects clipping",
11218     __FILE__,VFrustumCulling,group);
11219   theCommands.Add("vhighlightselected",
11220     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
11221     "Without arguments it shows if highlighting of selected objects is enabled now.",
11222     __FILE__,VHighlightSelected,group);
11223   theCommands.Add ("vplace",
11224             "vplace dx dy"
11225     "\n\t\t: Places the point (in pixels) at the center of the window",
11226     __FILE__, VPlace, group);
11227   theCommands.Add("vxrotate",
11228     "vxrotate",
11229     __FILE__,VXRotate,group);
11230
11231     theCommands.Add("vmanipulator",
11232       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
11233       "\n    tool to create and manage AIS manipulators."
11234       "\n    Options: "
11235       "\n      '-attach AISObject'                 attach manipulator to AISObject"
11236       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
11237       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
11238       "\n      '-enableModes    {0|1}'             enable modes when attaching"
11239       "\n      '-detach'                           detach manipulator"
11240       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
11241       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
11242       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
11243       "\n      '-move x y z'                     - move attached object"
11244       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
11245       "\n      '-scale factor'                   - scale attached object"
11246       "\n      '-autoActivate      {0|1}'        - set activation on detection"
11247       "\n      '-followTranslation {0|1}'        - set following translation transform"
11248       "\n      '-followRotation    {0|1}'        - set following rotation transform"
11249       "\n      '-gap value'                      - set gap between sub-parts"
11250       "\n      '-part axis mode    {0|1}'        - set visual part"
11251       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
11252       "\n      '-size value'                     - set size of manipulator"
11253       "\n      '-zoomable {0|1}'                 - set zoom persistence",
11254     __FILE__, VManipulator, group);
11255
11256   theCommands.Add("vselprops",
11257     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
11258     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
11259     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
11260     "\n    -pickStrategy {first|topmost} : defines picking strategy"
11261     "\n                            'first'   to pick first acceptable (default)"
11262     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
11263     "\n    -pixTol    value        : sets up pixel tolerance"
11264     "\n    -dispMode  dispMode     : sets display mode for highlighting"
11265     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
11266     "\n    -color     {name|r g b} : sets highlight color"
11267     "\n    -transp    value        : sets transparency coefficient for highlight"
11268     "\n    -material  material     : sets highlight material"
11269     "\n    -print                  : prints current state of all mentioned parameters",
11270     __FILE__, VSelectionProperties, group);
11271
11272   theCommands.Add ("vseldump",
11273                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
11274                    "\n\t\t: Generate an image based on detection results:"
11275                    "\n\t\t:   depth       normalized depth values"
11276                    "\n\t\t:   unnormDepth unnormalized depth values"
11277                    "\n\t\t:   object      color of detected object"
11278                    "\n\t\t:   owner       color of detected owner"
11279                    "\n\t\t:   selMode     color of selection mode"
11280                    "\n\t\t:   entity      color of etected entity",
11281                    __FILE__, VDumpSelectionImage, group);
11282
11283 #if defined(_WIN32)
11284   theCommands.Add("vprogressive",
11285     "vprogressive",
11286     __FILE__, VProgressiveMode, group);
11287 #endif
11288 }