0028095: Draw Harness, ViewerTest - use RGBA format instead of BGRA within vreadpixel
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_ColorScale.hxx>
23 #include <AIS_Manipulator.hxx>
24 #include <AIS_RubberBand.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_InteractiveObject.hxx>
27 #include <AIS_ListOfInteractive.hxx>
28 #include <AIS_ListIteratorOfListOfInteractive.hxx>
29 #include <DBRep.hxx>
30 #include <Graphic3d_ArrayOfPolylines.hxx>
31 #include <Graphic3d_AspectMarker3d.hxx>
32 #include <Graphic3d_ExportFormat.hxx>
33 #include <Graphic3d_NameOfTextureEnv.hxx>
34 #include <Graphic3d_GraduatedTrihedron.hxx>
35 #include <Graphic3d_TextureEnv.hxx>
36 #include <Graphic3d_TextureParams.hxx>
37 #include <Graphic3d_TypeOfTextureFilter.hxx>
38 #include <Graphic3d_AspectFillArea3d.hxx>
39 #include <ViewerTest.hxx>
40 #include <ViewerTest_AutoUpdater.hxx>
41 #include <ViewerTest_EventManager.hxx>
42 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
43 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_CmdParser.hxx>
45 #include <V3d_AmbientLight.hxx>
46 #include <V3d_DirectionalLight.hxx>
47 #include <V3d_PositionalLight.hxx>
48 #include <V3d_SpotLight.hxx>
49 #include <NCollection_DoubleMap.hxx>
50 #include <NCollection_List.hxx>
51 #include <NCollection_Vector.hxx>
52 #include <AIS_InteractiveContext.hxx>
53 #include <Draw_Interpretor.hxx>
54 #include <Draw.hxx>
55 #include <Draw_Appli.hxx>
56 #include <Image_AlienPixMap.hxx>
57 #include <OpenGl_GraphicDriver.hxx>
58 #include <OSD_Timer.hxx>
59 #include <TColStd_HSequenceOfAsciiString.hxx>
60 #include <TColStd_SequenceOfInteger.hxx>
61 #include <TColStd_HSequenceOfReal.hxx>
62 #include <TColgp_Array1OfPnt2d.hxx>
63 #include <TColStd_MapOfAsciiString.hxx>
64 #include <Aspect_TypeOfLine.hxx>
65 #include <Image_Diff.hxx>
66 #include <Aspect_DisplayConnection.hxx>
67 #include <gp_Pnt.hxx>
68 #include <gp_Dir.hxx>
69 #include <gp_Pln.hxx>
70 #include <PrsMgr_PresentableObject.hxx>
71 #include <Graphic3d_ClipPlane.hxx>
72 #include <NCollection_DataMap.hxx>
73 #include <Graphic3d_Texture2Dmanual.hxx>
74 #include <Prs3d_ShadingAspect.hxx>
75 #include <Prs3d_Drawer.hxx>
76 #include <Prs3d_LineAspect.hxx>
77 #include <Prs3d_Root.hxx>
78
79 #ifdef _WIN32
80 #undef DrawText
81 #endif
82
83 #include <cstdlib>
84
85 #if defined(_WIN32)
86   #include <WNT_WClass.hxx>
87   #include <WNT_Window.hxx>
88 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
89   #include <Cocoa_Window.hxx>
90 #else
91   #include <Xw_Window.hxx>
92   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
93   #include <X11/Xutil.h>
94   #include <tk.h>
95 #endif
96
97 // Auxiliary definitions
98 static const char THE_KEY_DELETE = 127;
99
100 //==============================================================================
101 //  VIEWER GLOBAL VARIABLES
102 //==============================================================================
103
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
106
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
109
110 extern int VErase (Draw_Interpretor& theDI,
111                    Standard_Integer  theArgNb,
112                    const char**      theArgVec);
113
114 #if defined(_WIN32)
115 static Handle(WNT_Window)& VT_GetWindow() {
116   static Handle(WNT_Window) WNTWin;
117   return WNTWin;
118 }
119 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
120 static Handle(Cocoa_Window)& VT_GetWindow()
121 {
122   static Handle(Cocoa_Window) aWindow;
123   return aWindow;
124 }
125 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
126 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
127 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
128
129 #else
130 static Handle(Xw_Window)& VT_GetWindow(){
131   static Handle(Xw_Window) XWWin;
132   return XWWin;
133 }
134
135 static void VProcessEvents(ClientData,int);
136 #endif
137
138 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
139 {
140   static Handle(Aspect_DisplayConnection) aDisplayConnection;
141   return aDisplayConnection;
142 }
143
144 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
145 {
146   GetDisplayConnection() = theDisplayConnection;
147 }
148
149 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
150 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
151 {
152   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
153 #if defined(_WIN32)
154   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156     return aWindow->HWindow();
157 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
158   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
159   if (!aWindow.IsNull())
160   return aWindow->XWindow();
161 #endif
162   return aWindowHandle;
163 }
164 #endif
165
166 static Standard_Boolean MyHLRIsOn = Standard_False;
167
168 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
169 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
170 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
171 static OpenGl_Caps ViewerTest_myDefaultCaps;
172
173 static void OSWindowSetup();
174
175 static struct
176 {
177   Quantity_Color FlatColor;
178   Quantity_Color GradientColor1;
179   Quantity_Color GradientColor2;
180   Aspect_GradientFillMethod FillMethod;
181 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
182
183 //==============================================================================
184 //  EVENT GLOBAL VARIABLES
185 //==============================================================================
186
187 static int Start_Rot = 0;
188 int X_Motion = 0; // Current cursor position
189 int Y_Motion = 0;
190 int X_ButtonPress = 0; // Last ButtonPress position
191 int Y_ButtonPress = 0;
192 Standard_Boolean IsDragged = Standard_False;
193 Standard_Boolean DragFirst = Standard_False;
194 Standard_Boolean TheIsAnimating = Standard_False;
195
196
197 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
198 {
199   static Handle(AIS_RubberBand) aBand;
200   if (aBand.IsNull())
201   {
202     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
203     aBand->SetDisplayMode (0);
204   }
205   return aBand;
206 }
207
208 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
209
210 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
211 {
212   static ViewerTest_MapOfAISManipulators aMap;
213   return aMap;
214 }
215
216 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
217 {
218   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
219   for (; anIt.More(); anIt.Next())
220   {
221     if (anIt.Value()->HasActiveMode())
222     {
223       return anIt.Value();
224     }
225   }
226   return NULL;
227 }
228
229 //==============================================================================
230
231 #ifdef _WIN32
232 static LRESULT WINAPI ViewerWindowProc(
233                                        HWND hwnd,
234                                        UINT uMsg,
235                                        WPARAM wParam,
236                                        LPARAM lParam );
237 static LRESULT WINAPI AdvViewerWindowProc(
238   HWND hwnd,
239   UINT uMsg,
240   WPARAM wParam,
241   LPARAM lParam );
242 #endif
243
244
245 //==============================================================================
246 //function : WClass
247 //purpose  :
248 //==============================================================================
249
250 const Handle(MMgt_TShared)& ViewerTest::WClass()
251 {
252   static Handle(MMgt_TShared) theWClass;
253 #if defined(_WIN32)
254   if (theWClass.IsNull())
255   {
256     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
257       CS_VREDRAW | CS_HREDRAW, 0, 0,
258       ::LoadCursor (NULL, IDC_ARROW));
259   }
260 #endif
261   return theWClass;
262 }
263
264 //==============================================================================
265 //function : CreateName
266 //purpose  : Create numerical name for new object in theMap
267 //==============================================================================
268 template <typename ObjectType>
269 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
270                                     const TCollection_AsciiString& theDefaultString)
271 {
272   if (theObjectMap.IsEmpty())
273     return theDefaultString + TCollection_AsciiString(1);
274
275   Standard_Integer aNextKey = 1;
276   Standard_Boolean isFound = Standard_False;
277   while (!isFound)
278   {
279     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
280     // Look for objects with default names
281     if (theObjectMap.IsBound1(aStringKey))
282     {
283       aNextKey++;
284     }
285     else
286       isFound = Standard_True;
287   }
288
289   return theDefaultString + TCollection_AsciiString(aNextKey);
290 }
291
292 //==============================================================================
293 //structure : ViewerTest_Names
294 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
295 //==============================================================================
296 struct ViewerTest_Names
297 {
298 private:
299   TCollection_AsciiString myDriverName;
300   TCollection_AsciiString myViewerName;
301   TCollection_AsciiString myViewName;
302
303 public:
304
305   const TCollection_AsciiString& GetDriverName () const
306   {
307     return myDriverName;
308   }
309   void SetDriverName (const TCollection_AsciiString& theDriverName)
310   {
311     myDriverName = theDriverName;
312   }
313   const TCollection_AsciiString& GetViewerName () const
314   {
315     return myViewerName;
316   }
317   void SetViewerName (const TCollection_AsciiString& theViewerName)
318   {
319     myViewerName = theViewerName;
320   }
321   const TCollection_AsciiString& GetViewName () const
322   {
323     return myViewName;
324   }
325   void SetViewName (const TCollection_AsciiString& theViewName)
326   {
327     myViewName = theViewName;
328   }
329
330   //===========================================================================
331   //function : Constructor for ViewerTest_Names
332   //purpose  : Get view, viewer, driver names from custom string
333   //===========================================================================
334
335   ViewerTest_Names (const TCollection_AsciiString& theInputString)
336   {
337     TCollection_AsciiString aName(theInputString);
338     if (theInputString.IsEmpty())
339     {
340       // Get current configuration
341       if (ViewerTest_myDrivers.IsEmpty())
342         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
343           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
344       else
345         myDriverName = ViewerTest_myDrivers.Find2
346         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
347
348       if(ViewerTest_myContexts.IsEmpty())
349       {
350         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
351           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
352       }
353       else
354         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
355
356         myViewName = CreateName <Handle(V3d_View)>
357           (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
358     }
359     else
360     {
361       // There is at least view name
362       Standard_Integer aParserNumber = 0;
363       for (Standard_Integer i = 0; i < 3; ++i)
364       {
365         Standard_Integer aParserPos = aName.SearchFromEnd("/");
366         if(aParserPos != -1)
367         {
368           aParserNumber++;
369           aName.Split(aParserPos-1);
370         }
371         else
372           break;
373       }
374       if (aParserNumber == 0)
375       {
376         // Only view name
377         if (!ViewerTest::GetAISContext().IsNull())
378         {
379           myDriverName = ViewerTest_myDrivers.Find2
380           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
381           myViewerName = ViewerTest_myContexts.Find2
382           (ViewerTest::GetAISContext());
383         }
384         else
385         {
386           // There is no opened contexts here, need to create names for viewer and driver
387           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
388             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
389
390           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
391             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
392         }
393         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
394       }
395       else if (aParserNumber == 1)
396       {
397         // Here is viewerName/viewName
398         if (!ViewerTest::GetAISContext().IsNull())
399           myDriverName = ViewerTest_myDrivers.Find2
400           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
401         else
402         {
403           // There is no opened contexts here, need to create name for driver
404           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
405             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
406         }
407         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
408
409         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
410       }
411       else
412       {
413         //Here is driverName/viewerName/viewName
414         myDriverName = TCollection_AsciiString(aName);
415
416         TCollection_AsciiString aViewerName(theInputString);
417         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
418         myViewerName = TCollection_AsciiString(aViewerName);
419
420         myViewName = TCollection_AsciiString(theInputString);
421       }
422     }
423   }
424 };
425
426 //==============================================================================
427 //function : FindContextByView
428 //purpose  : Find AIS_InteractiveContext by View
429 //==============================================================================
430
431 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
432 {
433   Handle(AIS_InteractiveContext) anAISContext;
434
435   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
436        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
437   {
438     if (anIter.Value()->CurrentViewer() == theView->Viewer())
439        return anIter.Key2();
440   }
441   return anAISContext;
442 }
443
444
445 //==============================================================================
446 //function : SetWindowTitle
447 //purpose  : Set window title
448 //==============================================================================
449
450 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
451                      Standard_CString theTitle)
452 {
453 #if defined(_WIN32)
454   SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
455     theTitle);
456 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
457   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
458 #else
459   if(GetDisplayConnection()->GetDisplay())
460   {
461     Window aWindow =
462       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
463     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
464   }
465 #endif
466 }
467
468 //==============================================================================
469 //function : IsWindowOverlapped
470 //purpose  : Check if theWindow overlapp another view
471 //==============================================================================
472
473 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
474                                      const Standard_Integer thePxTop,
475                                      const Standard_Integer thePxRight,
476                                      const Standard_Integer thePxBottom,
477                                      TCollection_AsciiString& theViewId)
478 {
479   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
480       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
481   {
482     Standard_Integer aTop = 0,
483       aLeft = 0,
484       aRight = 0,
485       aBottom = 0;
486     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
487     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
488         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
489         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
490         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
491     {
492       theViewId = anIter.Key1();
493       return Standard_True;
494     }
495   }
496   return Standard_False;
497 }
498
499 // Workaround: to create and delete non-orthographic views outside ViewerTest
500 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
501 {
502   ViewerTest_myViews.UnBind1 (theName);
503 }
504
505 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
506                                const Handle(V3d_View)& theView)
507 {
508   ViewerTest_myViews.Bind (theName, theView);
509 }
510
511 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
512 {
513   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
514 }
515 //==============================================================================
516 //function : ViewerInit
517 //purpose  : Create the window viewer and initialize all the global variable
518 //==============================================================================
519
520 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
521                                                 const Standard_Integer thePxTop,
522                                                 const Standard_Integer thePxWidth,
523                                                 const Standard_Integer thePxHeight,
524                                                 Standard_CString theViewName,
525                                                 Standard_CString theDisplayName)
526 {
527   // Default position and dimension of the viewer window.
528   // Note that left top corner is set to be sufficiently small to have
529   // window fit in the small screens (actual for remote desktops, see #23003).
530   // The position corresponds to the window's client area, thus some
531   // gap is added for window frame to be visible.
532   Standard_Integer aPxLeft   = 20;
533   Standard_Integer aPxTop    = 40;
534   Standard_Integer aPxWidth  = 409;
535   Standard_Integer aPxHeight = 409;
536   Standard_Boolean toCreateViewer = Standard_False;
537
538   Handle(OpenGl_GraphicDriver) aGraphicDriver;
539   ViewerTest_Names aViewNames(theViewName);
540   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
541     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
542
543   if (thePxLeft != 0)
544     aPxLeft = thePxLeft;
545   if (thePxTop != 0)
546     aPxTop = thePxTop;
547   if (thePxWidth != 0)
548     aPxWidth = thePxWidth;
549   if (thePxHeight != 0)
550     aPxHeight = thePxHeight;
551
552   // Get graphic driver (create it or get from another view)
553   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
554   {
555     // Get connection string
556   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
557     TCollection_AsciiString aDisplayName(theDisplayName);
558     if (!aDisplayName.IsEmpty())
559       SetDisplayConnection (new Aspect_DisplayConnection ());
560     else
561       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
562   #else
563     (void)theDisplayName; // avoid warning on unused argument
564     SetDisplayConnection (new Aspect_DisplayConnection ());
565   #endif
566
567     if (Draw_VirtualWindows)
568     {
569       // don't waste the time waiting for VSync when window is not displayed on the screen
570       ViewerTest_myDefaultCaps.swapInterval = 0;
571       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
572       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
573     }
574     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
575     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
576
577     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
578     toCreateViewer = Standard_True;
579   }
580   else
581   {
582     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
583   }
584
585   //Dispose the window if input parameters are default
586   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
587   {
588     Standard_Integer aTop = 0,
589                      aLeft = 0,
590                      aRight = 0,
591                      aBottom = 0,
592                      aScreenWidth = 0,
593                      aScreenHeight = 0;
594
595     // Get screen resolution
596 #if defined(_WIN32) || defined(__WIN32__)
597     RECT aWindowSize;
598     GetClientRect(GetDesktopWindow(), &aWindowSize);
599     aScreenHeight = aWindowSize.bottom;
600     aScreenWidth = aWindowSize.right;
601 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
602     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
603 #else
604     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
605     aScreenWidth = WidthOfScreen(aScreen);
606     aScreenHeight = HeightOfScreen(aScreen);
607 #endif
608
609     TCollection_AsciiString anOverlappedViewId("");
610
611     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
612     {
613       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
614
615       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
616         && aRight + 2*aPxWidth + 40 > aScreenWidth)
617       {
618         if (aBottom + aPxHeight + 40 > aScreenHeight)
619         {
620           aPxLeft = 20;
621           aPxTop = 40;
622           break;
623         }
624         aPxLeft = 20;
625         aPxTop = aBottom + 40;
626       }
627       else
628         aPxLeft = aRight + 20;
629     }
630   }
631
632   // Get viewer name
633   TCollection_AsciiString aTitle("3D View - ");
634   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
635
636   // Change name of current active window
637   if (!ViewerTest::CurrentView().IsNull())
638   {
639     TCollection_AsciiString anActiveWindowTitle("3D View - ");
640     anActiveWindowTitle = anActiveWindowTitle
641       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
642     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
643   }
644
645   // Create viewer
646   Handle(V3d_Viewer) a3DViewer;
647   // If it's the single view, we first look for empty context
648   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
649   {
650     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
651       anIter(ViewerTest_myContexts);
652     if (anIter.More())
653       ViewerTest::SetAISContext (anIter.Value());
654     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
655   }
656   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
657   {
658     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
659     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
660   }
661   else if (a3DViewer.IsNull())
662   {
663     toCreateViewer = Standard_True;
664     a3DViewer = new V3d_Viewer(aGraphicDriver);
665     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
666     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
667                                            ViewerTest_DefaultBackground.GradientColor2,
668                                            ViewerTest_DefaultBackground.FillMethod);
669   }
670
671   // AIS context setup
672   if (ViewerTest::GetAISContext().IsNull() ||
673       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
674   {
675     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
676     ViewerTest::SetAISContext (aContext);
677     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
678   }
679   else
680   {
681     ViewerTest::ResetEventManager();
682   }
683
684   // Create window
685 #if defined(_WIN32)
686   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
687                                     Handle(WNT_WClass)::DownCast (WClass()),
688                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
689                                     aPxLeft, aPxTop,
690                                     aPxWidth, aPxHeight,
691                                     Quantity_NOC_BLACK);
692 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
693   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
694                                      aPxLeft, aPxTop,
695                                      aPxWidth, aPxHeight);
696   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
697 #else
698   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
699                                   aTitle.ToCString(),
700                                   aPxLeft, aPxTop,
701                                   aPxWidth, aPxHeight);
702 #endif
703   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
704
705   // View setup
706   Handle(V3d_View) aView = a3DViewer->CreateView();
707   aView->SetWindow (VT_GetWindow());
708   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
709
710   ViewerTest::CurrentView(aView);
711   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
712
713   // Setup for X11 or NT
714   OSWindowSetup();
715
716   // Set parameters for V3d_View and V3d_Viewer
717   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
718   aV3dView->SetComputedMode(Standard_False);
719   MyHLRIsOn = aV3dView->ComputedMode();
720
721   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
722   if (toCreateViewer)
723   {
724     a3DViewer->SetDefaultLights();
725     a3DViewer->SetLightOn();
726   }
727
728   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
729   #if TCL_MAJOR_VERSION  < 8
730   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
731       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
732   #else
733   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
734       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
735   #endif
736   #endif
737
738   VT_GetWindow()->Map();
739
740   // Set the handle of created view in the event manager
741   ViewerTest::ResetEventManager();
742
743   ViewerTest::CurrentView()->Redraw();
744
745   aView.Nullify();
746   a3DViewer.Nullify();
747
748   return aViewNames.GetViewName();
749 }
750
751 //==============================================================================
752 //function : RedrawAllViews
753 //purpose  : Redraw all created views
754 //==============================================================================
755 void ViewerTest::RedrawAllViews()
756 {
757   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
758   for (; aViewIt.More(); aViewIt.Next())
759   {
760     const Handle(V3d_View)& aView = aViewIt.Key2();
761     aView->Redraw();
762   }
763 }
764
765 //==============================================================================
766 //function : Vinit
767 //purpose  : Create the window viewer and initialize all the global variable
768 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
769 //==============================================================================
770
771 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
772 {
773   if (theArgsNb > 9)
774   {
775     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
776               << "Type help for more information.\n";
777     return 1;
778   }
779
780   TCollection_AsciiString aViewName, aDisplayName;
781   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
782   TCollection_AsciiString aName, aValue;
783   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
784   {
785     const TCollection_AsciiString anArg = theArgVec[anArgIt];
786     TCollection_AsciiString anArgCase = anArg;
787     anArgCase.UpperCase();
788     if (ViewerTest::SplitParameter (anArg, aName, aValue))
789     {
790       aName.UpperCase();
791       if (aName.IsEqual ("NAME"))
792       {
793         aViewName = aValue;
794       }
795       else if (aName.IsEqual ("L")
796             || aName.IsEqual ("LEFT"))
797       {
798         aPxLeft = aValue.IntegerValue();
799       }
800       else if (aName.IsEqual ("T")
801             || aName.IsEqual ("TOP"))
802       {
803         aPxTop = aValue.IntegerValue();
804       }
805     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
806       else if (aName.IsEqual ("DISP")
807             || aName.IsEqual ("DISPLAY"))
808       {
809         aDisplayName = aValue;
810       }
811     #endif
812       else if (aName.IsEqual ("W")
813             || aName.IsEqual ("WIDTH"))
814       {
815         aPxWidth = aValue.IntegerValue();
816       }
817       else if (aName.IsEqual ("H")
818             || aName.IsEqual ("HEIGHT"))
819       {
820         aPxHeight = aValue.IntegerValue();
821       }
822       else
823       {
824         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
825       }
826     }
827     else if (aViewName.IsEmpty())
828     {
829       aViewName = anArg;
830     }
831     else
832     {
833       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
834     }
835   }
836
837   ViewerTest_Names aViewNames (aViewName);
838   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
839   {
840     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
841     theDi.Eval (aCommand.ToCString());
842     return 0;
843   }
844
845   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
846                                                             aViewName.ToCString(),
847                                                             aDisplayName.ToCString());
848   theDi << aViewId;
849   return 0;
850 }
851
852 //==============================================================================
853 //function : VHLR
854 //purpose  : hidden lines removal algorithm
855 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
856 //==============================================================================
857
858 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
859 {
860   if (ViewerTest::CurrentView().IsNull())
861   {
862     di << argv[0] << ": Call vinit before this command, please.\n";
863     return 1;
864   }
865
866   if (argc < 2)
867   {
868     di << argv[0] << ": Wrong number of command arguments.\n"
869       << "Type help " << argv[0] << " for more information.\n";
870     return 1;
871   }
872
873   // Enable or disable HLR mode.
874   Standard_Boolean isHLROn =
875     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
876
877   if (isHLROn != MyHLRIsOn)
878   {
879     MyHLRIsOn = isHLROn;
880     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
881   }
882
883   // Show or hide hidden lines in HLR mode.
884   Standard_Boolean isCurrentShowHidden
885     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
886
887   Standard_Boolean isShowHidden =
888     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
889                 : isCurrentShowHidden;
890
891
892   if (isShowHidden != isCurrentShowHidden)
893   {
894     if (isShowHidden)
895     {
896       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
897     }
898     else
899     {
900       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
901     }
902
903     // Redisplay shapes.
904     if (MyHLRIsOn)
905     {
906       AIS_ListOfInteractive aListOfShapes;
907       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
908
909       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
910       {
911         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
912         if (aShape.IsNull())
913         {
914           continue;
915         }
916         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
917       }
918     }
919   }
920
921   ViewerTest::CurrentView()->Update();
922   return 0;
923 }
924
925 //==============================================================================
926 //function : VHLRType
927 //purpose  : change type of using HLR algorithm
928 //==============================================================================
929
930 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
931 {
932   if (ViewerTest::CurrentView().IsNull())
933   {
934     di << argv[0] << ": Call vinit before this command, please.\n";
935     return 1;
936   }
937
938   if (argc < 2)
939   {
940     di << argv[0] << ": Wrong number of command arguments.\n"
941       << "Type help " << argv[0] << " for more information.\n";
942     return 1;
943   }
944
945   Prs3d_TypeOfHLR aTypeOfHLR =
946     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
947
948   if (argc == 2)
949   {
950     AIS_ListOfInteractive aListOfShapes;
951     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
952     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
953     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
954       anIter.More(); anIter.Next())
955     {
956       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
957       if (aShape.IsNull())
958         continue;
959       if (aShape->TypeOfHLR() != aTypeOfHLR)
960         aShape->SetTypeOfHLR (aTypeOfHLR);
961       if (MyHLRIsOn)
962         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
963     }
964     ViewerTest::CurrentView()->Update();
965     return 0;
966   }
967   else
968   {
969     for (Standard_Integer i = 2; i < argc; ++i)
970     {
971       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
972       TCollection_AsciiString aName (argv[i]);
973
974       if (!aMap.IsBound2 (aName))
975       {
976         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
977         continue;
978       }
979       Handle(AIS_Shape) anAISObject =
980         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
981       if (anAISObject.IsNull())
982         continue;
983       anAISObject->SetTypeOfHLR (aTypeOfHLR);
984       if (MyHLRIsOn)
985         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
986     }
987     ViewerTest::CurrentView()->Update();
988   }
989
990   return 0;
991 }
992
993 //==============================================================================
994 //function : FindViewIdByWindowHandle
995 //purpose  : Find theView Id in the map of views by window handle
996 //==============================================================================
997 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
998 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
999 {
1000   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1001        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1002   {
1003     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1004     if (aWindowHandle == theWindowHandle)
1005       return anIter.Key1();
1006   }
1007   return TCollection_AsciiString("");
1008 }
1009 #endif
1010
1011 //==============================================================================
1012 //function : ActivateView
1013 //purpose  : Make the view active
1014 //==============================================================================
1015
1016 void ActivateView (const TCollection_AsciiString& theViewName)
1017 {
1018   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1019   if (!aView.IsNull())
1020   {
1021     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1022     if (!anAISContext.IsNull())
1023     {
1024       if (!ViewerTest::CurrentView().IsNull())
1025       {
1026         TCollection_AsciiString aTitle("3D View - ");
1027         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1028         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1029       }
1030
1031       ViewerTest::CurrentView (aView);
1032       // Update degenerate mode
1033       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1034       ViewerTest::SetAISContext (anAISContext);
1035       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1036       aTitle = aTitle + theViewName + "(*)";
1037       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1038 #if defined(_WIN32) || defined(__WIN32__)
1039       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1040 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1041       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1042 #else
1043       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1044 #endif
1045       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1046       ViewerTest::CurrentView()->Redraw();
1047     }
1048   }
1049 }
1050
1051 //==============================================================================
1052 //function : RemoveView
1053 //purpose  :
1054 //==============================================================================
1055 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1056                              const Standard_Boolean  theToRemoveContext)
1057 {
1058   if (!ViewerTest_myViews.IsBound2 (theView))
1059   {
1060     return;
1061   }
1062
1063   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1064   RemoveView (aViewName, theToRemoveContext);
1065 }
1066
1067 //==============================================================================
1068 //function : RemoveView
1069 //purpose  : Close and remove view from display, clear maps if neccessary
1070 //==============================================================================
1071 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1072 {
1073   if (!ViewerTest_myViews.IsBound1(theViewName))
1074   {
1075     cout << "Wrong view name\n";
1076     return;
1077   }
1078
1079   // Activate another view if it's active now
1080   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1081   {
1082     if (ViewerTest_myViews.Extent() > 1)
1083     {
1084       TCollection_AsciiString aNewViewName;
1085       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
1086            anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1087         if (anIter.Key1() != theViewName)
1088         {
1089           aNewViewName = anIter.Key1();
1090           break;
1091         }
1092         ActivateView (aNewViewName);
1093     }
1094     else
1095     {
1096       Handle(V3d_View) anEmptyView;
1097 #if defined(_WIN32) || defined(__WIN32__)
1098       Handle(WNT_Window) anEmptyWindow;
1099 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1100       Handle(Cocoa_Window) anEmptyWindow;
1101 #else
1102       Handle(Xw_Window) anEmptyWindow;
1103 #endif
1104       VT_GetWindow() = anEmptyWindow;
1105       ViewerTest::CurrentView (anEmptyView);
1106       if (isContextRemoved)
1107       {
1108         Handle(AIS_InteractiveContext) anEmptyContext;
1109         ViewerTest::SetAISContext(anEmptyContext);
1110       }
1111     }
1112   }
1113
1114   // Delete view
1115   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1116   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1117
1118   // Remove view resources
1119   ViewerTest_myViews.UnBind1(theViewName);
1120   aView->Remove();
1121
1122 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1123   XFlush (GetDisplayConnection()->GetDisplay());
1124 #endif
1125
1126   // Keep context opened only if the closed view is last to avoid
1127   // unused empty contexts
1128   if (!aCurrentContext.IsNull())
1129   {
1130     // Check if there are more difined views in the viewer
1131     aCurrentContext->CurrentViewer()->InitDefinedViews();
1132     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1133     {
1134       // Remove driver if there is no viewers that use it
1135       Standard_Boolean isRemoveDriver = Standard_True;
1136       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1137           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1138       {
1139         if (aCurrentContext != anIter.Key2() &&
1140           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1141         {
1142           isRemoveDriver = Standard_False;
1143           break;
1144         }
1145       }
1146
1147       aCurrentContext->RemoveAll (Standard_False);
1148       if(isRemoveDriver)
1149       {
1150         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1151       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1152         #if TCL_MAJOR_VERSION  < 8
1153         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1154         #else
1155         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1156         #endif
1157       #endif
1158       }
1159
1160       ViewerTest_myContexts.UnBind2(aCurrentContext);
1161     }
1162   }
1163   cout << "3D View - " << theViewName << " was deleted.\n";
1164
1165 }
1166
1167 //==============================================================================
1168 //function : VClose
1169 //purpose  : Remove the view defined by its name
1170 //==============================================================================
1171
1172 static int VClose (Draw_Interpretor& /*theDi*/,
1173                    Standard_Integer  theArgsNb,
1174                    const char**      theArgVec)
1175 {
1176   NCollection_List<TCollection_AsciiString> aViewList;
1177   if (theArgsNb > 1)
1178   {
1179     TCollection_AsciiString anArg (theArgVec[1]);
1180     anArg.UpperCase();
1181     if (anArg.IsEqual ("ALL")
1182      || anArg.IsEqual ("*"))
1183     {
1184       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1185            anIter.More(); anIter.Next())
1186       {
1187         aViewList.Append (anIter.Key1());
1188       }
1189       if (aViewList.IsEmpty())
1190       {
1191         std::cout << "No view to close\n";
1192         return 0;
1193       }
1194     }
1195     else
1196     {
1197       ViewerTest_Names aViewName (theArgVec[1]);
1198       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1199       {
1200         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1201         return 1;
1202       }
1203       aViewList.Append (aViewName.GetViewName());
1204     }
1205   }
1206   else
1207   {
1208     // close active view
1209     if (ViewerTest::CurrentView().IsNull())
1210     {
1211       std::cerr << "No active view!\n";
1212       return 1;
1213     }
1214     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1215   }
1216
1217   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1218   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1219        anIter.More(); anIter.Next())
1220   {
1221     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1222   }
1223
1224   return 0;
1225 }
1226
1227 //==============================================================================
1228 //function : VActivate
1229 //purpose  : Activate the view defined by its ID
1230 //==============================================================================
1231
1232 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1233 {
1234   if (theArgsNb > 2)
1235   {
1236     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1237     << "Usage: " << theArgVec[0] << " ViewID\n";
1238     return 1;
1239   }
1240   if(theArgsNb == 1)
1241   {
1242     theDi.Eval("vviewlist");
1243     return 0;
1244   }
1245
1246   TCollection_AsciiString aNameString(theArgVec[1]);
1247   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1248   {
1249     TCollection_AsciiString aTitle("3D View - ");
1250     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1251     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1252     Handle(V3d_View) anEmptyView;
1253 #if defined(_WIN32) || defined(__WIN32__)
1254     Handle(WNT_Window) anEmptyWindow;
1255 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1256     Handle(Cocoa_Window) anEmptyWindow;
1257 #else
1258     Handle(Xw_Window) anEmptyWindow;
1259 #endif
1260     VT_GetWindow() = anEmptyWindow;
1261     ViewerTest::CurrentView (anEmptyView);
1262     ViewerTest::ResetEventManager();
1263     theDi << theArgVec[0] << ": all views are inactive\n";
1264     return 0;
1265   }
1266
1267   ViewerTest_Names aViewNames(aNameString);
1268
1269   // Check if this view exists in the viewer with the driver
1270   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1271   {
1272     theDi << "Wrong view name\n";
1273     return 1;
1274   }
1275
1276   // Check if it is active already
1277   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1278   {
1279     theDi << theArgVec[0] << ": the view is active already\n";
1280     return 0;
1281   }
1282
1283   ActivateView (aViewNames.GetViewName());
1284   return 0;
1285 }
1286
1287 //==============================================================================
1288 //function : VViewList
1289 //purpose  : Print current list of views per viewer and graphic driver ID
1290 //           shared between viewers
1291 //==============================================================================
1292
1293 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1294 {
1295   if (theArgsNb > 2)
1296   {
1297     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1298           << "Usage: " << theArgVec[0] << " name";
1299     return 1;
1300   }
1301   if (ViewerTest_myContexts.Size() < 1)
1302     return 0;
1303
1304   Standard_Boolean isTreeView =
1305     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1306
1307   if (isTreeView)
1308     theDi << theArgVec[0] <<":\n";
1309
1310     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
1311       aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
1312     {
1313       if (isTreeView)
1314         theDi << aDriverIter.Key1() << ":\n";
1315
1316       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1317         aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1318       {
1319         if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1320         {
1321           if (isTreeView)
1322           {
1323             TCollection_AsciiString aContextName(aContextIter.Key1());
1324             theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1325           }
1326
1327           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1328             aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
1329           {
1330             if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1331             {
1332               TCollection_AsciiString aViewName(aViewIter.Key1());
1333               if (isTreeView)
1334               {
1335                 if (aViewIter.Value() == ViewerTest::CurrentView())
1336                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1337                 else
1338                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1339               }
1340               else
1341               {
1342                 theDi << aViewName << " ";
1343               }
1344             }
1345           }
1346         }
1347       }
1348     }
1349   return 0;
1350 }
1351
1352 //==============================================================================
1353 //function : VT_ProcessKeyPress
1354 //purpose  : Handle KeyPress event from a CString
1355 //==============================================================================
1356 void VT_ProcessKeyPress (const char* buf_ret)
1357 {
1358   //cout << "KeyPress" << endl;
1359   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1360   // Letter in alphabetic order
1361
1362   if (!strcasecmp (buf_ret, "A"))
1363   {
1364     // AXO
1365     aView->SetProj(V3d_XposYnegZpos);
1366   }
1367   else if (!strcasecmp (buf_ret, "D"))
1368   {
1369     // Reset
1370     aView->Reset();
1371   }
1372   else if (!strcasecmp (buf_ret, "F"))
1373   {
1374     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1375     {
1376       ViewerTest::GetAISContext()->FitSelected (aView);
1377     }
1378     else
1379     {
1380       // FitAll
1381       aView->FitAll();
1382     }
1383   }
1384   else if (!strcasecmp (buf_ret, "H"))
1385   {
1386     // HLR
1387     cout << "HLR" << endl;
1388     aView->SetComputedMode (!aView->ComputedMode());
1389     MyHLRIsOn = aView->ComputedMode();
1390   }
1391   else if (!strcasecmp (buf_ret, "P"))
1392   {
1393     // Type of HLR
1394     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1395     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1396       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1397     else
1398       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1399     if (aContext->NbSelected()==0)
1400     {
1401       AIS_ListOfInteractive aListOfShapes;
1402       aContext->DisplayedObjects(aListOfShapes);
1403       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1404         anIter.More(); anIter.Next())
1405       {
1406         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1407         if (aShape.IsNull())
1408           continue;
1409         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1410           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1411         else
1412           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1413         aContext->Redisplay (aShape, Standard_False);
1414       }
1415     }
1416     else
1417     {
1418       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1419       {
1420         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1421         if (aShape.IsNull())
1422           continue;
1423         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1424           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1425         else
1426           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1427         aContext->Redisplay (aShape, Standard_False);
1428       }
1429     }
1430
1431     aContext->UpdateCurrentViewer();
1432
1433   }
1434   else if (!strcasecmp (buf_ret, "S"))
1435   {
1436     std::cout << "setup Shaded display mode" << std::endl;
1437
1438     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1439     if(Ctx->NbSelected()==0)
1440       Ctx->SetDisplayMode(AIS_Shaded);
1441     else{
1442       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1443         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1444       Ctx->UpdateCurrentViewer();
1445     }
1446   }
1447   else if (!strcasecmp (buf_ret, "U"))
1448   {
1449     // Unset display mode
1450     std::cout << "reset display mode to defaults" << std::endl;
1451
1452     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1453     if(Ctx->NbSelected()==0)
1454       Ctx->SetDisplayMode(AIS_WireFrame);
1455     else{
1456       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1457         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1458       Ctx->UpdateCurrentViewer();
1459     }
1460
1461   }
1462   else if (!strcasecmp (buf_ret, "T"))
1463   {
1464     // Top
1465     aView->SetProj(V3d_Zpos);
1466   }
1467   else if (!strcasecmp (buf_ret, "B"))
1468   {
1469     // Bottom
1470     aView->SetProj(V3d_Zneg);
1471   }
1472   else if (!strcasecmp (buf_ret, "L"))
1473   {
1474     // Left
1475     aView->SetProj(V3d_Xneg);
1476   }
1477   else if (!strcasecmp (buf_ret, "R"))
1478   {
1479     // Right
1480     aView->SetProj(V3d_Xpos);
1481   }
1482   else if (!strcasecmp (buf_ret, "W"))
1483   {
1484     std::cout << "setup WireFrame display mode" << std::endl;
1485     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1486     if(Ctx->NbSelected()==0)
1487       Ctx->SetDisplayMode(AIS_WireFrame);
1488     else{
1489       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1490         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1491       Ctx->UpdateCurrentViewer();
1492     }
1493   }
1494   else if (!strcasecmp (buf_ret, ","))
1495   {
1496     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1497   }
1498   else if (!strcasecmp (buf_ret, "."))
1499   {
1500     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1501   }
1502   else if (!strcasecmp (buf_ret, "/"))
1503   {
1504     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1505     if (aCamera->IsStereo())
1506     {
1507       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1508       aView->Redraw();
1509     }
1510   }
1511   else if (!strcasecmp (buf_ret, "*"))
1512   {
1513     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1514     if (aCamera->IsStereo())
1515     {
1516       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1517       aView->Redraw();
1518     }
1519   }
1520   else if (*buf_ret == THE_KEY_DELETE)
1521   {
1522     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1523     if (!aCtx.IsNull()
1524      && aCtx->NbSelected() > 0)
1525     {
1526       Draw_Interprete ("verase");
1527     }
1528   }
1529   else
1530   {
1531     // Number
1532     Standard_Integer Num = Draw::Atoi(buf_ret);
1533     if(Num>=0 && Num<=7)
1534       ViewerTest::StandardModeActivation(Num);
1535   }
1536 }
1537
1538 //==============================================================================
1539 //function : VT_ProcessExpose
1540 //purpose  : Redraw the View on an Expose Event
1541 //==============================================================================
1542 void VT_ProcessExpose()
1543 {
1544   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1545   if (!aView3d.IsNull())
1546   {
1547     aView3d->Redraw();
1548   }
1549 }
1550
1551 //==============================================================================
1552 //function : VT_ProcessConfigure
1553 //purpose  : Resize the View on an Configure Event
1554 //==============================================================================
1555 void VT_ProcessConfigure()
1556 {
1557   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1558   if (aView3d.IsNull())
1559   {
1560     return;
1561   }
1562
1563   aView3d->MustBeResized();
1564   aView3d->Update();
1565   aView3d->Redraw();
1566 }
1567
1568 //==============================================================================
1569 //function : VT_ProcessButton1Press
1570 //purpose  : Picking
1571 //==============================================================================
1572 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1573                                          const char**     theArgVec,
1574                                          Standard_Boolean theToPick,
1575                                          Standard_Boolean theIsShift)
1576 {
1577   if (TheIsAnimating)
1578   {
1579     TheIsAnimating = Standard_False;
1580     return Standard_False;
1581   }
1582
1583   if (theToPick)
1584   {
1585     Standard_Real X, Y, Z;
1586     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1587
1588     Draw::Set (theArgVec[1], X);
1589     Draw::Set (theArgVec[2], Y);
1590     Draw::Set (theArgVec[3], Z);
1591   }
1592
1593   if (theIsShift)
1594   {
1595     ViewerTest::CurrentEventManager()->ShiftSelect();
1596   }
1597   else
1598   {
1599     ViewerTest::CurrentEventManager()->Select();
1600   }
1601
1602   return Standard_False;
1603 }
1604
1605 //==============================================================================
1606 //function : VT_ProcessButton1Release
1607 //purpose  : End selecting
1608 //==============================================================================
1609 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1610 {
1611   if (IsDragged)
1612   {
1613     IsDragged = Standard_False;
1614     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1615     if (theIsShift)
1616     {
1617       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1618                        X_Motion, Y_Motion);
1619     }
1620     else
1621     {
1622       EM->Select (X_ButtonPress, Y_ButtonPress,
1623                   X_Motion, Y_Motion);
1624     }
1625   }
1626 }
1627
1628 //==============================================================================
1629 //function : VT_ProcessButton3Press
1630 //purpose  : Start Rotation
1631 //==============================================================================
1632 void VT_ProcessButton3Press()
1633 {
1634   Start_Rot = 1;
1635   if (MyHLRIsOn)
1636   {
1637     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1638   }
1639   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1640 }
1641
1642 //==============================================================================
1643 //function : VT_ProcessButton3Release
1644 //purpose  : End rotation
1645 //==============================================================================
1646 void VT_ProcessButton3Release()
1647 {
1648   if (Start_Rot)
1649   {
1650     Start_Rot = 0;
1651     if (MyHLRIsOn)
1652     {
1653       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1654     }
1655   }
1656 }
1657
1658 //==============================================================================
1659 //function : ProcessControlButton1Motion
1660 //purpose  : Zoom
1661 //==============================================================================
1662
1663 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1664 static void ProcessControlButton1Motion()
1665 {
1666   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1667
1668   X_ButtonPress = X_Motion;
1669   Y_ButtonPress = Y_Motion;
1670 }
1671 #endif
1672
1673 //==============================================================================
1674 //function : VT_ProcessControlButton2Motion
1675 //purpose  : Panning
1676 //==============================================================================
1677 void VT_ProcessControlButton2Motion()
1678 {
1679   Standard_Integer aDx = X_Motion - X_ButtonPress;
1680   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1681
1682   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1683
1684   ViewerTest::CurrentView()->Pan (aDx, aDy);
1685
1686   X_ButtonPress = X_Motion;
1687   Y_ButtonPress = Y_Motion;
1688 }
1689
1690 //==============================================================================
1691 //function : VT_ProcessControlButton3Motion
1692 //purpose  : Rotation
1693 //==============================================================================
1694 void VT_ProcessControlButton3Motion()
1695 {
1696   if (Start_Rot)
1697   {
1698     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1699   }
1700 }
1701
1702 //==============================================================================
1703 //function : VT_ProcessMotion
1704 //purpose  :
1705 //==============================================================================
1706 void VT_ProcessMotion()
1707 {
1708   //pre-hilights detected objects at mouse position
1709
1710   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1711   EM->MoveTo(X_Motion, Y_Motion);
1712 }
1713
1714
1715 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1716 {
1717   Xpix = X_Motion;Ypix=Y_Motion;
1718 }
1719
1720 //==============================================================================
1721 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1722 //purpose  : Switches to an axonometric, top, left and other views
1723 //==============================================================================
1724
1725 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1726 {
1727   if ( ViewerTest::CurrentView().IsNull() )
1728   {
1729     di<<"Call vinit before this command, please\n";
1730     return 1;
1731   }
1732
1733   ViewerTest::CurrentView()->SetProj(ori);
1734   return 0;
1735 }
1736
1737 //==============================================================================
1738 //function : VAxo
1739 //purpose  : Switch to an Axonometric view
1740 //Draw arg : No args
1741 //==============================================================================
1742
1743 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1744 {
1745   return ViewProject(di, V3d_XposYnegZpos);
1746 }
1747
1748 //==============================================================================
1749 //function : VTop
1750 //purpose  : Switch to a Top View
1751 //Draw arg : No args
1752 //==============================================================================
1753
1754 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1755 {
1756   return ViewProject(di, V3d_Zpos);
1757 }
1758
1759 //==============================================================================
1760 //function : VBottom
1761 //purpose  : Switch to a Bottom View
1762 //Draw arg : No args
1763 //==============================================================================
1764
1765 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1766 {
1767   return ViewProject(di, V3d_Zneg);
1768 }
1769
1770 //==============================================================================
1771 //function : VLeft
1772 //purpose  : Switch to a Left View
1773 //Draw arg : No args
1774 //==============================================================================
1775
1776 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1777 {
1778   return ViewProject(di, V3d_Xneg);
1779 }
1780
1781 //==============================================================================
1782 //function : VRight
1783 //purpose  : Switch to a Right View
1784 //Draw arg : No args
1785 //==============================================================================
1786
1787 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1788 {
1789   return ViewProject(di, V3d_Xpos);
1790 }
1791
1792 //==============================================================================
1793 //function : VFront
1794 //purpose  : Switch to a Front View
1795 //Draw arg : No args
1796 //==============================================================================
1797
1798 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1799 {
1800   return ViewProject(di, V3d_Yneg);
1801 }
1802
1803 //==============================================================================
1804 //function : VBack
1805 //purpose  : Switch to a Back View
1806 //Draw arg : No args
1807 //==============================================================================
1808
1809 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1810 {
1811   return ViewProject(di, V3d_Ypos);
1812 }
1813
1814 //==============================================================================
1815 //function : VHelp
1816 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1817 //Draw arg : No args
1818 //==============================================================================
1819
1820 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1821 {
1822
1823   di << "Q : Quit the application\n";
1824
1825   di << "=========================\n";
1826   di << "F : FitAll\n";
1827   di << "T : TopView\n";
1828   di << "B : BottomView\n";
1829   di << "R : RightView\n";
1830   di << "L : LeftView\n";
1831   di << "A : AxonometricView\n";
1832   di << "D : ResetView\n";
1833
1834   di << "=========================\n";
1835   di << "S : Shading\n";
1836   di << "W : Wireframe\n";
1837   di << "H : HidelLineRemoval\n";
1838   di << "U : Unset display mode\n";
1839   di << "Delete : Remove selection from viewer\n";
1840
1841   di << "=========================\n";
1842   di << "Selection mode \n";
1843   di << "0 : Shape\n";
1844   di << "1 : Vertex\n";
1845   di << "2 : Edge\n";
1846   di << "3 : Wire\n";
1847   di << "4 : Face\n";
1848   di << "5 : Shell\n";
1849   di << "6 : Solid\n";
1850   di << "7 : Compound\n";
1851
1852   di << "=========================\n";
1853   di << "Z : Switch Z clipping On/Off\n";
1854   di << ", : Hilight next detected\n";
1855   di << ". : Hilight previous detected\n";
1856
1857   return 0;
1858 }
1859
1860 #ifdef _WIN32
1861
1862 static Standard_Boolean Ppick = 0;
1863 static Standard_Integer Pargc = 0;
1864 static const char**           Pargv = NULL;
1865
1866
1867 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1868                                           UINT Msg,
1869                                           WPARAM wParam,
1870                                           LPARAM lParam )
1871 {
1872   if (!ViewerTest_myViews.IsEmpty()) {
1873
1874     WPARAM fwKeys = wParam;
1875
1876     switch( Msg ) {
1877     case WM_CLOSE:
1878        {
1879          // Delete view from map of views
1880          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1881          return 0;
1882        }
1883        break;
1884     case WM_ACTIVATE:
1885       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1886         || ViewerTest::CurrentView().IsNull())
1887       {
1888         // Activate inactive window
1889         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1890         {
1891           ActivateView (FindViewIdByWindowHandle(hwnd));
1892         }
1893       }
1894       break;
1895
1896     case WM_LBUTTONUP:
1897       if (IsDragged && !DragFirst)
1898       {
1899         if (!GetActiveAISManipulator().IsNull())
1900         {
1901           GetActiveAISManipulator()->StopTransform();
1902           ViewerTest::GetAISContext()->ClearSelected();
1903         }
1904
1905         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1906         {
1907           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1908           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1909         }
1910
1911         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1912       }
1913       IsDragged = Standard_False;
1914       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1915
1916     case WM_RBUTTONUP:
1917       if (IsDragged && !DragFirst)
1918       {
1919         if (!GetActiveAISManipulator().IsNull())
1920         {
1921           GetActiveAISManipulator()->StopTransform (Standard_False);
1922           ViewerTest::GetAISContext()->ClearSelected();
1923         }
1924         IsDragged = Standard_False;
1925       }
1926       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1927
1928     case WM_LBUTTONDOWN:
1929       if (!GetActiveAISManipulator().IsNull())
1930       {
1931         IsDragged = ( fwKeys == MK_LBUTTON );
1932       }
1933       else
1934       {
1935         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1936       }
1937
1938       if (IsDragged)
1939       {
1940         DragFirst = Standard_True;
1941         X_ButtonPress = LOWORD(lParam);
1942         Y_ButtonPress = HIWORD(lParam);
1943       }
1944       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1945
1946     case WM_MOUSEMOVE:
1947       if (IsDragged)
1948       {
1949         X_Motion = LOWORD (lParam);
1950         Y_Motion = HIWORD (lParam);
1951         if (!GetActiveAISManipulator().IsNull())
1952         {
1953           if (DragFirst)
1954           {
1955             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1956           }
1957           else
1958           {
1959             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1960             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1961           }
1962         }
1963         else
1964         {
1965           bool toRedraw = false;
1966           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1967           {
1968             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1969             toRedraw = true;
1970           }
1971
1972           RECT aRect;
1973           if (GetClientRect (hwnd, &aRect))
1974           {
1975             int aHeight = aRect.bottom - aRect.top;
1976             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1977             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1978             toRedraw = true;
1979           }
1980           if (toRedraw)
1981           {
1982             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1983           }
1984         }
1985
1986         DragFirst = Standard_False;
1987       }
1988       else
1989         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1990       break;
1991
1992     default:
1993       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1994     }
1995     return 0;
1996   }
1997   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1998 }
1999
2000
2001 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2002                                        UINT Msg,
2003                                        WPARAM wParam,
2004                                        LPARAM lParam )
2005 {
2006   static int Up = 1;
2007   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2008   if (aView.IsNull())
2009   {
2010     return DefWindowProc( hwnd, Msg, wParam, lParam );
2011   }
2012
2013     PAINTSTRUCT    ps;
2014
2015     switch( Msg ) {
2016     case WM_PAINT:
2017       BeginPaint(hwnd, &ps);
2018       EndPaint(hwnd, &ps);
2019       VT_ProcessExpose();
2020       break;
2021
2022     case WM_SIZE:
2023       VT_ProcessConfigure();
2024       break;
2025     case WM_MOVE:
2026     case WM_MOVING:
2027     case WM_SIZING:
2028       switch (aView->RenderingParams().StereoMode)
2029       {
2030         case Graphic3d_StereoMode_RowInterlaced:
2031         case Graphic3d_StereoMode_ColumnInterlaced:
2032         case Graphic3d_StereoMode_ChessBoard:
2033           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2034           break;
2035         default:
2036           break;
2037       }
2038       break;
2039
2040     case WM_KEYDOWN:
2041       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2042       {
2043         char c[2];
2044         c[0] = (char) wParam;
2045         c[1] = '\0';
2046         if (wParam == VK_DELETE)
2047         {
2048           c[0] = THE_KEY_DELETE;
2049         }
2050         // comma
2051         else if (wParam == VK_OEM_COMMA)
2052         {
2053           c[0] = ',';
2054         }
2055         // dot
2056         else if (wParam == VK_OEM_PERIOD)
2057         {
2058           c[0] = '.';
2059         }
2060         else if (wParam == VK_DIVIDE)
2061         {
2062           c[0] = '/';
2063         }
2064         // dot
2065         else if (wParam == VK_MULTIPLY)
2066         {
2067           c[0] = '*';
2068         }
2069         VT_ProcessKeyPress (c);
2070       }
2071       break;
2072
2073     case WM_LBUTTONUP:
2074     case WM_MBUTTONUP:
2075     case WM_RBUTTONUP:
2076       Up = 1;
2077       VT_ProcessButton3Release();
2078       break;
2079
2080     case WM_LBUTTONDOWN:
2081     case WM_MBUTTONDOWN:
2082     case WM_RBUTTONDOWN:
2083       {
2084         WPARAM fwKeys = wParam;
2085
2086         Up = 0;
2087
2088         X_ButtonPress = LOWORD(lParam);
2089         Y_ButtonPress = HIWORD(lParam);
2090
2091         if (Msg == WM_LBUTTONDOWN)
2092         {
2093           if ((fwKeys & MK_CONTROL) != 0)
2094           {
2095             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2096           }
2097           else
2098           {
2099             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2100           }
2101         }
2102         else if (Msg == WM_RBUTTONDOWN)
2103         {
2104           // Start rotation
2105           VT_ProcessButton3Press();
2106         }
2107       }
2108       break;
2109
2110     case WM_MOUSEWHEEL:
2111     {
2112       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2113       if (wParam & MK_CONTROL)
2114       {
2115         if (aView->Camera()->IsStereo())
2116         {
2117           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2118           if (aFocus > 0.2
2119            && aFocus < 2.0)
2120           {
2121             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2122             aView->Redraw();
2123           }
2124         }
2125       }
2126       else
2127       {
2128         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2129       }
2130       break;
2131     }
2132
2133     case WM_MOUSEMOVE:
2134       {
2135         //cout << "\t WM_MOUSEMOVE" << endl;
2136         WPARAM fwKeys = wParam;
2137         X_Motion = LOWORD(lParam);
2138         Y_Motion = HIWORD(lParam);
2139
2140         if ( Up &&
2141           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2142           {
2143             Up = 0;
2144             X_ButtonPress = LOWORD(lParam);
2145             Y_ButtonPress = HIWORD(lParam);
2146
2147             if ((fwKeys & MK_RBUTTON) != 0) {
2148               // Start rotation
2149               VT_ProcessButton3Press();
2150             }
2151           }
2152
2153           if ((fwKeys & MK_CONTROL) != 0)
2154           {
2155             if ((fwKeys & MK_LBUTTON) != 0)
2156             {
2157               ProcessControlButton1Motion();
2158             }
2159             else if ((fwKeys & MK_MBUTTON) != 0
2160                  || ((fwKeys & MK_LBUTTON) != 0
2161                   && (fwKeys & MK_RBUTTON) != 0))
2162             {
2163               VT_ProcessControlButton2Motion();
2164             }
2165             else if ((fwKeys & MK_RBUTTON) != 0)
2166             {
2167               VT_ProcessControlButton3Motion();
2168             }
2169           }
2170           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2171           {
2172             VT_ProcessMotion();
2173           }
2174       }
2175       break;
2176
2177     default:
2178       return( DefWindowProc( hwnd, Msg, wParam, lParam ));
2179     }
2180     return 0L;
2181 }
2182
2183
2184
2185
2186 //==============================================================================
2187 //function : ViewerMainLoop
2188 //purpose  : Get a Event on the view and dispatch it
2189 //==============================================================================
2190
2191
2192 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2193 {
2194   Ppick = (argc > 0)? 1 : 0;
2195   Pargc = argc;
2196   Pargv = argv;
2197
2198   if ( Ppick ) {
2199     MSG msg;
2200     msg.wParam = 1;
2201
2202     cout << "Start picking" << endl;
2203
2204     while ( Ppick == 1 ) {
2205       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2206       if (GetMessage(&msg, NULL, 0, 0) ) {
2207         TranslateMessage(&msg);
2208         DispatchMessage(&msg);
2209       }
2210     }
2211
2212     cout << "Picking done" << endl;
2213   }
2214
2215   return Ppick;
2216 }
2217
2218 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2219
2220 int min( int a, int b )
2221 {
2222   if( a<b )
2223     return a;
2224   else
2225     return b;
2226 }
2227
2228 int max( int a, int b )
2229 {
2230   if( a>b )
2231     return a;
2232   else
2233     return b;
2234 }
2235
2236 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2237
2238 {
2239   static XEvent aReport;
2240   Standard_Boolean pick = argc > 0;
2241   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2242   XNextEvent (aDisplay, &aReport);
2243
2244   // Handle event for the chosen display connection
2245   switch (aReport.type) {
2246       case ClientMessage:
2247         {
2248           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2249           {
2250             // Close the window
2251             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2252           }
2253         }
2254         return 0;
2255      case FocusIn:
2256       {
2257          // Activate inactive view
2258          Window aWindow = GetWindowHandle(VT_GetWindow());
2259          if(aWindow != aReport.xfocus.window)
2260          {
2261            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2262          }
2263       }
2264       break;
2265       case Expose:
2266         {
2267           VT_ProcessExpose();
2268         }
2269         break;
2270       case ConfigureNotify:
2271         {
2272           VT_ProcessConfigure();
2273         }
2274         break;
2275       case KeyPress:
2276         {
2277
2278           KeySym ks_ret ;
2279           char buf_ret[11] ;
2280           int ret_len ;
2281           XComposeStatus status_in_out;
2282
2283           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2284             (char *) buf_ret , 10 ,
2285             &ks_ret , &status_in_out ) ;
2286
2287
2288           buf_ret[ret_len] = '\0' ;
2289
2290           if (ret_len)
2291           {
2292             VT_ProcessKeyPress (buf_ret);
2293           }
2294         }
2295         break;
2296       case ButtonPress:
2297         {
2298           X_ButtonPress = aReport.xbutton.x;
2299           Y_ButtonPress = aReport.xbutton.y;
2300
2301           if (aReport.xbutton.button == Button1)
2302           {
2303             if (aReport.xbutton.state & ControlMask)
2304             {
2305               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2306             }
2307             else
2308             {
2309               IsDragged = Standard_True;
2310               DragFirst = Standard_True;
2311             }
2312           }
2313           else if (aReport.xbutton.button == Button3)
2314           {
2315             // Start rotation
2316             VT_ProcessButton3Press();
2317           }
2318         }
2319         break;
2320       case ButtonRelease:
2321         {
2322           if( IsDragged )
2323           {
2324             if( !DragFirst )
2325             {
2326               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2327               {
2328                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2329                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2330               }
2331             }
2332
2333             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2334             if( aContext.IsNull() )
2335             {
2336               cout << "The context is null. Please use vinit before createmesh" << endl;
2337               return 0;
2338             }
2339
2340             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2341             if( aReport.xbutton.button==1 )
2342               if( DragFirst )
2343                 if( ShiftPressed )
2344                 {
2345                   aContext->ShiftSelect();
2346                 }
2347                 else
2348                 {
2349                   aContext->Select();
2350                 }
2351               else
2352                 if( ShiftPressed )
2353                 {
2354                   aContext->ShiftSelect( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2355                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2356                     ViewerTest::CurrentView());
2357                 }
2358                 else
2359                 {
2360                   aContext->Select( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2361                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2362                     ViewerTest::CurrentView() );
2363                 }
2364             else
2365               VT_ProcessButton3Release();
2366
2367             IsDragged = Standard_False;
2368           }
2369           else
2370             VT_ProcessButton3Release();
2371         }
2372         break;
2373       case MotionNotify:
2374         {
2375           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2376           {
2377             break;
2378           }
2379           if( IsDragged )
2380           {
2381             if( !DragFirst )
2382             {
2383               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2384               {
2385                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2386               }
2387             }
2388
2389             X_Motion = aReport.xmotion.x;
2390             Y_Motion = aReport.xmotion.y;
2391             DragFirst = Standard_False;
2392
2393             Window aWindow = GetWindowHandle(VT_GetWindow());
2394             Window aRoot;
2395             int anX, anY;
2396             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2397             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2398             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2399             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2400             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2401           }
2402           else
2403           {
2404             X_Motion = aReport.xmotion.x;
2405             Y_Motion = aReport.xmotion.y;
2406
2407             // remove all the ButtonMotionMaskr
2408             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2409
2410             if ( aReport.xmotion.state & ControlMask ) {
2411               if ( aReport.xmotion.state & Button1Mask ) {
2412                 ProcessControlButton1Motion();
2413               }
2414               else if ( aReport.xmotion.state & Button2Mask ) {
2415                 VT_ProcessControlButton2Motion();
2416               }
2417               else if ( aReport.xmotion.state & Button3Mask ) {
2418                 VT_ProcessControlButton3Motion();
2419               }
2420             }
2421             else
2422             {
2423               VT_ProcessMotion();
2424             }
2425           }
2426         }
2427         break;
2428 }
2429 return pick;
2430 }
2431
2432 //==============================================================================
2433 //function : VProcessEvents
2434 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2435 //       event in the Viewer window
2436 //==============================================================================
2437
2438 static void VProcessEvents(ClientData,int)
2439 {
2440   NCollection_Vector<int> anEventNumbers;
2441   // Get number of messages from every display
2442   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2443        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2444   {
2445     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2446   }
2447     // Handle events for every display
2448   int anEventIter = 0;
2449   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2450        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2451   {
2452     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2453          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2454     {
2455       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2456       int anEventResult = ViewerMainLoop( 0, NULL);
2457       // If window is closed or context was not found finish current event processing loop
2458       if (!anEventResult)
2459         return;
2460     }
2461   }
2462
2463   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2464
2465 }
2466 #endif
2467
2468 //==============================================================================
2469 //function : OSWindowSetup
2470 //purpose  : Setup for the X11 window to be able to cath the event
2471 //==============================================================================
2472
2473
2474 static void OSWindowSetup()
2475 {
2476 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2477   // X11
2478
2479   Window  window   = VT_GetWindow()->XWindow();
2480   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2481   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2482   XSynchronize(aDisplay, 1);
2483
2484   // X11 : For keyboard on SUN
2485   XWMHints wmhints;
2486   wmhints.flags = InputHint;
2487   wmhints.input = 1;
2488
2489   XSetWMHints( aDisplay, window, &wmhints);
2490
2491   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2492     ButtonPressMask | ButtonReleaseMask |
2493     StructureNotifyMask |
2494     PointerMotionMask |
2495     Button1MotionMask | Button2MotionMask |
2496     Button3MotionMask | FocusChangeMask
2497     );
2498   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2499   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2500
2501   XSynchronize(aDisplay, 0);
2502
2503 #else
2504   // _WIN32
2505 #endif
2506
2507 }
2508
2509 //==============================================================================
2510 //function : VFit
2511 //purpose  :
2512 //==============================================================================
2513
2514 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2515 {
2516   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2517   if (aView.IsNull())
2518   {
2519     std::cout << "Error: no active viewer!\n";
2520     return 1;
2521   }
2522
2523   Standard_Boolean toFit = Standard_True;
2524   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2525   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2526   {
2527     TCollection_AsciiString anArg (theArgv[anArgIter]);
2528     anArg.LowerCase();
2529     if (anUpdateTool.parseRedrawMode (anArg))
2530     {
2531       continue;
2532     }
2533     else if (anArg == "-selected")
2534     {
2535       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2536       toFit = Standard_False;
2537     }
2538     else
2539     {
2540       std::cout << "Syntax error at '" << anArg << "'\n";
2541     }
2542   }
2543
2544   if (toFit)
2545   {
2546     aView->FitAll (0.01, Standard_False);
2547   }
2548   return 0;
2549 }
2550
2551 //=======================================================================
2552 //function : VFitArea
2553 //purpose  : Fit view to show area located between two points
2554 //         : given in world 2D or 3D coordinates.
2555 //=======================================================================
2556 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2557 {
2558   Handle(V3d_View) aView = ViewerTest::CurrentView();
2559   if (aView.IsNull())
2560   {
2561     std::cerr << theArgVec[0] << "Error: No active view.\n";
2562     return 1;
2563   }
2564
2565   // Parse arguments.
2566   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2567   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2568
2569   if (theArgNb == 5)
2570   {
2571     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2572     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2573     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2574     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2575   }
2576   else if (theArgNb == 7)
2577   {
2578     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2579     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2580     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2581     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2582     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2583     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2584   }
2585   else
2586   {
2587     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2588     theDI.PrintHelp(theArgVec[0]);
2589     return 1;
2590   }
2591
2592   // Convert model coordinates to view space
2593   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2594   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2595   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2596
2597   // Determine fit area
2598   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2599   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2600
2601   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2602
2603   if (aDiagonal < Precision::Confusion())
2604   {
2605     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2606     return 1;
2607   }
2608
2609   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2610   return 0;
2611 }
2612
2613 //==============================================================================
2614 //function : VZFit
2615 //purpose  : ZFitall, no DRAW arguments
2616 //Draw arg : No args
2617 //==============================================================================
2618 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2619 {
2620   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2621
2622   if (aCurrentView.IsNull())
2623   {
2624     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2625     return 1;
2626   }
2627
2628   if (theArgsNb == 1)
2629   {
2630     aCurrentView->ZFitAll();
2631     aCurrentView->Redraw();
2632     return 0;
2633   }
2634
2635   Standard_Real aScale = 1.0;
2636
2637   if (theArgsNb >= 2)
2638   {
2639     aScale = Draw::Atoi (theArgVec[1]);
2640   }
2641
2642   aCurrentView->ZFitAll (aScale);
2643   aCurrentView->Redraw();
2644
2645   return 0;
2646 }
2647
2648 //==============================================================================
2649 //function : VRepaint
2650 //purpose  :
2651 //==============================================================================
2652 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2653 {
2654   Handle(V3d_View) V = ViewerTest::CurrentView();
2655   if ( !V.IsNull() ) V->Redraw(); return 0;
2656 }
2657
2658 //==============================================================================
2659 //function : VClear
2660 //purpose  : Remove all the object from the viewer
2661 //Draw arg : No args
2662 //==============================================================================
2663
2664 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2665 {
2666   Handle(V3d_View) V = ViewerTest::CurrentView();
2667   if(!V.IsNull())
2668     ViewerTest::Clear();
2669   return 0;
2670 }
2671
2672 //==============================================================================
2673 //function : VPick
2674 //purpose  :
2675 //==============================================================================
2676
2677 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2678 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2679
2680 if ( argc < 4 ) {
2681   di << argv[0] << "Invalid number of arguments\n";
2682   return 1;
2683 }
2684
2685 while (ViewerMainLoop( argc, argv)) {
2686 }
2687
2688 return 0;
2689 }
2690
2691 //==============================================================================
2692 //function : VSetBg
2693 //purpose  : Load image as background
2694 //==============================================================================
2695
2696 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2697 {
2698   if (argc < 2 || argc > 3)
2699   {
2700     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2701     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2702     return 1;
2703   }
2704
2705   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2706   if(AISContext.IsNull())
2707   {
2708     di << "use 'vinit' command before " << argv[0] << "\n";
2709     return 1;
2710   }
2711
2712   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2713   if (argc == 3)
2714   {
2715     const char* szType = argv[2];
2716     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2717     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2718     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2719     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2720     else
2721     {
2722       di << "Wrong fill type : " << szType << "\n";
2723       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2724       return 1;
2725     }
2726   }
2727
2728   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2729   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2730
2731   return 0;
2732 }
2733
2734 //==============================================================================
2735 //function : VSetBgMode
2736 //purpose  : Change background image fill type
2737 //==============================================================================
2738
2739 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2740 {
2741   if (argc != 2)
2742   {
2743     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2744     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2745     return 1;
2746   }
2747
2748   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2749   if(AISContext.IsNull())
2750   {
2751     di << "use 'vinit' command before " << argv[0] << "\n";
2752     return 1;
2753   }
2754   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2755   const char* szType = argv[1];
2756   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2757   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2758   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2759   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2760   else
2761   {
2762     di << "Wrong fill type : " << szType << "\n";
2763     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2764     return 1;
2765   }
2766   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2767   V3dView->SetBgImageStyle(aFillType, Standard_True);
2768   return 0;
2769 }
2770
2771 //==============================================================================
2772 //function : VSetGradientBg
2773 //purpose  : Mount gradient background
2774 //==============================================================================
2775 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2776 {
2777   if (argc != 8 )
2778   {
2779     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2780     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2781     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2782     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2783     return 1;
2784   }
2785
2786   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2787   if(AISContext.IsNull())
2788   {
2789     di << "use 'vinit' command before " << argv[0] << "\n";
2790     return 1;
2791   }
2792   if (argc == 8)
2793   {
2794
2795     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2796     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2797     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2798     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2799
2800     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2801     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2802     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2803
2804     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2805     int aType = Draw::Atoi(argv[7]);
2806     if( aType < 0 || aType > 8 )
2807     {
2808       di << "Wrong fill type \n";
2809       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2810       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2811       return 1;
2812     }
2813
2814     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2815
2816     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2817     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2818   }
2819
2820   return 0;
2821 }
2822
2823 //==============================================================================
2824 //function : VSetGradientBgMode
2825 //purpose  : Change gradient background fill style
2826 //==============================================================================
2827 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2828 {
2829   if (argc != 2 )
2830   {
2831     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2832     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2833     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2834     return 1;
2835   }
2836
2837   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2838   if(AISContext.IsNull())
2839   {
2840     di << "use 'vinit' command before " << argv[0] << "\n";
2841     return 1;
2842   }
2843   if (argc == 2)
2844   {
2845     int aType = Draw::Atoi(argv[1]);
2846     if( aType < 0 || aType > 8 )
2847     {
2848       di << "Wrong fill type \n";
2849       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2850       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2851       return 1;
2852     }
2853
2854     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2855
2856     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2857     V3dView->SetBgGradientStyle( aMethod, 1 );
2858   }
2859
2860   return 0;
2861 }
2862
2863 //==============================================================================
2864 //function : VSetColorBg
2865 //purpose  : Set color background
2866 //==============================================================================
2867 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2868 {
2869   if (argc != 4 )
2870   {
2871     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2872     di << "R,G,B = [0..255]\n";
2873     return 1;
2874   }
2875
2876   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2877   if(AISContext.IsNull())
2878   {
2879     di << "use 'vinit' command before " << argv[0] << "\n";
2880     return 1;
2881   }
2882   if (argc == 4)
2883   {
2884
2885     Standard_Real R = Draw::Atof(argv[1])/255.;
2886     Standard_Real G = Draw::Atof(argv[2])/255.;
2887     Standard_Real B = Draw::Atof(argv[3])/255.;
2888     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2889
2890     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2891     V3dView->SetBackgroundColor( aColor );
2892     V3dView->Update();
2893   }
2894
2895   return 0;
2896 }
2897
2898 //==============================================================================
2899 //function : VSetDefaultBg
2900 //purpose  : Set default viewer background fill color
2901 //==============================================================================
2902 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2903 {
2904   if (theArgNb != 4
2905    && theArgNb != 8)
2906   {
2907     std::cout << "Error: wrong syntax! See usage:\n";
2908     theDI.PrintHelp (theArgVec[0]);
2909     return 1;
2910   }
2911
2912   ViewerTest_DefaultBackground.FillMethod =
2913     theArgNb == 4 ? Aspect_GFM_NONE
2914                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2915
2916   if (theArgNb == 4)
2917   {
2918     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2919     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2920     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2921     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2922   }
2923   else
2924   {
2925     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2926     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2927     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2928     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2929
2930     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2931     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2932     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2933     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2934   }
2935
2936   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2937        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2938   {
2939     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2940     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2941     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2942                                          ViewerTest_DefaultBackground.GradientColor2,
2943                                          ViewerTest_DefaultBackground.FillMethod);
2944   }
2945
2946   return 0;
2947 }
2948
2949 //==============================================================================
2950 //function : VScale
2951 //purpose  : View Scaling
2952 //==============================================================================
2953
2954 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2955 {
2956   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2957   if ( V3dView.IsNull() ) return 1;
2958
2959   if ( argc != 4 ) {
2960     di << argv[0] << "Invalid number of arguments\n";
2961     return 1;
2962   }
2963   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2964   return 0;
2965 }
2966 //==============================================================================
2967 //function : VZBuffTrihedron
2968 //purpose  :
2969 //==============================================================================
2970
2971 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2972                             Standard_Integer  theArgNb,
2973                             const char**      theArgVec)
2974 {
2975   Handle(V3d_View) aView = ViewerTest::CurrentView();
2976   if (aView.IsNull())
2977   {
2978     std::cout << "Error: no active viewer!\n";
2979     return 1;
2980   }
2981
2982   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2983
2984   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2985   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2986   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2987   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2988   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2989   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2990   Standard_Real                 aScale        = 0.1;
2991   Standard_Real                 aSizeRatio    = 0.8;
2992   Standard_Real                 anArrowDiam   = 0.05;
2993   Standard_Integer              aNbFacets     = 12;
2994   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2995   {
2996     Standard_CString        anArg = theArgVec[anArgIter];
2997     TCollection_AsciiString aFlag (anArg);
2998     aFlag.LowerCase();
2999     if (anUpdateTool.parseRedrawMode (aFlag))
3000     {
3001       continue;
3002     }
3003     else if (aFlag == "-on")
3004     {
3005       continue;
3006     }
3007     else if (aFlag == "-off")
3008     {
3009       aView->TriedronErase();
3010       return 0;
3011     }
3012     else if (aFlag == "-pos"
3013           || aFlag == "-position"
3014           || aFlag == "-corner")
3015     {
3016       if (++anArgIter >= theArgNb)
3017       {
3018         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3019         return 1;
3020       }
3021
3022       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3023       aPosName.LowerCase();
3024       if (aPosName == "center")
3025       {
3026         aPosition = Aspect_TOTP_CENTER;
3027       }
3028       else if (aPosName == "left_lower"
3029             || aPosName == "lower_left"
3030             || aPosName == "leftlower"
3031             || aPosName == "lowerleft")
3032       {
3033         aPosition = Aspect_TOTP_LEFT_LOWER;
3034       }
3035       else if (aPosName == "left_upper"
3036             || aPosName == "upper_left"
3037             || aPosName == "leftupper"
3038             || aPosName == "upperleft")
3039       {
3040         aPosition = Aspect_TOTP_LEFT_UPPER;
3041       }
3042       else if (aPosName == "right_lower"
3043             || aPosName == "lower_right"
3044             || aPosName == "rightlower"
3045             || aPosName == "lowerright")
3046       {
3047         aPosition = Aspect_TOTP_RIGHT_LOWER;
3048       }
3049       else if (aPosName == "right_upper"
3050             || aPosName == "upper_right"
3051             || aPosName == "rightupper"
3052             || aPosName == "upperright")
3053       {
3054         aPosition = Aspect_TOTP_RIGHT_UPPER;
3055       }
3056       else
3057       {
3058         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3059         return 1;
3060       }
3061     }
3062     else if (aFlag == "-type")
3063     {
3064       if (++anArgIter >= theArgNb)
3065       {
3066         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3067         return 1;
3068       }
3069
3070       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3071       aTypeName.LowerCase();
3072       if (aTypeName == "wireframe"
3073        || aTypeName == "wire")
3074       {
3075         aVisType = V3d_WIREFRAME;
3076       }
3077       else if (aTypeName == "zbuffer"
3078             || aTypeName == "shaded")
3079       {
3080         aVisType = V3d_ZBUFFER;
3081       }
3082       else
3083       {
3084         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3085       }
3086     }
3087     else if (aFlag == "-scale")
3088     {
3089       if (++anArgIter >= theArgNb)
3090       {
3091         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3092         return 1;
3093       }
3094
3095       aScale = Draw::Atof (theArgVec[anArgIter]);
3096     }
3097     else if (aFlag == "-size"
3098           || aFlag == "-sizeratio")
3099     {
3100       if (++anArgIter >= theArgNb)
3101       {
3102         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3103         return 1;
3104       }
3105
3106       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3107     }
3108     else if (aFlag == "-arrowdiam"
3109           || aFlag == "-arrowdiameter")
3110     {
3111       if (++anArgIter >= theArgNb)
3112       {
3113         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3114         return 1;
3115       }
3116
3117       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3118     }
3119     else if (aFlag == "-nbfacets")
3120     {
3121       if (++anArgIter >= theArgNb)
3122       {
3123         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3124         return 1;
3125       }
3126
3127       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3128     }
3129     else if (aFlag == "-colorlabel"
3130           || aFlag == "-colorlabels")
3131     {
3132       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3133                                                            theArgVec + anArgIter + 1,
3134                                                            aLabelsColor);
3135       if (aNbParsed == 0)
3136       {
3137         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3138         return 1;
3139       }
3140       anArgIter += aNbParsed;
3141     }
3142     else if (aFlag == "-colorarrowx")
3143     {
3144       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3145                                                            theArgVec + anArgIter + 1,
3146                                                            anArrowColorX);
3147       if (aNbParsed == 0)
3148       {
3149         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3150         return 1;
3151       }
3152       anArgIter += aNbParsed;
3153     }
3154     else if (aFlag == "-colorarrowy")
3155     {
3156       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3157                                                            theArgVec + anArgIter + 1,
3158                                                            anArrowColorY);
3159       if (aNbParsed == 0)
3160       {
3161         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3162         return 1;
3163       }
3164       anArgIter += aNbParsed;
3165     }
3166     else if (aFlag == "-colorarrowz")
3167     {
3168       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3169                                                            theArgVec + anArgIter + 1,
3170                                                            anArrowColorZ);
3171       if (aNbParsed == 0)
3172       {
3173         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3174         return 1;
3175       }
3176       anArgIter += aNbParsed;
3177     }
3178     else
3179     {
3180       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3181       return 1;
3182     }
3183   }
3184
3185   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3186                                aSizeRatio, anArrowDiam, aNbFacets);
3187   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3188   aView->ZFitAll();
3189   return 0;
3190 }
3191
3192 //==============================================================================
3193 //function : VRotate
3194 //purpose  : Camera Rotating
3195 //==============================================================================
3196
3197 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3198 {
3199   Handle(V3d_View) aView = ViewerTest::CurrentView();
3200   if (aView.IsNull())
3201   {
3202     std::cout << "No active view!\n";
3203     return 1;
3204   }
3205
3206   Standard_Boolean hasFlags = Standard_False;
3207   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3208   {
3209     Standard_CString        anArg (theArgVec[anArgIter]);
3210     TCollection_AsciiString aFlag (anArg);
3211     aFlag.LowerCase();
3212     if (aFlag == "-mousestart"
3213      || aFlag == "-mousefrom")
3214     {
3215       hasFlags = Standard_True;
3216       if (anArgIter + 2 >= theArgNb)
3217       {
3218         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3219         return 1;
3220       }
3221
3222       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3223       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3224       aView->StartRotation (anX, anY);
3225     }
3226     else if (aFlag == "-mousemove")
3227     {
3228       hasFlags = Standard_True;
3229       if (anArgIter + 2 >= theArgNb)
3230       {
3231         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3232         return 1;
3233       }
3234
3235       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3236       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3237       aView->Rotation (anX, anY);
3238     }
3239     else if (theArgNb != 4
3240           && theArgNb != 7)
3241     {
3242       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3243       return 1;
3244     }
3245   }
3246
3247   if (hasFlags)
3248   {
3249     return 0;
3250   }
3251   else if (theArgNb == 4)
3252   {
3253     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3254     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3255     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3256     aView->Rotate (anAX, anAY, anAZ);
3257     return 0;
3258   }
3259   else if (theArgNb == 7)
3260   {
3261     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3262     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3263     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3264
3265     Standard_Real anX = Draw::Atof (theArgVec[4]);
3266     Standard_Real anY = Draw::Atof (theArgVec[5]);
3267     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3268
3269     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3270     return 0;
3271   }
3272
3273   std::cout << "Error: Invalid number of arguments\n";
3274   return 1;
3275 }
3276
3277 //==============================================================================
3278 //function : VZoom
3279 //purpose  : View zoom in / out (relative to current zoom)
3280 //==============================================================================
3281
3282 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3283   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3284   if ( V3dView.IsNull() ) {
3285     return 1;
3286   }
3287
3288   if ( argc == 2 ) {
3289     Standard_Real coef = Draw::Atof(argv[1]);
3290     if ( coef <= 0.0 ) {
3291       di << argv[1] << "Invalid value\n";
3292       return 1;
3293     }
3294     V3dView->SetZoom( Draw::Atof(argv[1]) );
3295     return 0;
3296   } else {
3297     di << argv[0] << " Invalid number of arguments\n";
3298     return 1;
3299   }
3300 }
3301
3302 //==============================================================================
3303 //function : VPan
3304 //purpose  : View panning (in pixels)
3305 //==============================================================================
3306
3307 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3308   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3309   if ( V3dView.IsNull() ) return 1;
3310
3311   if ( argc == 3 ) {
3312     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3313     return 0;
3314   } else {
3315     di << argv[0] << " Invalid number of arguments\n";
3316     return 1;
3317   }
3318 }
3319
3320 //==============================================================================
3321 //function : VPlace
3322 //purpose  : Place the point (in pixels) at the center of the window
3323 //==============================================================================
3324 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3325 {
3326   Handle(V3d_View) aView = ViewerTest::CurrentView();
3327   if (aView.IsNull())
3328   {
3329     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3330     return 1;
3331   }
3332
3333   if (theArgNb != 3)
3334   {
3335     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3336     return 1;
3337   }
3338
3339   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3340
3341   return 0;
3342 }
3343
3344 //==============================================================================
3345 //function : VExport
3346 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3347 //==============================================================================
3348
3349 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3350 {
3351   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3352   if (V3dView.IsNull())
3353     return 1;
3354
3355   if (argc == 1)
3356   {
3357     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3358     return 1;
3359   }
3360
3361   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3362   TCollection_AsciiString aFormatStr;
3363
3364   TCollection_AsciiString aFileName (argv[1]);
3365   Standard_Integer aLen = aFileName.Length();
3366
3367   if (argc > 2)
3368   {
3369     aFormatStr = TCollection_AsciiString (argv[2]);
3370   }
3371   else if (aLen >= 4)
3372   {
3373     if (aFileName.Value (aLen - 2) == '.')
3374     {
3375       aFormatStr = aFileName.ToCString() + aLen - 2;
3376     }
3377     else if (aFileName.Value (aLen - 3) == '.')
3378     {
3379       aFormatStr = aFileName.ToCString() + aLen - 3;
3380     }
3381     else
3382     {
3383       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3384       return 1;
3385     }
3386   }
3387   else
3388   {
3389     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3390     return 1;
3391   }
3392
3393   aFormatStr.UpperCase();
3394   if (aFormatStr == "PS")
3395     anExpFormat = Graphic3d_EF_PostScript;
3396   else if (aFormatStr == "EPS")
3397     anExpFormat = Graphic3d_EF_EnhPostScript;
3398   else if (aFormatStr == "TEX")
3399     anExpFormat = Graphic3d_EF_TEX;
3400   else if (aFormatStr == "PDF")
3401     anExpFormat = Graphic3d_EF_PDF;
3402   else if (aFormatStr == "SVG")
3403     anExpFormat = Graphic3d_EF_SVG;
3404   else if (aFormatStr == "PGF")
3405     anExpFormat = Graphic3d_EF_PGF;
3406   else if (aFormatStr == "EMF")
3407     anExpFormat = Graphic3d_EF_EMF;
3408   else
3409   {
3410     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3411     return 1;
3412   }
3413
3414   try
3415   {
3416   Standard_DISABLE_DEPRECATION_WARNINGS
3417     if (!V3dView->Export (argv[1], anExpFormat))
3418   Standard_ENABLE_DEPRECATION_WARNINGS
3419     {
3420       di << "Error: export of image to " << aFormatStr << " failed!\n";
3421     }
3422   }
3423   catch (Standard_Failure)
3424   {
3425     di << "Error: export of image to " << aFormatStr << " failed";
3426     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
3427   }
3428   return 0;
3429 }
3430
3431 //==============================================================================
3432 //function : VColorScale
3433 //purpose  : representation color scale
3434 //==============================================================================
3435
3436 static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
3437                                     const TCollection_AsciiString& theGreen,
3438                                     const TCollection_AsciiString& theBlue,
3439                                                     Standard_Real& theRedValue,
3440                                                     Standard_Real& theGreenValue,
3441                                                     Standard_Real& theBlueValue)
3442 {
3443   if (!theRed.IsRealValue()
3444    || !theGreen.IsRealValue()
3445    || !theBlue.IsRealValue())
3446   {
3447     std::cout << "Error: RGB color values should be real!\n";
3448     return Standard_True;
3449   }
3450   theRedValue = theRed    .RealValue();
3451   theGreenValue = theGreen.RealValue();
3452   theBlueValue = theBlue  .RealValue();
3453   if (theRedValue < 0.0 || theRedValue > 1.0
3454    || theGreenValue < 0.0 || theGreenValue > 1.0
3455    || theBlueValue < 0.0 || theBlueValue > 1.0)
3456   {
3457     std::cout << "Error: RGB color values should be within range 0..1!\n";
3458     return Standard_True;
3459   }
3460   return Standard_False;
3461 }
3462
3463 static int VColorScale (Draw_Interpretor& theDI,
3464                         Standard_Integer  theArgNb,
3465                         const char**      theArgVec)
3466 {
3467   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3468   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3469   if (aContext.IsNull())
3470   {
3471     std::cout << "Error: no active view!\n";
3472     return 1;
3473   }
3474   if (theArgNb <= 1)
3475   {
3476     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3477     return 1;
3478   }
3479
3480   Handle(AIS_ColorScale) aCS;
3481   // find object
3482   Handle(AIS_InteractiveObject) anIObj;
3483   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3484   {
3485     aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3486     if (aCS.IsNull())
3487     {
3488       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3489       return 1;
3490     }
3491   }
3492   else
3493   {
3494     aCS = new AIS_ColorScale();
3495     GetMapOfAIS().Bind (aCS,theArgVec[1]);
3496   }
3497
3498   if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD)
3499   {
3500     aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3501   }
3502   if (aCS->TransformPersistence().IsNull()
3503    || aCS->TransformPersistence()->Mode() != Graphic3d_TMF_2d)
3504   {
3505     aContext->SetTransformPersistence (aCS, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3506   }
3507
3508   Standard_Real                   aMinRange    = aCS->GetMin();
3509   Standard_Real                   aMaxRange    = aCS->GetMax();
3510   Standard_Integer                aBreadth     = aCS->GetBreadth();
3511   Standard_Integer                aHeight      = aCS->GetHeight();
3512   Standard_Integer                aNbIntervals = aCS->GetNumberOfIntervals();
3513   Standard_Integer                aTextHeight  = aCS->GetTextHeight();
3514   Aspect_TypeOfColorScalePosition aLabPosition = aCS->GetLabelPosition();
3515   Standard_Integer                aPosX = aCS->GetXPosition();
3516   Standard_Integer                aPosY = aCS->GetYPosition();
3517
3518   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3519
3520   if (theArgNb <= 2)
3521   {
3522     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3523           << "Min range: " << aMinRange << "\n"
3524           << "Max range: " << aMaxRange << "\n"
3525           << "Number of intervals: " << aNbIntervals << "\n"
3526           << "Text height: " << aTextHeight << "\n"
3527           << "Color scale position: " << aPosX <<" "<< aPosY<< "\n"
3528           << "Color scale title: " << aCS->GetTitle() << "\n"
3529           << "Label position: ";
3530     switch (aLabPosition)
3531     {
3532       case Aspect_TOCSP_NONE:
3533         theDI << "None\n";
3534         break;
3535       case Aspect_TOCSP_LEFT:
3536         theDI << "Left\n";
3537         break;
3538       case Aspect_TOCSP_RIGHT:
3539         theDI << "Right\n";
3540         break;
3541       case Aspect_TOCSP_CENTER:
3542         theDI << "Center\n";
3543         break;
3544     }
3545     return 0;
3546   }
3547
3548   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3549   {
3550     Standard_CString        anArg = theArgVec[anArgIter];
3551     TCollection_AsciiString aFlag (anArg);
3552     aFlag.LowerCase();
3553     if (anUpdateTool.parseRedrawMode (aFlag))
3554     {
3555       continue;
3556     }
3557     else if (aFlag == "-range")
3558     {
3559       if (anArgIter + 3 >= theArgNb)
3560       {
3561         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3562         return 1;
3563       }
3564
3565       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3566       TCollection_AsciiString anArg2 (theArgVec[++anArgIter]);
3567       TCollection_AsciiString anArg3 (theArgVec[++anArgIter]);
3568       if (!anArg1.IsRealValue())
3569       {
3570         std::cout << "Error: the minRange value should be real!\n";
3571         return 1;
3572       }
3573       else if (!anArg2.IsRealValue())
3574       {
3575         std::cout << "Error: the maxRange value should be real!\n";
3576         return 1;
3577       }
3578       else if (!anArg3.IsIntegerValue())
3579       {
3580         std::cout << "Error: the number of intervals should be integer!\n";
3581         return 1;
3582       }
3583
3584       aMinRange    = anArg1.RealValue();
3585       aMaxRange    = anArg2.RealValue();
3586       aNbIntervals = anArg3.IntegerValue();
3587     }
3588     else if (aFlag == "-font")
3589     {
3590       if (anArgIter + 1 >= theArgNb)
3591       {
3592         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3593         return 1;
3594       }
3595       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3596       if (!aFontArg.IsIntegerValue())
3597       {
3598         std::cout << "Error: HeightFont value should be integer!\n";
3599         return 1;
3600       }
3601
3602       aTextHeight = aFontArg.IntegerValue();
3603       anArgIter += 1;
3604     }
3605     else if (aFlag == "-textpos")
3606     {
3607       if (anArgIter + 1 >= theArgNb)
3608       {
3609         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3610         return 1;
3611       }
3612       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3613       aTextPosArg.LowerCase();
3614       if (aTextPosArg == "none")
3615       {
3616         aLabPosition = Aspect_TOCSP_NONE;
3617       }
3618       else if (aTextPosArg == "left")
3619       {
3620         aLabPosition = Aspect_TOCSP_LEFT;
3621       }
3622       else if (aTextPosArg == "right")
3623       {
3624         aLabPosition = Aspect_TOCSP_RIGHT;
3625       }
3626       else if (aTextPosArg == "center")
3627       {
3628         aLabPosition = Aspect_TOCSP_CENTER;
3629       }
3630       else
3631       {
3632         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3633         return 1;
3634       }
3635     }
3636     else if (aFlag == "-logarithmic"
3637           || aFlag == "-log")
3638     {
3639       if (anArgIter + 1 >= theArgNb)
3640       {
3641         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3642         return 1;
3643       }
3644       Standard_Boolean IsLog;
3645       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3646       {
3647         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3648         return 1;
3649       }
3650       aCS->SetLogarithmic (IsLog);
3651     }
3652     else if (aFlag == "-xy")
3653     {
3654       if (anArgIter + 2 >= theArgNb)
3655       {
3656         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3657         return 1;
3658       }
3659
3660       TCollection_AsciiString aX (theArgVec[++anArgIter]);
3661       TCollection_AsciiString aY (theArgVec[++anArgIter]);
3662       if (!aX.IsIntegerValue()
3663        || !aY.IsIntegerValue())
3664       {
3665         std::cout << "Error: coordinates should be integer values!\n";
3666         return 1;
3667       }
3668
3669       aPosX = aX.IntegerValue();
3670       aPosY = aY.IntegerValue();
3671     }
3672     else if (aFlag == "-width"
3673           || aFlag == "-w")
3674     {
3675       if (anArgIter + 1 >= theArgNb)
3676       {
3677         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3678         return 1;
3679       }
3680
3681       TCollection_AsciiString aW (theArgVec[++anArgIter]);
3682       if (!aW.IsIntegerValue())
3683       {
3684         std::cout << "Error: a width should be an integer value!\n";
3685         return 1;
3686       }
3687
3688       aBreadth = aW.IntegerValue();
3689     }
3690     else if (aFlag == "-height"
3691           || aFlag == "-h")
3692     {
3693       if (anArgIter + 1 >= theArgNb)
3694       {
3695         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3696         return 1;
3697       }
3698
3699       TCollection_AsciiString aH (theArgVec[++anArgIter]);
3700       if (!aH.IsIntegerValue())
3701       {
3702         std::cout << "Error: a width should be an integer value!\n";
3703         return 1;
3704       }
3705
3706       aHeight = aH.IntegerValue();
3707     }
3708     else if (aFlag == "-color")
3709     {
3710       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3711       {
3712         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3713         return 1;
3714       }
3715
3716       Quantity_NameOfColor aColorName;
3717       if (anArgIter + 4 >= theArgNb)
3718       {
3719         if (anArgIter + 2 >= theArgNb)
3720         {
3721           std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3722           return 1;
3723         }
3724         else if (!Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3725         {
3726           std::cout << "Error: wrong color name: '" << theArgVec[anArgIter + 2] << "' !\n";
3727           return 1;
3728         }
3729       }
3730
3731       TCollection_AsciiString anInd (theArgVec[anArgIter + 1]);
3732       if (!anInd.IsIntegerValue())
3733       {
3734         std::cout << "Error: Index value should be integer!\n";
3735         return 1;
3736       }
3737
3738       Standard_Integer anIndex = anInd.IntegerValue();
3739       if (anIndex <= 0 || anIndex > aNbIntervals)
3740       {
3741         std::cout << "Error: Index value should be within range 1.." << aNbIntervals <<"!\n";
3742         return 1;
3743       }
3744
3745       if (Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3746       {
3747         aCS->SetIntervalColor (Quantity_Color (aColorName), anIndex);
3748         aCS->SetColorType (Aspect_TOCSD_USER);
3749         anArgIter += 2;
3750         continue;
3751       }
3752
3753       TCollection_AsciiString aRed   (theArgVec[anArgIter + 2]);
3754       TCollection_AsciiString aGreen (theArgVec[anArgIter + 3]);
3755       TCollection_AsciiString aBlue  (theArgVec[anArgIter + 4]);
3756       Standard_Real aRedValue,aGreenValue, aBlueValue;
3757       if(checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3758       {
3759         return 1;
3760       }
3761       aCS->SetIntervalColor (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB), anIndex);
3762       aCS->SetColorType (Aspect_TOCSD_USER);
3763       anArgIter += 4;
3764     }
3765     else if (aFlag == "-label")
3766     {
3767       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3768       {
3769         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3770         return 1;
3771       }
3772       else if (anArgIter + 2 >= theArgNb)
3773       {
3774         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3775         return 1;
3776       }
3777
3778       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3779       if (anIndex <= 0 || anIndex > aNbIntervals+1)
3780       {
3781         std::cout << "Error: Index value should be within range 1.." << aNbIntervals+1 <<"!\n";
3782         return 1;
3783       }
3784
3785       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3786       aCS->SetLabel     (aText, anIndex);
3787       aCS->SetLabelType (Aspect_TOCSD_USER);
3788       anArgIter += 2;
3789     }
3790     else if (aFlag == "-colors")
3791     {
3792       Aspect_SequenceOfColor aSeq;
3793       if (anArgIter + aNbIntervals + 1 > theArgNb)
3794       {
3795         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3796                   << aNbIntervals << " intervals\n";
3797         return 1;
3798       }
3799
3800       Standard_Integer aColorIter = anArgIter + 1;
3801       while (aColorIter < theArgNb)
3802       {
3803         if (theArgVec[aColorIter][0] == '-')
3804         {
3805           break;
3806         }
3807
3808         else if (theArgVec[aColorIter][0] >= 97
3809               && theArgVec[aColorIter][0] <= 122)
3810         {
3811           Quantity_NameOfColor aColorName;
3812           if (!Quantity_Color::ColorFromName (theArgVec[aColorIter], aColorName))
3813           {
3814             std::cout << "Error: wrong color name: " << theArgVec[aColorIter] << " !\n";
3815             return 1;
3816           }
3817           aSeq.Append (Quantity_Color (aColorName));
3818           aColorIter++;
3819           anArgIter++;
3820         }
3821         else
3822         {
3823           TCollection_AsciiString aRed   (theArgVec[aColorIter]);
3824           TCollection_AsciiString aGreen (theArgVec[aColorIter + 1]);
3825           TCollection_AsciiString aBlue  (theArgVec[aColorIter + 2]);
3826           Standard_Real aRedValue,aGreenValue, aBlueValue;
3827           if (checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3828           {
3829             return 1;
3830           }
3831           aSeq.Append (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB));
3832           aColorIter += 3;
3833           anArgIter += 3;
3834         }
3835       }
3836       if (aSeq.Length() < aNbIntervals)
3837       {
3838         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3839                   << aNbIntervals << " intervals\n";
3840         return 1;
3841       }
3842
3843       aCS->SetColors    (aSeq);
3844       aCS->SetColorType (Aspect_TOCSD_USER);
3845     }
3846     else if (aFlag == "-labels")
3847     {
3848       if (anArgIter + aNbIntervals + 1 >= theArgNb)
3849       {
3850         std::cout << "Error: not enough arguments! You should provide " << (aNbIntervals + 1)
3851                   << " text labels for " << aNbIntervals << " intervals.\n";
3852         return 1;
3853       }
3854
3855       TColStd_SequenceOfExtendedString aSeq;
3856       for (int aLabelIter = anArgIter + 1; aLabelIter <= anArgIter + aNbIntervals + 1; aLabelIter += 1)
3857       {
3858         aSeq.Append (TCollection_ExtendedString (theArgVec[aLabelIter]));
3859       }
3860       aCS->SetLabels (aSeq);
3861       aCS->SetLabelType (Aspect_TOCSD_USER);
3862       anArgIter += aSeq.Length();
3863     }
3864     else if (aFlag == "-title")
3865     {
3866       if (anArgIter + 1 >= theArgNb)
3867       {
3868         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3869         return 1;
3870       }
3871
3872       Standard_Boolean isTwoArgs = Standard_False;
3873       if (anArgIter + 2 < theArgNb)
3874       {
3875         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3876         aSecondArg.LowerCase();
3877         if (aSecondArg == "none")
3878         {
3879           aCS->SetTitlePosition (Aspect_TOCSP_NONE);
3880           isTwoArgs = Standard_True;
3881         }
3882         else if (aSecondArg == "left")
3883         {
3884           aCS->SetTitlePosition (Aspect_TOCSP_LEFT);
3885           isTwoArgs = Standard_True;
3886         }
3887         else if (aSecondArg == "right")
3888         {
3889           aCS->SetTitlePosition (Aspect_TOCSP_RIGHT);
3890           isTwoArgs = Standard_True;
3891         }
3892         else if (aSecondArg == "center")
3893         {
3894           aCS->SetTitlePosition (Aspect_TOCSP_CENTER);
3895           isTwoArgs = Standard_True;
3896         }
3897       }
3898
3899       aCS->SetTitle (theArgVec[anArgIter + 1]);
3900       if (isTwoArgs)
3901       {
3902         anArgIter += 1;
3903       }
3904       anArgIter += 1;
3905     }
3906     else if (aFlag == "-demoversion"
3907           || aFlag == "-demo")
3908     {
3909       aPosX        = 0;
3910       aPosY        = 0;
3911       aTextHeight  = 16;
3912       aMinRange    = 0.0;
3913       aMaxRange    = 100;
3914       aNbIntervals = 10;
3915       aBreadth     = 0;
3916       aHeight      = 0;
3917       aLabPosition = Aspect_TOCSP_RIGHT;
3918       aCS->SetColorType (Aspect_TOCSD_AUTO);
3919       aCS->SetLabelType (Aspect_TOCSD_AUTO);
3920     }
3921     else if (aFlag == "-findcolor")
3922     {
3923       if (anArgIter + 1 >= theArgNb)
3924       {
3925         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3926         return 1;
3927       }
3928
3929       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3930
3931       if (!anArg1.IsRealValue())
3932       {
3933         std::cout << "Error: the value should be real!\n";
3934         return 1;
3935       }
3936
3937       Quantity_Color aColor;
3938       aCS->FindColor (anArg1.RealValue(), aColor);
3939       theDI << Quantity_Color::StringName (aColor.Name());
3940       return 0;
3941     }
3942     else
3943     {
3944       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3945       return 1;
3946     }
3947   }
3948   if (!aBreadth || !aHeight)
3949   {
3950     Standard_Integer aWinWidth, aWinHeight;
3951     aView->Window()->Size (aWinWidth, aWinHeight);
3952     if (!aBreadth)
3953     {
3954       aBreadth = aWinWidth;
3955     }
3956     if (!aHeight)
3957     {
3958       aHeight = aWinHeight;
3959     }
3960   }
3961   aCS->SetSize              (aBreadth, aHeight);
3962   aCS->SetPosition          (aPosX, aPosY);
3963   aCS->SetTextHeight        (aTextHeight);
3964   aCS->SetRange             (aMinRange, aMaxRange);
3965   aCS->SetNumberOfIntervals (aNbIntervals);
3966   aCS->SetLabelPosition     (aLabPosition);
3967 //  aCS->SetColor             (aView->BackgroundColor().Invert());
3968   aCS->SetToUpdate();
3969   aContext->Display (aCS);
3970
3971   return 0;
3972 }
3973
3974 //==============================================================================
3975 //function : VGraduatedTrihedron
3976 //purpose  : Displays or hides a graduated trihedron
3977 //==============================================================================
3978 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
3979                                   Quantity_Color& theColor)
3980 {
3981   Quantity_NameOfColor aColorName;
3982   TCollection_AsciiString aVal = theValue;
3983   aVal.UpperCase();
3984   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
3985   {
3986     return Standard_False;
3987   }
3988   theColor = Quantity_Color (aColorName);
3989   return Standard_True;
3990 }
3991
3992 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
3993 {
3994   if (theArgNum < 2)
3995   {
3996     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
3997               << theArgs[0] <<"' for more information.\n";
3998     return 1;  //TCL_ERROR
3999   }
4000
4001   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4002   TCollection_AsciiString aParseKey;
4003   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4004   {
4005     TCollection_AsciiString anArg (theArgs [anArgIt]);
4006
4007     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4008     {
4009       aParseKey = anArg;
4010       aParseKey.Remove (1);
4011       aParseKey.LowerCase();
4012       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4013       continue;
4014     }
4015
4016     if (aParseKey.IsEmpty())
4017     {
4018       continue;
4019     }
4020
4021     aMapOfArgs(aParseKey)->Append (anArg);
4022   }
4023
4024   // Check parameters
4025   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4026        aMapIt.More(); aMapIt.Next())
4027   {
4028     const TCollection_AsciiString& aKey = aMapIt.Key();
4029     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4030
4031     // Bool key, without arguments
4032     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4033         && anArgs->IsEmpty())
4034     {
4035       continue;
4036     }
4037
4038     // One argument
4039     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4040           && anArgs->Length() == 1)
4041     {
4042       continue;
4043     }
4044
4045     // On/off arguments
4046     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4047         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4048         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4049         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4050         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4051     {
4052       continue;
4053     }
4054
4055     // One string argument
4056     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4057           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4058           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4059     {
4060       continue;
4061     }
4062
4063     // One integer argument
4064     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4065           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4066           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4067           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4068          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4069     {
4070       continue;
4071     }
4072
4073     // One real argument
4074     if ( aKey.IsEqual ("arrowlength")
4075          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4076     {
4077       continue;
4078     }
4079
4080     // Two string arguments
4081     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4082          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4083     {
4084       continue;
4085     }
4086
4087     TCollection_AsciiString aLowerKey;
4088     aLowerKey  = "-";
4089     aLowerKey += aKey;
4090     aLowerKey.LowerCase();
4091     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4092     std::cout << "Type help for more information.\n";
4093     return 1;
4094   }
4095
4096   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4097   if (anAISContext.IsNull())
4098   {
4099     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4100     return 1;
4101   }
4102
4103   Standard_Boolean toDisplay = Standard_True;
4104   Quantity_Color aColor;
4105   Graphic3d_GraduatedTrihedron aTrihedronData;
4106   // Process parameters
4107   Handle(TColStd_HSequenceOfAsciiString) aValues;
4108   if (aMapOfArgs.Find ("off", aValues))
4109   {
4110     toDisplay = Standard_False;
4111   }
4112
4113   // AXES NAMES
4114   if (aMapOfArgs.Find ("xname", aValues))
4115   {
4116     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4117   }
4118   if (aMapOfArgs.Find ("yname", aValues))
4119   {
4120     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4121   }
4122   if (aMapOfArgs.Find ("zname", aValues))
4123   {
4124     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4125   }
4126   if (aMapOfArgs.Find ("xdrawname", aValues))
4127   {
4128     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4129   }
4130   if (aMapOfArgs.Find ("ydrawname", aValues))
4131   {
4132     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4133   }
4134   if (aMapOfArgs.Find ("zdrawname", aValues))
4135   {
4136     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4137   }
4138   if (aMapOfArgs.Find ("xnameoffset", aValues))
4139   {
4140     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4141   }
4142   if (aMapOfArgs.Find ("ynameoffset", aValues))
4143   {
4144     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4145   }
4146   if (aMapOfArgs.Find ("znameoffset", aValues))
4147   {
4148     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4149   }
4150
4151   // COLORS
4152   if (aMapOfArgs.Find ("xnamecolor", aValues))
4153   {
4154     if (!GetColor (aValues->Value(1), aColor))
4155     {
4156       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4157       return 1;
4158     }
4159     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4160   }
4161   if (aMapOfArgs.Find ("ynamecolor", aValues))
4162   {
4163     if (!GetColor (aValues->Value(1), aColor))
4164     {
4165       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4166       return 1;
4167     }
4168     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4169   }
4170   if (aMapOfArgs.Find ("znamecolor", aValues))
4171   {
4172     if (!GetColor (aValues->Value(1), aColor))
4173     {
4174       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4175       return 1;
4176     }
4177     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4178   }
4179   if (aMapOfArgs.Find ("xcolor", aValues))
4180   {
4181     if (!GetColor (aValues->Value(1), aColor))
4182     {
4183       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4184       return 1;
4185     }
4186     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4187   }
4188   if (aMapOfArgs.Find ("ycolor", aValues))
4189   {
4190     if (!GetColor (aValues->Value(1), aColor))
4191     {
4192       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4193       return 1;
4194     }
4195     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4196   }
4197   if (aMapOfArgs.Find ("zcolor", aValues))
4198   {
4199     if (!GetColor (aValues->Value(1), aColor))
4200     {
4201       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4202       return 1;
4203     }
4204     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4205   }
4206
4207   // TICKMARKS
4208   if (aMapOfArgs.Find ("xticks", aValues))
4209   {
4210     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4211   }
4212   if (aMapOfArgs.Find ("yticks", aValues))
4213   {
4214     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4215   }
4216   if (aMapOfArgs.Find ("zticks", aValues))
4217   {
4218     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4219   }
4220   if (aMapOfArgs.Find ("xticklength", aValues))
4221   {
4222     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4223   }
4224   if (aMapOfArgs.Find ("yticklength", aValues))
4225   {
4226     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4227   }
4228   if (aMapOfArgs.Find ("zticklength", aValues))
4229   {
4230     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4231   }
4232   if (aMapOfArgs.Find ("xdrawticks", aValues))
4233   {
4234     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4235   }
4236   if (aMapOfArgs.Find ("ydrawticks", aValues))
4237   {
4238     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4239   }
4240   if (aMapOfArgs.Find ("zdrawticks", aValues))
4241   {
4242     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4243   }
4244
4245   // VALUES
4246   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4247   {
4248     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4249   }
4250   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4251   {
4252     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4253   }
4254   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4255   {
4256     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4257   }
4258   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4259   {
4260     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4261   }
4262   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4263   {
4264     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4265   }
4266   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4267   {
4268     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4269   }
4270
4271   // ARROWS
4272   if (aMapOfArgs.Find ("arrowlength", aValues))
4273   {
4274     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4275   }
4276
4277   // FONTS
4278   if (aMapOfArgs.Find ("namefont", aValues))
4279   {
4280     aTrihedronData.SetNamesFont (aValues->Value(1));
4281   }
4282   if (aMapOfArgs.Find ("valuesfont", aValues))
4283   {
4284     aTrihedronData.SetValuesFont (aValues->Value(1));
4285   }
4286
4287   if (aMapOfArgs.Find ("drawgrid", aValues))
4288   {
4289     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4290   }
4291   if (aMapOfArgs.Find ("drawaxes", aValues))
4292   {
4293     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4294   }
4295
4296   // The final step: display of erase trihedron
4297   if (toDisplay)
4298   {
4299     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4300   }
4301   else
4302   {
4303     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4304   }
4305
4306   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4307   ViewerTest::CurrentView()->Redraw();
4308
4309   return 0;
4310 }
4311
4312 //==============================================================================
4313 //function : VTile
4314 //purpose  :
4315 //==============================================================================
4316 static int VTile (Draw_Interpretor& theDI,
4317                   Standard_Integer  theArgNb,
4318                   const char**      theArgVec)
4319 {
4320   Handle(V3d_View) aView = ViewerTest::CurrentView();
4321   if (aView.IsNull())
4322   {
4323     std::cerr << "Error: no active viewer.\n";
4324     return 1;
4325   }
4326
4327   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4328   if (theArgNb < 2)
4329   {
4330     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4331           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4332           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4333     return 0;
4334   }
4335
4336   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4337   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4338   {
4339     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4340     anArg.LowerCase();
4341     if (anArg == "-lowerleft"
4342      || anArg == "-upperleft")
4343     {
4344       if (anArgIter + 3 < theArgNb)
4345       {
4346         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4347         return 1;
4348       }
4349       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4350       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4351       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4352     }
4353     else if (anArg == "-total"
4354           || anArg == "-totalsize"
4355           || anArg == "-viewsize")
4356     {
4357       if (anArgIter + 3 < theArgNb)
4358       {
4359         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4360         return 1;
4361       }
4362       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4363       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4364       if (aTile.TotalSize.x() < 1
4365        || aTile.TotalSize.y() < 1)
4366       {
4367         std::cerr << "Error: total size is incorrect.\n";
4368         return 1;
4369       }
4370     }
4371     else if (anArg == "-tilesize")
4372     {
4373       if (anArgIter + 3 < theArgNb)
4374       {
4375         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4376         return 1;
4377       }
4378
4379       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4380       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4381       if (aTile.TileSize.x() < 1
4382        || aTile.TileSize.y() < 1)
4383       {
4384         std::cerr << "Error: tile size is incorrect.\n";
4385         return 1;
4386       }
4387     }
4388     else if (anArg == "-unset")
4389     {
4390       aView->Camera()->SetTile (Graphic3d_CameraTile());
4391       aView->Redraw();
4392       return 0;
4393     }
4394   }
4395
4396   if (aTile.TileSize.x() < 1
4397    || aTile.TileSize.y() < 1)
4398   {
4399     std::cerr << "Error: tile size is undefined.\n";
4400     return 1;
4401   }
4402   else if (aTile.TotalSize.x() < 1
4403         || aTile.TotalSize.y() < 1)
4404   {
4405     std::cerr << "Error: total size is undefined.\n";
4406     return 1;
4407   }
4408
4409   aView->Camera()->SetTile (aTile);
4410   aView->Redraw();
4411   return 0;
4412 }
4413
4414 //! Format ZLayer ID.
4415 inline const char* formZLayerId (const Standard_Integer theLayerId)
4416 {
4417   switch (theLayerId)
4418   {
4419     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4420     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4421     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4422     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4423     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4424     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4425   }
4426   return "";
4427 }
4428
4429 //! Print the ZLayer information.
4430 inline void printZLayerInfo (Draw_Interpretor& theDI,
4431                              const Graphic3d_ZLayerSettings& theLayer)
4432 {
4433   if (!theLayer.Name().IsEmpty())
4434   {
4435     theDI << "  Name: " << theLayer.Name() << "\n";
4436   }
4437   if (theLayer.IsImmediate())
4438   {
4439     theDI << "  Immediate: TRUE\n";
4440   }
4441   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4442   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4443   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4444   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4445   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4446   {
4447     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4448   }
4449 }
4450
4451 //==============================================================================
4452 //function : VZLayer
4453 //purpose  : Test z layer operations for v3d viewer
4454 //==============================================================================
4455 static int VZLayer (Draw_Interpretor& theDI,
4456                     Standard_Integer  theArgNb,
4457                     const char**      theArgVec)
4458 {
4459   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4460   if (aContextAIS.IsNull())
4461   {
4462     std::cout << "No active viewer!\n";
4463     return 1;
4464   }
4465
4466   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4467   if (theArgNb < 2)
4468   {
4469     TColStd_SequenceOfInteger aLayers;
4470     aViewer->GetAllZLayers (aLayers);
4471     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4472     {
4473       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4474       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4475       printZLayerInfo (theDI, aSettings);
4476     }
4477     return 1;
4478   }
4479
4480   Standard_Integer anArgIter = 1;
4481   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4482   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4483   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4484   {
4485     ++anArgIter;
4486   }
4487
4488   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4489   if (aFirstArg.IsIntegerValue())
4490   {
4491     ++anArgIter;
4492     aLayerId = aFirstArg.IntegerValue();
4493   }
4494   else
4495   {
4496     aFirstArg.LowerCase();
4497     if (aFirstArg == "default"
4498      || aFirstArg == "def")
4499     {
4500       aLayerId = Graphic3d_ZLayerId_Default;
4501       ++anArgIter;
4502     }
4503     else if (aFirstArg == "top")
4504     {
4505       aLayerId = Graphic3d_ZLayerId_Top;
4506       ++anArgIter;
4507     }
4508     else if (aFirstArg == "topmost")
4509     {
4510       aLayerId = Graphic3d_ZLayerId_Topmost;
4511       ++anArgIter;
4512     }
4513     else if (aFirstArg == "overlay"
4514           || aFirstArg == "toposd")
4515     {
4516       aLayerId = Graphic3d_ZLayerId_TopOSD;
4517       ++anArgIter;
4518     }
4519     else if (aFirstArg == "underlay"
4520           || aFirstArg == "botosd")
4521     {
4522       aLayerId = Graphic3d_ZLayerId_BotOSD;
4523       ++anArgIter;
4524     }
4525     else
4526     {
4527       TColStd_SequenceOfInteger aLayers;
4528       aViewer->GetAllZLayers (aLayers);
4529       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4530       {
4531         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4532         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4533         {
4534           aLayerId = aLayeriter.Value();
4535           ++anArgIter;
4536           break;
4537         }
4538       }
4539     }
4540   }
4541
4542   for (; anArgIter < theArgNb; ++anArgIter)
4543   {
4544     // perform operation
4545     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4546     anArg.LowerCase();
4547     if (anUpdateTool.parseRedrawMode (anArg))
4548     {
4549       //
4550     }
4551     else if (anArg == "-add"
4552           || anArg == "add")
4553     {
4554       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4555       if (!aViewer->AddZLayer (aLayerId))
4556       {
4557         std::cout << "Error: can not add a new z layer!\n";
4558         return 0;
4559       }
4560
4561       theDI << aLayerId;
4562     }
4563     else if (anArg == "-del"
4564           || anArg == "-delete"
4565           || anArg == "del")
4566     {
4567       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4568       {
4569         if (++anArgIter >= theArgNb)
4570         {
4571           std::cout << "Syntax error: id of z layer to remove is missing\n";
4572           return 1;
4573         }
4574
4575         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4576       }
4577
4578       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4579        || aLayerId == Graphic3d_ZLayerId_Default
4580        || aLayerId == Graphic3d_ZLayerId_Top
4581        || aLayerId == Graphic3d_ZLayerId_Topmost
4582        || aLayerId == Graphic3d_ZLayerId_TopOSD
4583        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4584       {
4585         std::cout << "Syntax error: standard Z layer can not be removed\n";
4586         return 1;
4587       }
4588
4589       // move all object displayed in removing layer to default layer
4590       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4591            anObjIter.More(); anObjIter.Next())
4592       {
4593         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4594         if (aPrs.IsNull()
4595          || aPrs->ZLayer() != aLayerId)
4596         {
4597           continue;
4598         }
4599         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4600       }
4601
4602       if (!aViewer->RemoveZLayer (aLayerId))
4603       {
4604         std::cout << "Z layer can not be removed!\n";
4605       }
4606       else
4607       {
4608         theDI << aLayerId << " ";
4609       }
4610     }
4611     else if (anArg == "-get"
4612           || anArg == "get")
4613     {
4614       TColStd_SequenceOfInteger aLayers;
4615       aViewer->GetAllZLayers (aLayers);
4616       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4617       {
4618         theDI << aLayeriter.Value() << " ";
4619       }
4620
4621       theDI << "\n";
4622     }
4623     else if (anArg == "-name")
4624     {
4625       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4626       {
4627         std::cout << "Syntax error: id of Z layer is missing\n";
4628         return 1;
4629       }
4630
4631       if (++anArgIter >= theArgNb)
4632       {
4633         std::cout << "Syntax error: name is missing\n";
4634         return 1;
4635       }
4636
4637       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4638       aSettings.SetName (theArgVec[anArgIter]);
4639       aViewer->SetZLayerSettings (aLayerId, aSettings);
4640     }
4641     else if (anArg == "-origin")
4642     {
4643       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4644       {
4645         std::cout << "Syntax error: id of Z layer is missing\n";
4646         return 1;
4647       }
4648
4649       if (anArgIter + 2 >= theArgNb)
4650       {
4651         std::cout << "Syntax error: origin coordinates are missing\n";
4652         return 1;
4653       }
4654
4655       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4656       gp_XYZ anOrigin;
4657       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4658       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4659       anOrigin.SetZ (0.0);
4660       if (anArgIter + 3 < theArgNb)
4661       {
4662         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4663         anArgIter += 3;
4664       }
4665       else
4666       {
4667         anArgIter += 2;
4668       }
4669       aSettings.SetOrigin (anOrigin);
4670       aViewer->SetZLayerSettings (aLayerId, aSettings);
4671     }
4672     else if (anArg == "-settings"
4673           || anArg == "settings")
4674     {
4675       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4676       {
4677         if (++anArgIter >= theArgNb)
4678         {
4679           std::cout << "Syntax error: id of Z layer is missing\n";
4680           return 1;
4681         }
4682
4683         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4684       }
4685
4686       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4687       printZLayerInfo (theDI, aSettings);
4688     }
4689     else if (anArg == "-enable"
4690           || anArg == "enable"
4691           || anArg == "-disable"
4692           || anArg == "disable")
4693     {
4694       const Standard_Boolean toEnable = anArg == "-enable"
4695                                      || anArg == "enable";
4696       if (++anArgIter >= theArgNb)
4697       {
4698         std::cout << "Syntax error: option name is missing\n";
4699         return 1;
4700       }
4701
4702       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4703       aSubOp.LowerCase();
4704       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4705       {
4706         if (++anArgIter >= theArgNb)
4707         {
4708           std::cout << "Syntax error: id of Z layer is missing\n";
4709           return 1;
4710         }
4711
4712         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4713       }
4714
4715       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4716       if (aSubOp == "depthtest"
4717        || aSubOp == "test")
4718       {
4719         aSettings.SetEnableDepthTest (toEnable);
4720       }
4721       else if (aSubOp == "depthwrite"
4722             || aSubOp == "write")
4723       {
4724         aSettings.SetEnableDepthWrite (toEnable);
4725       }
4726       else if (aSubOp == "depthclear"
4727             || aSubOp == "clear")
4728       {
4729         aSettings.SetClearDepth (toEnable);
4730       }
4731       else if (aSubOp == "depthoffset"
4732             || aSubOp == "offset")
4733       {
4734         Graphic3d_PolygonOffset aParams;
4735         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4736         if (toEnable)
4737         {
4738           if (anArgIter + 2 >= theArgNb)
4739           {
4740             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4741             return 1;
4742           }
4743
4744           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4745           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4746         }
4747         aSettings.SetPolygonOffset (aParams);
4748       }
4749       else if (aSubOp == "positiveoffset"
4750             || aSubOp == "poffset")
4751       {
4752         if (toEnable)
4753         {
4754           aSettings.SetDepthOffsetPositive();
4755         }
4756         else
4757         {
4758           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4759         }
4760       }
4761       else if (aSubOp == "negativeoffset"
4762             || aSubOp == "noffset")
4763       {
4764         if (toEnable)
4765         {
4766           aSettings.SetDepthOffsetNegative();
4767         }
4768         else
4769         {
4770           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4771         }
4772       }
4773       else if (aSubOp == "textureenv")
4774       {
4775         aSettings.SetEnvironmentTexture (toEnable);
4776       }
4777
4778       aViewer->SetZLayerSettings (aLayerId, aSettings);
4779     }
4780     else
4781     {
4782       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4783       return 1;
4784     }
4785   }
4786
4787   return 0;
4788 }
4789
4790 // The interactive presentation of 2d layer item
4791 // for "vlayerline" command it provides a presentation of
4792 // line with user-defined linewidth, linetype and transparency.
4793 class V3d_LineItem : public AIS_InteractiveObject
4794 {
4795 public:
4796   // CASCADE RTTI
4797   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4798
4799   // constructor
4800   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4801                                Standard_Real X2, Standard_Real Y2,
4802                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4803                                Standard_Real theWidth    = 0.5,
4804                                Standard_Real theTransp   = 1.0);
4805
4806   private:
4807
4808   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4809                 const Handle(Prs3d_Presentation)& thePresentation,
4810                 const Standard_Integer theMode) Standard_OVERRIDE;
4811
4812   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4813                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4814   {}
4815
4816 private:
4817
4818   Standard_Real       myX1, myY1, myX2, myY2;
4819   Aspect_TypeOfLine   myType;
4820   Standard_Real       myWidth;
4821 };
4822
4823 // default constructor for line item
4824 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4825                            Standard_Real X2, Standard_Real Y2,
4826                            Aspect_TypeOfLine theType,
4827                            Standard_Real theWidth,
4828                            Standard_Real theTransp) :
4829   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4830   myType(theType), myWidth(theWidth)
4831 {
4832   SetTransparency (1-theTransp);
4833 }
4834
4835 // render line
4836 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4837                             const Handle(Prs3d_Presentation)& thePresentation,
4838                             const Standard_Integer /*theMode*/)
4839 {
4840   thePresentation->Clear();
4841   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4842   Standard_Integer aWidth, aHeight;
4843   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4844   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4845   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4846   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4847   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4848   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4849   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4850   aGroup->AddPrimitiveArray (aPrim);
4851 }
4852
4853 //=============================================================================
4854 //function : VLayerLine
4855 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4856 //         : linewidth, transparency coefficient
4857 //============================================================================
4858 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4859 {
4860   // get the active view
4861   Handle(V3d_View) aView = ViewerTest::CurrentView();
4862   if (aView.IsNull())
4863   {
4864     di << "Call vinit before!\n";
4865     return 1;
4866   }
4867   else if (argc < 5)
4868   {
4869     di << "Use: " << argv[0];
4870     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4871     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4872     di << "              0 - solid  \n";
4873     di << "              1 - dashed \n";
4874     di << "              2 - dot    \n";
4875     di << "              3 - dashdot\n";
4876     di << " transparency : { 0.0 - 1.0 } \n";
4877     di << "                  0.0 - transparent\n";
4878     di << "                  1.0 - visible    \n";
4879     return 1;
4880   }
4881
4882   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4883   // get the input params
4884   Standard_Real X1 = Draw::Atof(argv[1]);
4885   Standard_Real Y1 = Draw::Atof(argv[2]);
4886   Standard_Real X2 = Draw::Atof(argv[3]);
4887   Standard_Real Y2 = Draw::Atof(argv[4]);
4888
4889   Standard_Real    aWidth = 0.5;
4890   Standard_Integer aType  = 0;
4891   Standard_Real    aTransparency = 1.0;
4892
4893   // has width
4894   if (argc > 5)
4895     aWidth = Draw::Atof(argv[5]);
4896
4897   // has type
4898   if (argc > 6)
4899      aType = (Standard_Integer) Draw::Atoi(argv[6]);
4900
4901   // has transparency
4902   if (argc > 7)
4903   {
4904     aTransparency = Draw::Atof(argv[7]);
4905     if (aTransparency < 0 || aTransparency > 1.0)
4906       aTransparency = 1.0;
4907   }
4908
4909   // select appropriate line type
4910   Aspect_TypeOfLine aLineType;
4911   switch (aType)
4912   {
4913     case 1:
4914       aLineType = Aspect_TOL_DASH;
4915     break;
4916
4917     case 2:
4918       aLineType = Aspect_TOL_DOT;
4919     break;
4920
4921     case 3:
4922       aLineType = Aspect_TOL_DOTDASH;
4923     break;
4924
4925     default:
4926       aLineType = Aspect_TOL_SOLID;
4927   }
4928
4929   static Handle (V3d_LineItem) aLine;
4930   if (!aLine.IsNull())
4931   {
4932     aContext->Erase (aLine);
4933   }
4934   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4935                             aLineType, aWidth,
4936                             aTransparency);
4937
4938   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4939   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4940   aLine->SetToUpdate();
4941   aContext->Display (aLine, Standard_True);
4942
4943   return 0;
4944 }
4945
4946
4947 //==============================================================================
4948 //function : VGrid
4949 //purpose  :
4950 //==============================================================================
4951
4952 static int VGrid (Draw_Interpretor& /*theDI*/,
4953                   Standard_Integer  theArgNb,
4954                   const char**      theArgVec)
4955 {
4956   // get the active view
4957   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4958   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4959   if (aView.IsNull() || aViewer.IsNull())
4960   {
4961     std::cerr << "No active view. Please call vinit.\n";
4962     return 1;
4963   }
4964
4965   Aspect_GridType     aType = aViewer->GridType();
4966   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4967
4968   Standard_Integer anIter = 1;
4969   for (; anIter < theArgNb; ++anIter)
4970   {
4971     const char* aValue = theArgVec[anIter];
4972     if (*aValue == 'r')
4973     {
4974       aType = Aspect_GT_Rectangular;
4975     }
4976     else if (*aValue == 'c')
4977     {
4978       aType = Aspect_GT_Circular;
4979     }
4980     else if (*aValue == 'l')
4981     {
4982       aMode = Aspect_GDM_Lines;
4983     }
4984     else if (*aValue == 'p')
4985     {
4986       aMode = Aspect_GDM_Points;
4987     }
4988     else if (strcmp (aValue, "off" ) == 0)
4989     {
4990       aViewer->DeactivateGrid();
4991       return 0;
4992     }
4993     else
4994     {
4995       break;
4996     }
4997   }
4998
4999   Standard_Integer aTail = (theArgNb - anIter);
5000   if (aTail == 0)
5001   {
5002     aViewer->ActivateGrid (aType, aMode);
5003     return 0;
5004   }
5005   else if (aTail != 2 && aTail != 5)
5006   {
5007     std::cerr << "Incorrect arguments number! Usage:\n"
5008               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5009     return 1;
5010   }
5011
5012   Quantity_Length anOriginX, anOriginY;
5013   Quantity_PlaneAngle aRotAngle;
5014   if (aType == Aspect_GT_Rectangular)
5015   {
5016     Quantity_Length aRStepX, aRStepY;
5017     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5018
5019     anOriginX = Draw::Atof (theArgVec[anIter++]);
5020     anOriginY = Draw::Atof (theArgVec[anIter++]);
5021     if (aTail == 5)
5022     {
5023       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5024       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5025       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5026     }
5027     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5028     aViewer->ActivateGrid (aType, aMode);
5029   }
5030   else if (aType == Aspect_GT_Circular)
5031   {
5032     Quantity_Length aRadiusStep;
5033     Standard_Integer aDivisionNumber;
5034     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5035
5036     anOriginX = Draw::Atof (theArgVec[anIter++]);
5037     anOriginY = Draw::Atof (theArgVec[anIter++]);
5038     if (aTail == 5)
5039     {
5040       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5041       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5042       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5043     }
5044
5045     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5046     aViewer->ActivateGrid (aType, aMode);
5047   }
5048
5049   return 0;
5050 }
5051
5052 //==============================================================================
5053 //function : VPriviledgedPlane
5054 //purpose  :
5055 //==============================================================================
5056
5057 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5058                               Standard_Integer  theArgNb,
5059                               const char**      theArgVec)
5060 {
5061   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5062   {
5063     std::cerr << "Error: wrong number of arguments! See usage:\n";
5064     theDI.PrintHelp (theArgVec[0]);
5065     return 1;
5066   }
5067
5068   // get the active viewer
5069   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5070   if (aViewer.IsNull())
5071   {
5072     std::cerr << "Error: no active viewer. Please call vinit.\n";
5073     return 1;
5074   }
5075
5076   if (theArgNb == 1)
5077   {
5078     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5079     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5080     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5081     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5082     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5083           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5084           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5085     return 0;
5086   }
5087
5088   Standard_Integer anArgIdx = 1;
5089   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5090   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5091   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5092   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5093   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5094   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5095
5096   gp_Ax3 aPriviledgedPlane;
5097   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5098   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5099   if (theArgNb > 7)
5100   {
5101     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5102     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5103     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5104     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5105     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5106   }
5107   else
5108   {
5109     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5110   }
5111
5112   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5113
5114   return 0;
5115 }
5116
5117 //==============================================================================
5118 //function : VConvert
5119 //purpose  :
5120 //==============================================================================
5121
5122 static int VConvert (Draw_Interpretor& theDI,
5123                      Standard_Integer  theArgNb,
5124                      const char**      theArgVec)
5125 {
5126   // get the active view
5127   Handle(V3d_View) aView = ViewerTest::CurrentView();
5128   if (aView.IsNull())
5129   {
5130     std::cerr << "Error: no active view. Please call vinit.\n";
5131     return 1;
5132   }
5133
5134   enum { Model, Ray, View, Window, Grid } aMode = Model;
5135
5136   // access coordinate arguments
5137   TColStd_SequenceOfReal aCoord;
5138   Standard_Integer anArgIdx = 1;
5139   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5140   {
5141     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5142     if (!anArg.IsRealValue())
5143     {
5144       break;
5145     }
5146     aCoord.Append (anArg.RealValue());
5147   }
5148
5149   // non-numeric argument too early
5150   if (aCoord.IsEmpty())
5151   {
5152     std::cerr << "Error: wrong number of arguments! See usage:\n";
5153     theDI.PrintHelp (theArgVec[0]);
5154     return 1;
5155   }
5156
5157   // collect all other arguments and options
5158   for (; anArgIdx < theArgNb; ++anArgIdx)
5159   {
5160     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5161     anArg.LowerCase();
5162     if      (anArg == "window") aMode = Window;
5163     else if (anArg == "view")   aMode = View;
5164     else if (anArg == "grid")   aMode = Grid;
5165     else if (anArg == "ray")    aMode = Ray;
5166     else
5167     {
5168       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5169       theDI.PrintHelp (theArgVec[0]);
5170       return 1;
5171     }
5172   }
5173
5174   // complete input checks
5175   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5176       (aCoord.Length() == 2 && theArgNb > 4) ||
5177       (aCoord.Length() == 3 && theArgNb > 5))
5178   {
5179     std::cerr << "Error: wrong number of arguments! See usage:\n";
5180     theDI.PrintHelp (theArgVec[0]);
5181     return 1;
5182   }
5183
5184   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5185   Standard_Integer aXYp[2] = {0, 0};
5186
5187   // convert one-dimensional coordinate
5188   if (aCoord.Length() == 1)
5189   {
5190     switch (aMode)
5191     {
5192       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
5193       case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
5194       default:
5195         std::cerr << "Error: wrong arguments! See usage:\n";
5196         theDI.PrintHelp (theArgVec[0]);
5197         return 1;
5198     }
5199   }
5200
5201   // convert 2D coordinates from projection or view reference space
5202   if (aCoord.Length() == 2)
5203   {
5204     switch (aMode)
5205     {
5206       case Model :
5207         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5208         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5209         return 0;
5210
5211       case View :
5212         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5213         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5214         return 0;
5215
5216       case Window :
5217         aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
5218         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5219         return 0;
5220
5221       case Grid :
5222         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5223         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5224         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5225         return 0;
5226
5227       case Ray :
5228         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5229                                 (Standard_Integer) aCoord (2),
5230                                 aXYZ[0], aXYZ[1], aXYZ[2],
5231                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5232         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5233         return 0;
5234
5235       default:
5236         std::cerr << "Error: wrong arguments! See usage:\n";
5237         theDI.PrintHelp (theArgVec[0]);
5238         return 1;
5239     }
5240   }
5241
5242   // convert 3D coordinates from view reference space
5243   else if (aCoord.Length() == 3)
5244   {
5245     switch (aMode)
5246     {
5247       case Window :
5248         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5249         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5250         return 0;
5251
5252       case Grid :
5253         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5254         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5255         return 0;
5256
5257       default:
5258         std::cerr << "Error: wrong arguments! See usage:\n";
5259         theDI.PrintHelp (theArgVec[0]);
5260         return 1;
5261     }
5262   }
5263
5264   return 0;
5265 }
5266
5267 //==============================================================================
5268 //function : VFps
5269 //purpose  :
5270 //==============================================================================
5271
5272 static int VFps (Draw_Interpretor& theDI,
5273                  Standard_Integer  theArgNb,
5274                  const char**      theArgVec)
5275 {
5276   // get the active view
5277   Handle(V3d_View) aView = ViewerTest::CurrentView();
5278   if (aView.IsNull())
5279   {
5280     std::cerr << "No active view. Please call vinit.\n";
5281     return 1;
5282   }
5283
5284   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5285   if (aFramesNb <= 0)
5286   {
5287     std::cerr << "Incorrect arguments!\n";
5288     return 1;
5289   }
5290
5291   // the time is meaningless for first call
5292   // due to async OpenGl rendering
5293   aView->Redraw();
5294
5295   // redraw view in loop to estimate average values
5296   OSD_Timer aTimer;
5297   aTimer.Start();
5298   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5299   {
5300     aView->Redraw();
5301   }
5302   aTimer.Stop();
5303   Standard_Real aCpu;
5304   const Standard_Real aTime = aTimer.ElapsedTime();
5305   aTimer.OSD_Chronometer::Show (aCpu);
5306
5307   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5308   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5309
5310   // return statistics
5311   theDI << "FPS: " << aFpsAver << "\n"
5312         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5313
5314   // compute additional statistics in ray-tracing mode
5315   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5316
5317   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5318   {
5319     Standard_Integer aSizeX;
5320     Standard_Integer aSizeY;
5321
5322     aView->Window()->Size (aSizeX, aSizeY);
5323
5324     // 1 shadow ray and 1 secondary ray pew each bounce
5325     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5326
5327     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5328   }
5329
5330   return 0;
5331 }
5332
5333 //==============================================================================
5334 //function : VGlDebug
5335 //purpose  :
5336 //==============================================================================
5337
5338 static int VGlDebug (Draw_Interpretor& theDI,
5339                      Standard_Integer  theArgNb,
5340                      const char**      theArgVec)
5341 {
5342   Handle(OpenGl_GraphicDriver) aDriver;
5343   Handle(V3d_View) aView = ViewerTest::CurrentView();
5344   if (!aView.IsNull())
5345   {
5346     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5347   }
5348   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5349   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5350
5351   if (theArgNb < 2)
5352   {
5353     TCollection_AsciiString aDebActive, aSyncActive;
5354     if (aCaps == NULL)
5355     {
5356       aCaps = aDefCaps;
5357     }
5358     else
5359     {
5360       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5361                                                                   "GL_ARB_debug_output");
5362       aDebActive = isActive ? " (active)" : " (inactive)";
5363       if (isActive)
5364       {
5365         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5366         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5367       }
5368     }
5369
5370     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5371           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5372           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5373           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5374     return 0;
5375   }
5376
5377   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5378   {
5379     Standard_CString        anArg     = theArgVec[anArgIter];
5380     TCollection_AsciiString anArgCase (anArg);
5381     anArgCase.LowerCase();
5382     Standard_Boolean toEnableDebug = Standard_True;
5383     if (anArgCase == "-glsl"
5384      || anArgCase == "-glslwarn"
5385      || anArgCase == "-glslwarns"
5386      || anArgCase == "-glslwarnings")
5387     {
5388       Standard_Boolean toShowWarns = Standard_True;
5389       if (++anArgIter < theArgNb
5390       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5391       {
5392         --anArgIter;
5393       }
5394       aDefCaps->glslWarnings = toShowWarns;
5395       if (aCaps != NULL)
5396       {
5397         aCaps->glslWarnings = toShowWarns;
5398       }
5399     }
5400     else if (anArgCase == "-extra"
5401           || anArgCase == "-extramsg"
5402           || anArgCase == "-extramessages")
5403     {
5404       Standard_Boolean toShow = Standard_True;
5405       if (++anArgIter < theArgNb
5406       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5407       {
5408         --anArgIter;
5409       }
5410       aDefCaps->suppressExtraMsg = !toShow;
5411       if (aCaps != NULL)
5412       {
5413         aCaps->suppressExtraMsg = !toShow;
5414       }
5415     }
5416     else if (anArgCase == "-noextra"
5417           || anArgCase == "-noextramsg"
5418           || anArgCase == "-noextramessages")
5419     {
5420       Standard_Boolean toSuppress = Standard_True;
5421       if (++anArgIter < theArgNb
5422       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5423       {
5424         --anArgIter;
5425       }
5426       aDefCaps->suppressExtraMsg = toSuppress;
5427       if (aCaps != NULL)
5428       {
5429         aCaps->suppressExtraMsg = toSuppress;
5430       }
5431     }
5432     else if (anArgCase == "-sync")
5433     {
5434       Standard_Boolean toSync = Standard_True;
5435       if (++anArgIter < theArgNb
5436       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5437       {
5438         --anArgIter;
5439       }
5440       aDefCaps->contextSyncDebug = toSync;
5441       if (toSync)
5442       {
5443         aDefCaps->contextDebug = Standard_True;
5444       }
5445     }
5446     else if (anArgCase == "-debug")
5447     {
5448       if (++anArgIter < theArgNb
5449       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5450       {
5451         --anArgIter;
5452       }
5453       aDefCaps->contextDebug = toEnableDebug;
5454     }
5455     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5456           && (anArgIter + 1 == theArgNb))
5457     {
5458       // simple alias to turn on almost everything
5459       aDefCaps->contextDebug     = toEnableDebug;
5460       aDefCaps->contextSyncDebug = toEnableDebug;
5461       aDefCaps->glslWarnings     = toEnableDebug;
5462     }
5463     else
5464     {
5465       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5466       return 1;
5467     }
5468   }
5469
5470   return 0;
5471 }
5472
5473 //==============================================================================
5474 //function : VVbo
5475 //purpose  :
5476 //==============================================================================
5477
5478 static int VVbo (Draw_Interpretor& theDI,
5479                  Standard_Integer  theArgNb,
5480                  const char**      theArgVec)
5481 {
5482   const Standard_Boolean toSet    = (theArgNb > 1);
5483   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5484   if (toSet)
5485   {
5486     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5487   }
5488
5489   // get the context
5490   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5491   if (aContextAIS.IsNull())
5492   {
5493     if (!toSet)
5494     {
5495       std::cerr << "No active view!\n";
5496     }
5497     return 1;
5498   }
5499   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5500   if (!aDriver.IsNull())
5501   {
5502     if (!toSet)
5503     {
5504       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5505     }
5506     else
5507     {
5508       aDriver->ChangeOptions().vboDisable = toUseVbo;
5509     }
5510   }
5511
5512   return 0;
5513 }
5514
5515 //==============================================================================
5516 //function : VCaps
5517 //purpose  :
5518 //==============================================================================
5519
5520 static int VCaps (Draw_Interpretor& theDI,
5521                   Standard_Integer  theArgNb,
5522                   const char**      theArgVec)
5523 {
5524   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5525   Handle(OpenGl_GraphicDriver)   aDriver;
5526   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5527   if (!aContext.IsNull())
5528   {
5529     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5530     aCaps   = &aDriver->ChangeOptions();
5531   }
5532
5533   if (theArgNb < 2)
5534   {
5535     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5536     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5537     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5538     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5539     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5540     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5541     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5542     return 0;
5543   }
5544
5545   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5546   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5547   {
5548     Standard_CString        anArg     = theArgVec[anArgIter];
5549     TCollection_AsciiString anArgCase (anArg);
5550     anArgCase.LowerCase();
5551     if (anUpdateTool.parseRedrawMode (anArg))
5552     {
5553       continue;
5554     }
5555     else if (anArgCase == "-vsync"
5556           || anArgCase == "-swapinterval")
5557     {
5558       Standard_Boolean toEnable = Standard_True;
5559       if (++anArgIter < theArgNb
5560       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5561       {
5562         --anArgIter;
5563       }
5564       aCaps->swapInterval = toEnable;
5565     }
5566     else if (anArgCase == "-ffp")
5567     {
5568       Standard_Boolean toEnable = Standard_True;
5569       if (++anArgIter < theArgNb
5570       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5571       {
5572         --anArgIter;
5573       }
5574       aCaps->ffpEnable = toEnable;
5575     }
5576     else if (anArgCase == "-vbo")
5577     {
5578       Standard_Boolean toEnable = Standard_True;
5579       if (++anArgIter < theArgNb
5580       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5581       {
5582         --anArgIter;
5583       }
5584       aCaps->vboDisable = !toEnable;
5585     }
5586     else if (anArgCase == "-sprite"
5587           || anArgCase == "-sprites")
5588     {
5589       Standard_Boolean toEnable = Standard_True;
5590       if (++anArgIter < theArgNb
5591       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5592       {
5593         --anArgIter;
5594       }
5595       aCaps->pntSpritesDisable = !toEnable;
5596     }
5597     else if (anArgCase == "-softmode")
5598     {
5599       Standard_Boolean toEnable = Standard_True;
5600       if (++anArgIter < theArgNb
5601       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5602       {
5603         --anArgIter;
5604       }
5605       aCaps->contextNoAccel = toEnable;
5606     }
5607     else if (anArgCase == "-accel"
5608           || anArgCase == "-acceleration")
5609     {
5610       Standard_Boolean toEnable = Standard_True;
5611       if (++anArgIter < theArgNb
5612       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5613       {
5614         --anArgIter;
5615       }
5616       aCaps->contextNoAccel = !toEnable;
5617     }
5618     else if (anArgCase == "-compat"
5619           || anArgCase == "-compatprofile"
5620           || anArgCase == "-compatible"
5621           || anArgCase == "-compatibleprofile")
5622     {
5623       Standard_Boolean toEnable = Standard_True;
5624       if (++anArgIter < theArgNb
5625       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5626       {
5627         --anArgIter;
5628       }
5629       aCaps->contextCompatible = toEnable;
5630       if (!aCaps->contextCompatible)
5631       {
5632         aCaps->ffpEnable = Standard_False;
5633       }
5634     }
5635     else if (anArgCase == "-core"
5636           || anArgCase == "-coreprofile")
5637     {
5638       Standard_Boolean toEnable = Standard_True;
5639       if (++anArgIter < theArgNb
5640       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5641       {
5642         --anArgIter;
5643       }
5644       aCaps->contextCompatible = !toEnable;
5645       if (!aCaps->contextCompatible)
5646       {
5647         aCaps->ffpEnable = Standard_False;
5648       }
5649     }
5650     else if (anArgCase == "-stereo"
5651           || anArgCase == "-quadbuffer")
5652     {
5653       Standard_Boolean toEnable = Standard_True;
5654       if (++anArgIter < theArgNb
5655       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5656       {
5657         --anArgIter;
5658       }
5659       aCaps->contextStereo = toEnable;
5660     }
5661     else
5662     {
5663       std::cout << "Error: unknown argument '" << anArg << "'\n";
5664       return 1;
5665     }
5666   }
5667   if (aCaps != &ViewerTest_myDefaultCaps)
5668   {
5669     ViewerTest_myDefaultCaps = *aCaps;
5670   }
5671   return 0;
5672 }
5673
5674 //==============================================================================
5675 //function : VMemGpu
5676 //purpose  :
5677 //==============================================================================
5678
5679 static int VMemGpu (Draw_Interpretor& theDI,
5680                     Standard_Integer  theArgNb,
5681                     const char**      theArgVec)
5682 {
5683   // get the context
5684   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5685   if (aContextAIS.IsNull())
5686   {
5687     std::cerr << "No active view. Please call vinit.\n";
5688     return 1;
5689   }
5690
5691   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5692   if (aDriver.IsNull())
5693   {
5694     std::cerr << "Graphic driver not available.\n";
5695     return 1;
5696   }
5697
5698   Standard_Size aFreeBytes = 0;
5699   TCollection_AsciiString anInfo;
5700   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5701   {
5702     std::cerr << "Information not available.\n";
5703     return 1;
5704   }
5705
5706   if (theArgNb > 1 && *theArgVec[1] == 'f')
5707   {
5708     theDI << Standard_Real (aFreeBytes);
5709   }
5710   else
5711   {
5712     theDI << anInfo;
5713   }
5714
5715   return 0;
5716 }
5717
5718 // ==============================================================================
5719 // function : VReadPixel
5720 // purpose  :
5721 // ==============================================================================
5722 static int VReadPixel (Draw_Interpretor& theDI,
5723                        Standard_Integer  theArgNb,
5724                        const char**      theArgVec)
5725 {
5726   // get the active view
5727   Handle(V3d_View) aView = ViewerTest::CurrentView();
5728   if (aView.IsNull())
5729   {
5730     std::cerr << "No active view. Please call vinit.\n";
5731     return 1;
5732   }
5733   else if (theArgNb < 3)
5734   {
5735     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5736     return 1;
5737   }
5738
5739   Image_PixMap::ImgFormat aFormat     = Image_PixMap::ImgRGBA;
5740   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
5741
5742   Standard_Integer aWidth, aHeight;
5743   aView->Window()->Size (aWidth, aHeight);
5744   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5745   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5746   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5747   {
5748     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5749     return 1;
5750   }
5751
5752   Standard_Boolean toShowName = Standard_False;
5753   Standard_Boolean toShowHls  = Standard_False;
5754   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5755   {
5756     const char* aParam = theArgVec[anIter];
5757     if ( strcasecmp( aParam, "rgb" ) == 0 )
5758     {
5759       aFormat     = Image_PixMap::ImgRGB;
5760       aBufferType = Graphic3d_BT_RGB;
5761     }
5762     else if ( strcasecmp( aParam, "hls" ) == 0 )
5763     {
5764       aFormat     = Image_PixMap::ImgRGB;
5765       aBufferType = Graphic3d_BT_RGB;
5766       toShowHls   = Standard_True;
5767     }
5768     else if ( strcasecmp( aParam, "rgbf" ) == 0 )
5769     {
5770       aFormat     = Image_PixMap::ImgRGBF;
5771       aBufferType = Graphic3d_BT_RGB;
5772     }
5773     else if ( strcasecmp( aParam, "rgba" ) == 0 )
5774     {
5775       aFormat     = Image_PixMap::ImgRGBA;
5776       aBufferType = Graphic3d_BT_RGBA;
5777     }
5778     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
5779     {
5780       aFormat     = Image_PixMap::ImgRGBAF;
5781       aBufferType = Graphic3d_BT_RGBA;
5782     }
5783     else if ( strcasecmp( aParam, "depth" ) == 0 )
5784     {
5785       aFormat     = Image_PixMap::ImgGrayF;
5786       aBufferType = Graphic3d_BT_Depth;
5787     }
5788     else if ( strcasecmp( aParam, "name" ) == 0 )
5789     {
5790       toShowName = Standard_True;
5791     }
5792   }
5793
5794   Image_PixMap anImage;
5795   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5796   {
5797     std::cerr << "Image allocation failed\n";
5798     return 1;
5799   }
5800   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5801   {
5802     std::cerr << "Image dump failed\n";
5803     return 1;
5804   }
5805
5806   Quantity_Parameter anAlpha;
5807   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5808   if (toShowName)
5809   {
5810     if (aBufferType == Graphic3d_BT_RGBA)
5811     {
5812       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5813     }
5814     else
5815     {
5816       theDI << Quantity_Color::StringName (aColor.Name());
5817     }
5818   }
5819   else
5820   {
5821     switch (aBufferType)
5822     {
5823       default:
5824       case Graphic3d_BT_RGB:
5825       {
5826         if (toShowHls)
5827         {
5828           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5829         }
5830         else
5831         {
5832           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5833         }
5834         break;
5835       }
5836       case Graphic3d_BT_RGBA:
5837       {
5838         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5839         break;
5840       }
5841       case Graphic3d_BT_Depth:
5842       {
5843         theDI << aColor.Red();
5844         break;
5845       }
5846     }
5847   }
5848
5849   return 0;
5850 }
5851
5852 //==============================================================================
5853 //function : VDiffImage
5854 //purpose  : The draw-command compares two images.
5855 //==============================================================================
5856
5857 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5858 {
5859   if (theArgNb < 6)
5860   {
5861     theDI << "Not enough arguments.\n";
5862     return 1;
5863   }
5864
5865   // image file names
5866   const char* anImgPathRef = theArgVec[1];
5867   const char* anImgPathNew = theArgVec[2];
5868
5869   // get string tolerance and check its validity
5870   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5871   if (aTolColor < 0.0)
5872     aTolColor = 0.0;
5873   if (aTolColor > 1.0)
5874     aTolColor = 1.0;
5875
5876   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5877   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5878
5879   // image file of difference
5880   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5881
5882   // compare the images
5883   Image_Diff aComparer;
5884   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5885   {
5886     return 1;
5887   }
5888
5889   aComparer.SetColorTolerance (aTolColor);
5890   aComparer.SetBorderFilterOn (isBorderFilterOn);
5891   Standard_Integer aDiffColorsNb = aComparer.Compare();
5892   theDI << aDiffColorsNb << "\n";
5893
5894   // save image of difference
5895   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5896   {
5897     aComparer.SaveDiffImage (aDiffImagePath);
5898   }
5899
5900   return 0;
5901 }
5902
5903 //=======================================================================
5904 //function : VSelect
5905 //purpose  : Emulates different types of selection by mouse:
5906 //           1) single click selection
5907 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5908 //           3) selection with polygon having corners at
5909 //           pixel positions (x1,y1),...,(xn,yn)
5910 //           4) any of these selections with shift button pressed
5911 //=======================================================================
5912 static Standard_Integer VSelect (Draw_Interpretor& di,
5913                                  Standard_Integer argc,
5914                                  const char ** argv)
5915 {
5916   if(argc < 3)
5917   {
5918     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5919     return 1;
5920   }
5921
5922   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5923   if(myAIScontext.IsNull())
5924   {
5925     di << "use 'vinit' command before " << argv[0] << "\n";
5926     return 1;
5927   }
5928
5929   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5930   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5931   TCollection_AsciiString anArg;
5932   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5933   anArg.LowerCase();
5934   if (anArg == "-allowoverlap")
5935   {
5936     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5937       : argc == 7;
5938     if (!isValidated)
5939     {
5940       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5941       return 1;
5942     }
5943
5944     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5945     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5946     aCoordsNb -= 2;
5947   }
5948
5949   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5950   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5951   if(aCoordsNb == 2)
5952   {
5953     if(isShiftSelection)
5954       aCurrentEventManager->ShiftSelect();
5955     else
5956       aCurrentEventManager->Select();
5957   }
5958   else if(aCoordsNb == 4)
5959   {
5960     if(isShiftSelection)
5961       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5962     else
5963       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5964   }
5965   else
5966   {
5967     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
5968
5969     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
5970       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
5971
5972     if(isShiftSelection)
5973       aCurrentEventManager->ShiftSelect(aPolyline);
5974     else
5975       aCurrentEventManager->Select(aPolyline);
5976   }
5977   return 0;
5978 }
5979
5980 //=======================================================================
5981 //function : VMoveTo
5982 //purpose  : Emulates cursor movement to defined pixel position
5983 //=======================================================================
5984 static Standard_Integer VMoveTo (Draw_Interpretor& di,
5985                                 Standard_Integer argc,
5986                                 const char ** argv)
5987 {
5988   if(argc != 3)
5989   {
5990     di << "Usage : " << argv[0] << " x y\n";
5991     return 1;
5992   }
5993
5994   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5995   if(aContext.IsNull())
5996   {
5997     di << "use 'vinit' command before " << argv[0] << "\n";
5998     return 1;
5999   }
6000   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6001   return 0;
6002 }
6003
6004 namespace
6005 {
6006   //! Global map storing all animations registered in ViewerTest.
6007   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6008
6009   //! The animation calling the Draw Harness command.
6010   class ViewerTest_AnimationProc : public AIS_Animation
6011   {
6012   public:
6013
6014     //! Main constructor.
6015     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6016                               Draw_Interpretor* theDI,
6017                               const TCollection_AsciiString& theCommand)
6018     : AIS_Animation (theAnimationName),
6019       myDrawInter(theDI),
6020       myCommand  (theCommand)
6021     {
6022       //
6023     }
6024
6025   protected:
6026
6027     //! Evaluate the command.
6028     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6029     {
6030       TCollection_AsciiString aCmd = myCommand;
6031       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6032       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6033       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6034       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6035       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6036       myDrawInter->Eval (aCmd.ToCString());
6037     }
6038
6039     //! Find the keyword in the command and replace it with value.
6040     //! @return the position of the keyword to pass value
6041     void replace (TCollection_AsciiString&       theCmd,
6042                   const TCollection_AsciiString& theKey,
6043                   const TCollection_AsciiString& theVal)
6044     {
6045       TCollection_AsciiString aCmd (theCmd);
6046       aCmd.LowerCase();
6047       const Standard_Integer aPos = aCmd.Search (theKey);
6048       if (aPos == -1)
6049       {
6050         return;
6051       }
6052
6053       TCollection_AsciiString aPart1, aPart2;
6054       Standard_Integer aPart1To = aPos - 1;
6055       if (aPart1To >= 1
6056        && aPart1To <= theCmd.Length())
6057       {
6058         aPart1 = theCmd.SubString (1, aPart1To);
6059       }
6060
6061       Standard_Integer aPart2From = aPos + theKey.Length();
6062       if (aPart2From >= 1
6063        && aPart2From <= theCmd.Length())
6064       {
6065         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6066       }
6067
6068       theCmd = aPart1 + theVal + aPart2;
6069     }
6070
6071   protected:
6072
6073     Draw_Interpretor*       myDrawInter;
6074     TCollection_AsciiString myCommand;
6075
6076   };
6077
6078   //! Replace the animation with the new one.
6079   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6080                                 Handle(AIS_Animation)&       theAnimation,
6081                                 const Handle(AIS_Animation)& theAnimationNew)
6082   {
6083     theAnimationNew->CopyFrom (theAnimation);
6084     if (!theParentAnimation.IsNull())
6085     {
6086       theParentAnimation->Replace (theAnimation, theAnimationNew);
6087     }
6088     else
6089     {
6090       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6091       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6092     }
6093     theAnimation = theAnimationNew;
6094   }
6095
6096   //! Parse the point.
6097   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6098   {
6099     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6100     if (!anXYZ[0].IsRealValue()
6101      || !anXYZ[1].IsRealValue()
6102      || !anXYZ[2].IsRealValue())
6103     {
6104       return Standard_False;
6105     }
6106
6107     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6108     return Standard_True;
6109   }
6110
6111   //! Parse the quaternion.
6112   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6113   {
6114     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6115     if (!anXYZW[0].IsRealValue()
6116      || !anXYZW[1].IsRealValue()
6117      || !anXYZW[2].IsRealValue()
6118      || !anXYZW[3].IsRealValue())
6119     {
6120       return Standard_False;
6121     }
6122
6123     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6124     return Standard_True;
6125   }
6126
6127 }
6128
6129 //=================================================================================================
6130 //function : VViewParams
6131 //purpose  : Gets or sets AIS View characteristics
6132 //=================================================================================================
6133 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6134 {
6135   Handle(V3d_View) aView = ViewerTest::CurrentView();
6136   if (aView.IsNull())
6137   {
6138     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6139     return 1;
6140   }
6141
6142   Standard_Boolean toSetProj     = Standard_False;
6143   Standard_Boolean toSetUp       = Standard_False;
6144   Standard_Boolean toSetAt       = Standard_False;
6145   Standard_Boolean toSetEye      = Standard_False;
6146   Standard_Boolean toSetScale    = Standard_False;
6147   Standard_Boolean toSetSize     = Standard_False;
6148   Standard_Boolean toSetCenter2d = Standard_False;
6149   Quantity_Factor  aViewScale = aView->Scale();
6150   Quantity_Length  aViewSize  = 1.0;
6151   Graphic3d_Vec2i  aCenter2d;
6152   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6153   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6154   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6155   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6156   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6157   if (theArgsNb == 1)
6158   {
6159     // print all of the available view parameters
6160     char aText[4096];
6161     Sprintf (aText,
6162              "Scale: %g\n"
6163              "Proj:  %12g %12g %12g\n"
6164              "Up:    %12g %12g %12g\n"
6165              "At:    %12g %12g %12g\n"
6166              "Eye:   %12g %12g %12g\n",
6167               aViewScale,
6168               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6169               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6170               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6171               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6172     theDi << aText;
6173     return 0;
6174   }
6175
6176   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6177   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6178   {
6179     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6180     anArg.LowerCase();
6181     if (anUpdateTool.parseRedrawMode (anArg))
6182     {
6183       continue;
6184     }
6185     else if (anArg == "-cmd"
6186           || anArg == "-command"
6187           || anArg == "-args")
6188     {
6189       char aText[4096];
6190       Sprintf (aText,
6191                "-scale %g "
6192                "-proj %g %g %g "
6193                "-up %g %g %g "
6194                "-at %g %g %g\n",
6195                 aViewScale,
6196                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6197                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6198                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6199       theDi << aText;
6200     }
6201     else if (anArg == "-scale"
6202           || anArg == "-size")
6203     {
6204       if (anArgIter + 1 < theArgsNb
6205        && *theArgVec[anArgIter + 1] != '-')
6206       {
6207         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6208         if (aValueArg.IsRealValue())
6209         {
6210           ++anArgIter;
6211           if (anArg == "-scale")
6212           {
6213             toSetScale = Standard_True;
6214             aViewScale = aValueArg.RealValue();
6215           }
6216           else if (anArg == "-size")
6217           {
6218             toSetSize = Standard_True;
6219             aViewSize = aValueArg.RealValue();
6220           }
6221           continue;
6222         }
6223       }
6224       if (anArg == "-scale")
6225       {
6226         theDi << "Scale: " << aView->Scale() << "\n";
6227       }
6228       else if (anArg == "-size")
6229       {
6230         Graphic3d_Vec2d aSizeXY;
6231         aView->Size (aSizeXY.x(), aSizeXY.y());
6232         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6233       }
6234     }
6235     else if (anArg == "-eye"
6236           || anArg == "-at"
6237           || anArg == "-up"
6238           || anArg == "-proj")
6239     {
6240       if (anArgIter + 3 < theArgsNb)
6241       {
6242         gp_XYZ anXYZ;
6243         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6244         {
6245           anArgIter += 3;
6246           if (anArg == "-eye")
6247           {
6248             toSetEye = Standard_True;
6249             aViewEye = anXYZ;
6250           }
6251           else if (anArg == "-at")
6252           {
6253             toSetAt = Standard_True;
6254             aViewAt = anXYZ;
6255           }
6256           else if (anArg == "-up")
6257           {
6258             toSetUp = Standard_True;
6259             aViewUp = anXYZ;
6260           }
6261           else if (anArg == "-proj")
6262           {
6263             toSetProj = Standard_True;
6264             aViewProj = anXYZ;
6265           }
6266           continue;
6267         }
6268       }
6269
6270       if (anArg == "-eye")
6271       {
6272         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6273       }
6274       else if (anArg == "-at")
6275       {
6276         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6277       }
6278       else if (anArg == "-up")
6279       {
6280         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6281       }
6282       else if (anArg == "-proj")
6283       {
6284         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6285       }
6286     }
6287     else if (anArg == "-center")
6288     {
6289       if (anArgIter + 2 < theArgsNb)
6290       {
6291         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6292         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6293         if (anX.IsIntegerValue()
6294          && anY.IsIntegerValue())
6295         {
6296           toSetCenter2d = Standard_True;
6297           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6298         }
6299       }
6300     }
6301     else
6302     {
6303       std::cout << "Syntax error at '" << anArg << "'\n";
6304       return 1;
6305     }
6306   }
6307
6308   // change view parameters in proper order
6309   if (toSetScale)
6310   {
6311     aView->SetScale (aViewScale);
6312   }
6313   if (toSetSize)
6314   {
6315     aView->SetSize (aViewSize);
6316   }
6317   if (toSetEye)
6318   {
6319     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6320   }
6321   if (toSetAt)
6322   {
6323     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6324   }
6325   if (toSetProj)
6326   {
6327     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6328   }
6329   if (toSetUp)
6330   {
6331     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6332   }
6333   if (toSetCenter2d)
6334   {
6335     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6336   }
6337
6338   return 0;
6339 }
6340
6341 //==============================================================================
6342 //function : VAnimation
6343 //purpose  :
6344 //==============================================================================
6345 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6346                                     Standard_Integer  theArgNb,
6347                                     const char**      theArgVec)
6348 {
6349   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6350   if (theArgNb < 2)
6351   {
6352     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6353          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6354     {
6355       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6356     }
6357     return 0;
6358   }
6359   if (aCtx.IsNull())
6360   {
6361     std::cout << "Error: no active view\n";
6362     return 1;
6363   }
6364
6365   Standard_Integer anArgIter = 1;
6366   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6367   if (aNameArg.IsEmpty())
6368   {
6369     std::cout << "Syntax error: animation name is not defined.\n";
6370     return 1;
6371   }
6372
6373   TCollection_AsciiString aNameArgLower = aNameArg;
6374   aNameArgLower.LowerCase();
6375   if (aNameArgLower == "-reset"
6376    || aNameArgLower == "-clear")
6377   {
6378     ViewerTest_AnimationTimelineMap.Clear();
6379     return 0;
6380   }
6381   else if (aNameArg.Value (1) == '-')
6382   {
6383     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6384     return 1;
6385   }
6386
6387   const char* aNameSplitter = "/";
6388   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6389   if (aSplitPos == -1)
6390   {
6391     aNameSplitter = ".";
6392     aSplitPos = aNameArg.Search (aNameSplitter);
6393   }
6394
6395   // find existing or create a new animation by specified name within syntax "parent.child".
6396   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6397   for (; !aNameArg.IsEmpty();)
6398   {
6399     TCollection_AsciiString aNameParent;
6400     if (aSplitPos != -1)
6401     {
6402       if (aSplitPos == aNameArg.Length())
6403       {
6404         std::cout << "Syntax error: animation name is not defined.\n";
6405         return 1;
6406       }
6407
6408       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6409       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6410
6411       aSplitPos = aNameArg.Search (aNameSplitter);
6412     }
6413     else
6414     {
6415       aNameParent = aNameArg;
6416       aNameArg.Clear();
6417     }
6418
6419     if (anAnimation.IsNull())
6420     {
6421       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6422       {
6423         anAnimation = new AIS_Animation (aNameParent);
6424         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6425       }
6426       aRootAnimation = anAnimation;
6427     }
6428     else
6429     {
6430       aParentAnimation = anAnimation;
6431       anAnimation = aParentAnimation->Find (aNameParent);
6432       if (anAnimation.IsNull())
6433       {
6434         anAnimation = new AIS_Animation (aNameParent);
6435         aParentAnimation->Add (anAnimation);
6436       }
6437     }
6438   }
6439
6440   if (anArgIter >= theArgNb)
6441   {
6442     // just print the list of children
6443     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
6444     {
6445       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
6446     }
6447     return 0;
6448   }
6449
6450   // animation parameters
6451   Standard_Boolean toPlay = Standard_False;
6452   Standard_Real aPlaySpeed     = 1.0;
6453   Standard_Real aPlayStartTime = anAnimation->StartPts();
6454   Standard_Real aPlayDuration  = anAnimation->Duration();
6455   Standard_Integer aFpsNum     = 0;
6456   Standard_Integer aFpsDen     = 1;
6457   Standard_Boolean isFreeCamera = Standard_False;
6458   Standard_Boolean isLockLoop   = Standard_False;
6459   Handle(V3d_View) aView = ViewerTest::CurrentView();
6460   for (; anArgIter < theArgNb; ++anArgIter)
6461   {
6462     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6463     anArg.LowerCase();
6464     // general options
6465     if (anArg == "-reset"
6466      || anArg == "-clear")
6467     {
6468       anAnimation->Clear();
6469     }
6470     else if (anArg == "-remove"
6471           || anArg == "-del"
6472           || anArg == "-delete")
6473     {
6474       if (!aParentAnimation.IsNull())
6475       {
6476         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
6477       }
6478       else
6479       {
6480         aParentAnimation->Remove (anAnimation);
6481       }
6482     }
6483     // playback options
6484     else if (anArg == "-play")
6485     {
6486       toPlay = Standard_True;
6487       if (++anArgIter < theArgNb)
6488       {
6489         if (*theArgVec[anArgIter] == '-')
6490         {
6491           --anArgIter;
6492           continue;
6493         }
6494         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
6495
6496         if (++anArgIter < theArgNb)
6497         {
6498           if (*theArgVec[anArgIter] == '-')
6499           {
6500             --anArgIter;
6501             continue;
6502           }
6503           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6504         }
6505       }
6506     }
6507     else if (anArg == "-resume")
6508     {
6509       toPlay = Standard_True;
6510       aPlayStartTime = anAnimation->ElapsedTime();
6511       if (++anArgIter < theArgNb)
6512       {
6513         if (*theArgVec[anArgIter] == '-')
6514         {
6515           --anArgIter;
6516           continue;
6517         }
6518
6519         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6520       }
6521     }
6522     else if (anArg == "-playspeed"
6523           || anArg == "-speed")
6524     {
6525       if (++anArgIter >= theArgNb)
6526       {
6527         std::cout << "Syntax error at " << anArg << ".\n";
6528         return 1;
6529       }
6530       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
6531     }
6532     else if (anArg == "-lock"
6533           || anArg == "-lockloop"
6534           || anArg == "-playlockloop")
6535     {
6536       isLockLoop = Standard_True;
6537     }
6538     else if (anArg == "-freecamera"
6539           || anArg == "-playfreecamera"
6540           || anArg == "-freelook")
6541     {
6542       isFreeCamera = Standard_True;
6543     }
6544     else if (anArg == "-fps")
6545     {
6546       if (++anArgIter >= theArgNb)
6547       {
6548         std::cout << "Syntax error at " << anArg << ".\n";
6549         return 1;
6550       }
6551
6552       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
6553       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
6554       if (aSplitIndex == 0)
6555       {
6556         aFpsNum = aFpsArg.IntegerValue();
6557       }
6558       else
6559       {
6560         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
6561         aFpsArg.Split (aFpsArg.Length() - 1);
6562         const TCollection_AsciiString aNumStr = aFpsArg;
6563         aFpsNum = aNumStr.IntegerValue();
6564         aFpsDen = aDenStr.IntegerValue();
6565         if (aFpsDen < 1)
6566         {
6567           std::cout << "Syntax error at " << anArg << ".\n";
6568           return 1;
6569         }
6570       }
6571     }
6572     // animation definition options
6573     else if (anArg == "-start"
6574           || anArg == "-starttime"
6575           || anArg == "-startpts")
6576     {
6577       if (++anArgIter >= theArgNb)
6578       {
6579         std::cout << "Syntax error at " << anArg << ".\n";
6580         return 1;
6581       }
6582
6583       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
6584       aRootAnimation->UpdateTotalDuration();
6585     }
6586     else if (anArg == "-end"
6587           || anArg == "-endtime"
6588           || anArg == "-endpts")
6589     {
6590       if (++anArgIter >= theArgNb)
6591       {
6592         std::cout << "Syntax error at " << anArg << ".\n";
6593         return 1;
6594       }
6595
6596       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
6597       aRootAnimation->UpdateTotalDuration();
6598     }
6599     else if (anArg == "-dur"
6600           || anArg == "-duration")
6601     {
6602       if (++anArgIter >= theArgNb)
6603       {
6604         std::cout << "Syntax error at " << anArg << ".\n";
6605         return 1;
6606       }
6607
6608       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
6609       aRootAnimation->UpdateTotalDuration();
6610     }
6611     else if (anArg == "-command"
6612           || anArg == "-cmd"
6613           || anArg == "-invoke"
6614           || anArg == "-eval"
6615           || anArg == "-proc")
6616     {
6617       if (++anArgIter >= theArgNb)
6618       {
6619         std::cout << "Syntax error at " << anArg << ".\n";
6620         return 1;
6621       }
6622
6623       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
6624       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
6625     }
6626     else if (anArg == "-objecttrsf"
6627           || anArg == "-objectransformation"
6628           || anArg == "-objtransformation"
6629           || anArg == "-objtrsf"
6630           || anArg == "-object"
6631           || anArg == "-obj")
6632     {
6633       if (++anArgIter >= theArgNb)
6634       {
6635         std::cout << "Syntax error at " << anArg << ".\n";
6636         return 1;
6637       }
6638
6639       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
6640       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
6641       if (!aMapOfAIS.IsBound2 (anObjName))
6642       {
6643         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
6644         return 1;
6645       }
6646
6647       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
6648       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
6649       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
6650       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
6651       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
6652       Standard_Boolean isTrsfSet = Standard_False;
6653       Standard_Integer aTrsfArgIter = anArgIter + 1;
6654       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
6655       {
6656         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
6657         aTrsfArg.LowerCase();
6658         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
6659         if (aTrsfArg.StartsWith ("-rotation")
6660          || aTrsfArg.StartsWith ("-rot"))
6661         {
6662           isTrsfSet = Standard_True;
6663           if (aTrsfArgIter + 4 >= theArgNb
6664           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
6665           {
6666             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6667             return 1;
6668           }
6669           aTrsfArgIter += 4;
6670         }
6671         else if (aTrsfArg.StartsWith ("-location")
6672               || aTrsfArg.StartsWith ("-loc"))
6673         {
6674           isTrsfSet = Standard_True;
6675           if (aTrsfArgIter + 3 >= theArgNb
6676           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
6677           {
6678             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6679             return 1;
6680           }
6681           aTrsfArgIter += 3;
6682         }
6683         else if (aTrsfArg.StartsWith ("-scale"))
6684         {
6685           isTrsfSet = Standard_True;
6686           if (++aTrsfArgIter >= theArgNb)
6687           {
6688             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6689             return 1;
6690           }
6691
6692           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
6693           if (!aScaleStr.IsRealValue())
6694           {
6695             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6696             return 1;
6697           }
6698           aScales[anIndex] = aScaleStr.RealValue();
6699         }
6700         else
6701         {
6702           anArgIter = aTrsfArgIter - 1;
6703           break;
6704         }
6705       }
6706       if (!isTrsfSet)
6707       {
6708         std::cout << "Syntax error at " << anArg << ".\n";
6709         return 1;
6710       }
6711       else if (aTrsfArgIter >= theArgNb)
6712       {
6713         anArgIter = theArgNb;
6714       }
6715
6716       aTrsfs[0].SetRotation        (aRotQuats[0]);
6717       aTrsfs[1].SetRotation        (aRotQuats[1]);
6718       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
6719       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
6720       aTrsfs[0].SetScaleFactor     (aScales[0]);
6721       aTrsfs[1].SetScaleFactor     (aScales[1]);
6722
6723       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
6724       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
6725     }
6726     else if (anArg == "-viewtrsf"
6727           || anArg == "-view")
6728     {
6729       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
6730       if (aCamAnimation.IsNull())
6731       {
6732         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
6733         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
6734       }
6735
6736       Handle(Graphic3d_Camera) aCams[2] =
6737       {
6738         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
6739         new Graphic3d_Camera (aCamAnimation->View()->Camera())
6740       };
6741
6742       Standard_Boolean isTrsfSet = Standard_False;
6743       Standard_Integer aViewArgIter = anArgIter + 1;
6744       for (; aViewArgIter < theArgNb; ++aViewArgIter)
6745       {
6746         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
6747         aViewArg.LowerCase();
6748         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
6749         if (aViewArg.StartsWith ("-scale"))
6750         {
6751           isTrsfSet = Standard_True;
6752           if (++aViewArgIter >= theArgNb)
6753           {
6754             std::cout << "Syntax error at " << anArg << ".\n";
6755             return 1;
6756           }
6757
6758           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
6759           if (!aScaleStr.IsRealValue())
6760           {
6761             std::cout << "Syntax error at " << aViewArg << ".\n";
6762             return 1;
6763           }
6764           Standard_Real aScale = aScaleStr.RealValue();
6765           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
6766           aCams[anIndex]->SetScale (aScale);
6767         }
6768         else if (aViewArg.StartsWith ("-eye")
6769               || aViewArg.StartsWith ("-center")
6770               || aViewArg.StartsWith ("-at")
6771               || aViewArg.StartsWith ("-up"))
6772         {
6773           isTrsfSet = Standard_True;
6774           gp_XYZ anXYZ;
6775           if (aViewArgIter + 3 >= theArgNb
6776           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
6777           {
6778             std::cout << "Syntax error at " << aViewArg << ".\n";
6779             return 1;
6780           }
6781           aViewArgIter += 3;
6782
6783           if (aViewArg.StartsWith ("-eye"))
6784           {
6785             aCams[anIndex]->SetEye (anXYZ);
6786           }
6787           else if (aViewArg.StartsWith ("-center")
6788                 || aViewArg.StartsWith ("-at"))
6789           {
6790             aCams[anIndex]->SetCenter (anXYZ);
6791           }
6792           else if (aViewArg.StartsWith ("-up"))
6793           {
6794             aCams[anIndex]->SetUp (anXYZ);
6795           }
6796         }
6797         else
6798         {
6799           anArgIter = aViewArgIter - 1;
6800           break;
6801         }
6802       }
6803       if (!isTrsfSet)
6804       {
6805         std::cout << "Syntax error at " << anArg << ".\n";
6806         return 1;
6807       }
6808       else if (aViewArgIter >= theArgNb)
6809       {
6810         anArgIter = theArgNb;
6811       }
6812
6813       aCamAnimation->SetCameraStart(aCams[0]);
6814       aCamAnimation->SetCameraEnd  (aCams[1]);
6815     }
6816     else
6817     {
6818       std::cout << "Syntax error at " << anArg << ".\n";
6819       return 1;
6820     }
6821   }
6822
6823   if (!toPlay)
6824   {
6825     return 0;
6826   }
6827
6828   // Start animation timeline and process frame updating.
6829   TheIsAnimating = Standard_True;
6830   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
6831   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
6832   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
6833   if (isFreeCamera)
6834   {
6835     aView->Camera()->Copy (aCameraBack);
6836   }
6837
6838   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
6839   if (aFpsNum <= 0)
6840   {
6841     while (!anAnimation->IsStopped())
6842     {
6843       aCameraBack->Copy (aView->Camera());
6844       const Standard_Real aPts = anAnimation->UpdateTimer();
6845       if (isFreeCamera)
6846       {
6847         aView->Camera()->Copy (aCameraBack);
6848       }
6849
6850       if (aPts >= anUpperPts)
6851       {
6852         anAnimation->Pause();
6853         break;
6854       }
6855
6856       if (aView->IsInvalidated())
6857       {
6858         aView->Redraw();
6859       }
6860       else
6861       {
6862         aView->RedrawImmediate();
6863       }
6864
6865       if (!isLockLoop)
6866       {
6867         // handle user events
6868         theDI.Eval ("after 1 set waiter 1");
6869         theDI.Eval ("vwait waiter");
6870       }
6871       if (!TheIsAnimating)
6872       {
6873         anAnimation->Pause();
6874         theDI << aPts;
6875         break;
6876       }
6877     }
6878
6879     if (aView->IsInvalidated())
6880     {
6881       aView->Redraw();
6882     }
6883     else
6884     {
6885       aView->RedrawImmediate();
6886     }
6887   }
6888   else
6889   {
6890     OSD_Timer aPerfTimer;
6891     aPerfTimer.Start();
6892
6893     // Manage frame-rated animation here
6894     Standard_Real aPts = aPlayStartTime;
6895     int64_t aNbFrames = 0;
6896     for (; aPts <= anUpperPts;)
6897     {
6898       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
6899       aPts = aPlayStartTime + aRecPts;
6900       ++aNbFrames;
6901       if (!anAnimation->Update (aPts))
6902       {
6903         break;
6904       }
6905
6906       aView->Redraw();
6907     }
6908
6909     aPerfTimer.Stop();
6910     anAnimation->Stop();
6911     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
6912     theDI << "Average FPS: " << aRecFps << "\n"
6913           << "Nb. Frames: "  << Standard_Real(aNbFrames);
6914
6915     aView->Redraw();
6916   }
6917
6918   aView->SetImmediateUpdate (wasImmediateUpdate);
6919   TheIsAnimating = Standard_False;
6920   return 0;
6921 }
6922
6923
6924 //=======================================================================
6925 //function : VChangeSelected
6926 //purpose  : Adds the shape to selection or remove one from it
6927 //=======================================================================
6928 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6929                                 Standard_Integer argc,
6930                                 const char ** argv)
6931 {
6932   if(argc != 2)
6933   {
6934     di<<"Usage : " << argv[0] << " shape \n";
6935     return 1;
6936   }
6937   //get AIS_Shape:
6938   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6939   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6940   TCollection_AsciiString aName(argv[1]);
6941   Handle(AIS_InteractiveObject) anAISObject;
6942
6943   if(!aMap.IsBound2(aName))
6944   {
6945     di<<"Use 'vdisplay' before";
6946     return 1;
6947   }
6948   else
6949   {
6950     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6951     if(anAISObject.IsNull()){
6952       di<<"No interactive object \n";
6953       return 1;
6954     }
6955
6956     aContext->AddOrRemoveSelected(anAISObject);
6957   }
6958   return 0;
6959 }
6960
6961 //=======================================================================
6962 //function : VNbSelected
6963 //purpose  : Returns number of selected objects
6964 //=======================================================================
6965 static Standard_Integer VNbSelected (Draw_Interpretor& di,
6966                                 Standard_Integer argc,
6967                                 const char ** argv)
6968 {
6969   if(argc != 1)
6970   {
6971     di << "Usage : " << argv[0] << "\n";
6972     return 1;
6973   }
6974   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6975   if(aContext.IsNull())
6976   {
6977     di << "use 'vinit' command before " << argv[0] << "\n";
6978     return 1;
6979   }
6980   di << aContext->NbSelected() << "\n";
6981   return 0;
6982 }
6983
6984 //=======================================================================
6985 //function : VPurgeDisplay
6986 //purpose  : Switches altialiasing on or off
6987 //=======================================================================
6988 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
6989                                 Standard_Integer argc,
6990                                 const char ** argv)
6991 {
6992   if (argc > 1)
6993   {
6994     di << "Usage : " << argv[0] << "\n";
6995     return 1;
6996   }
6997   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6998   if (aContext.IsNull())
6999   {
7000     di << "use 'vinit' command before " << argv[0] << "\n";
7001     return 1;
7002   }
7003   aContext->CloseAllContexts(Standard_False);
7004   di << aContext->PurgeDisplay() << "\n";
7005   return 0;
7006 }
7007
7008 //=======================================================================
7009 //function : VSetViewSize
7010 //purpose  :
7011 //=======================================================================
7012 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7013                                 Standard_Integer argc,
7014                                 const char ** argv)
7015 {
7016   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7017   if(aContext.IsNull())
7018   {
7019     di << "use 'vinit' command before " << argv[0] << "\n";
7020     return 1;
7021   }
7022   if(argc != 2)
7023   {
7024     di<<"Usage : " << argv[0] << " Size\n";
7025     return 1;
7026   }
7027   Standard_Real aSize = Draw::Atof (argv[1]);
7028   if (aSize <= 0.)
7029   {
7030     di<<"Bad Size value  : " << aSize << "\n";
7031     return 1;
7032   }
7033
7034   Handle(V3d_View) aView = ViewerTest::CurrentView();
7035   aView->SetSize(aSize);
7036   return 0;
7037 }
7038
7039 //=======================================================================
7040 //function : VMoveView
7041 //purpose  :
7042 //=======================================================================
7043 static Standard_Integer VMoveView (Draw_Interpretor& di,
7044                                 Standard_Integer argc,
7045                                 const char ** argv)
7046 {
7047   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7048   if(aContext.IsNull())
7049   {
7050     di << "use 'vinit' command before " << argv[0] << "\n";
7051     return 1;
7052   }
7053   if(argc < 4 || argc > 5)
7054   {
7055     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7056     return 1;
7057   }
7058   Standard_Real Dx = Draw::Atof (argv[1]);
7059   Standard_Real Dy = Draw::Atof (argv[2]);
7060   Standard_Real Dz = Draw::Atof (argv[3]);
7061   Standard_Boolean aStart = Standard_True;
7062   if (argc == 5)
7063   {
7064       aStart = (Draw::Atoi (argv[4]) > 0);
7065   }
7066
7067   Handle(V3d_View) aView = ViewerTest::CurrentView();
7068   aView->Move(Dx,Dy,Dz,aStart);
7069   return 0;
7070 }
7071
7072 //=======================================================================
7073 //function : VTranslateView
7074 //purpose  :
7075 //=======================================================================
7076 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7077                                 Standard_Integer argc,
7078                                 const char ** argv)
7079 {
7080   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7081   if(aContext.IsNull())
7082   {
7083     di << "use 'vinit' command before " << argv[0] << "\n";
7084     return 1;
7085   }
7086   if(argc < 4 || argc > 5)
7087   {
7088     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7089     return 1;
7090   }
7091   Standard_Real Dx = Draw::Atof (argv[1]);
7092   Standard_Real Dy = Draw::Atof (argv[2]);
7093   Standard_Real Dz = Draw::Atof (argv[3]);
7094   Standard_Boolean aStart = Standard_True;
7095   if (argc == 5)
7096   {
7097       aStart = (Draw::Atoi (argv[4]) > 0);
7098   }
7099
7100   Handle(V3d_View) aView = ViewerTest::CurrentView();
7101   aView->Translate(Dx,Dy,Dz,aStart);
7102   return 0;
7103 }
7104
7105 //=======================================================================
7106 //function : VTurnView
7107 //purpose  :
7108 //=======================================================================
7109 static Standard_Integer VTurnView (Draw_Interpretor& di,
7110                                 Standard_Integer argc,
7111                                 const char ** argv)
7112 {
7113   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7114   if(aContext.IsNull()) {
7115     di << "use 'vinit' command before " << argv[0] << "\n";
7116     return 1;
7117   }
7118   if(argc < 4 || argc > 5){
7119     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7120     return 1;
7121   }
7122   Standard_Real Ax = Draw::Atof (argv[1]);
7123   Standard_Real Ay = Draw::Atof (argv[2]);
7124   Standard_Real Az = Draw::Atof (argv[3]);
7125   Standard_Boolean aStart = Standard_True;
7126   if (argc == 5)
7127   {
7128       aStart = (Draw::Atoi (argv[4]) > 0);
7129   }
7130
7131   Handle(V3d_View) aView = ViewerTest::CurrentView();
7132   aView->Turn(Ax,Ay,Az,aStart);
7133   return 0;
7134 }
7135
7136 //==============================================================================
7137 //function : VTextureEnv
7138 //purpose  : ENables or disables environment mapping
7139 //==============================================================================
7140 class OCC_TextureEnv : public Graphic3d_TextureEnv
7141 {
7142 public:
7143   OCC_TextureEnv(const Standard_CString FileName);
7144   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7145   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7146                             const Standard_Boolean theModulateFlag,
7147                             const Graphic3d_TypeOfTextureFilter theFilter,
7148                             const Standard_ShortReal theXScale,
7149                             const Standard_ShortReal theYScale,
7150                             const Standard_ShortReal theXShift,
7151                             const Standard_ShortReal theYShift,
7152                             const Standard_ShortReal theAngle);
7153   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7154 };
7155 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7156
7157 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7158   : Graphic3d_TextureEnv(theFileName)
7159 {
7160 }
7161
7162 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7163   : Graphic3d_TextureEnv(theTexId)
7164 {
7165 }
7166
7167 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7168                                           const Standard_Boolean theModulateFlag,
7169                                           const Graphic3d_TypeOfTextureFilter theFilter,
7170                                           const Standard_ShortReal theXScale,
7171                                           const Standard_ShortReal theYScale,
7172                                           const Standard_ShortReal theXShift,
7173                                           const Standard_ShortReal theYShift,
7174                                           const Standard_ShortReal theAngle)
7175 {
7176   myParams->SetRepeat     (theRepeatFlag);
7177   myParams->SetModulate   (theModulateFlag);
7178   myParams->SetFilter     (theFilter);
7179   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7180   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7181   myParams->SetRotation   (theAngle);
7182 }
7183
7184 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7185 {
7186   // get the active view
7187   Handle(V3d_View) aView = ViewerTest::CurrentView();
7188   if (aView.IsNull())
7189   {
7190     std::cerr << "No active view. Please call vinit.\n";
7191     return 1;
7192   }
7193
7194   // Checking the input arguments
7195   Standard_Boolean anEnableFlag = Standard_False;
7196   Standard_Boolean isOk         = theArgNb >= 2;
7197   if (isOk)
7198   {
7199     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7200     anEnableFlag = anEnableOpt.IsEqual("on");
7201     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7202   }
7203   if (anEnableFlag)
7204   {
7205     isOk = (theArgNb == 3 || theArgNb == 11);
7206     if (isOk)
7207     {
7208       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7209       isOk = (!aTextureOpt.IsIntegerValue() ||
7210              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7211
7212       if (isOk && theArgNb == 11)
7213       {
7214         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7215                                 aModulateOpt(theArgVec[4]),
7216                                 aFilterOpt  (theArgVec[5]),
7217                                 aSScaleOpt  (theArgVec[6]),
7218                                 aTScaleOpt  (theArgVec[7]),
7219                                 aSTransOpt  (theArgVec[8]),
7220                                 aTTransOpt  (theArgVec[9]),
7221                                 anAngleOpt  (theArgVec[10]);
7222         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7223                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7224                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7225                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7226                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7227                 anAngleOpt.IsRealValue());
7228       }
7229     }
7230   }
7231
7232   if (!isOk)
7233   {
7234     std::cerr << "Usage :" << std::endl;
7235     std::cerr << theArgVec[0] << " off" << std::endl;
7236     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;
7237     return 1;
7238   }
7239
7240   if (anEnableFlag)
7241   {
7242     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7243     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7244                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7245                                      new OCC_TextureEnv(theArgVec[2]);
7246
7247     if (theArgNb == 11)
7248     {
7249       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7250       aTexEnv->SetTextureParameters(
7251         aRepeatOpt.  IsEqual("repeat"),
7252         aModulateOpt.IsEqual("modulate"),
7253         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7254                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7255                                                                            Graphic3d_TOTF_TRILINEAR,
7256         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7257         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7258         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7259         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7260         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7261         );
7262     }
7263     aView->SetTextureEnv(aTexEnv);
7264   }
7265   else // Disabling environment mapping
7266   {
7267     Handle(Graphic3d_TextureEnv) aTexture;
7268     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7269   }
7270
7271   aView->Redraw();
7272   return 0;
7273 }
7274
7275 namespace
7276 {
7277   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7278
7279   //! Remove registered clipping plane from all views and objects.
7280   static void removePlane (MapOfPlanes& theRegPlanes,
7281                            const TCollection_AsciiString& theName)
7282   {
7283     Handle(Graphic3d_ClipPlane) aClipPlane;
7284     if (!theRegPlanes.Find (theName, aClipPlane))
7285     {
7286       std::cout << "Warning: no such plane.\n";
7287       return;
7288     }
7289
7290     theRegPlanes.UnBind (theName);
7291     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7292          anIObjIt.More(); anIObjIt.Next())
7293     {
7294       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7295       aPrs->RemoveClipPlane (aClipPlane);
7296     }
7297
7298     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
7299          aViewIt.More(); aViewIt.Next())
7300     {
7301       const Handle(V3d_View)& aView = aViewIt.Key2();
7302       aView->RemoveClipPlane(aClipPlane);
7303     }
7304
7305     ViewerTest::RedrawAllViews();
7306   }
7307 }
7308
7309 //===============================================================================================
7310 //function : VClipPlane
7311 //purpose  :
7312 //===============================================================================================
7313 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7314 {
7315   // use short-cut for created clip planes map of created (or "registered by name") clip planes
7316   static MapOfPlanes aRegPlanes;
7317
7318   if (theArgsNb < 2)
7319   {
7320     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
7321     {
7322       theDi << aPlaneIter.Key() << " ";
7323     }
7324     return 0;
7325   }
7326
7327   TCollection_AsciiString aCommand (theArgVec[1]);
7328   aCommand.LowerCase();
7329   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
7330   if (anActiveView.IsNull())
7331   {
7332     std::cout << "Error: no active view.\n";
7333     return 1;
7334   }
7335
7336   // print maximum number of planes for current viewer
7337   if (aCommand == "-maxplanes"
7338    || aCommand == "maxplanes")
7339   {
7340     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
7341           << " plane slots provided by driver.\n";
7342     return 0;
7343   }
7344
7345   // create / delete plane instance
7346   if (aCommand == "-create"
7347    || aCommand == "create"
7348    || aCommand == "-delete"
7349    || aCommand == "delete"
7350    || aCommand == "-clone"
7351    || aCommand == "clone")
7352   {
7353     if (theArgsNb < 3)
7354     {
7355       std::cout << "Syntax error: plane name is required.\n";
7356       return 1;
7357     }
7358
7359     Standard_Boolean toCreate = aCommand == "-create"
7360                              || aCommand == "create";
7361     Standard_Boolean toClone  = aCommand == "-clone"
7362                              || aCommand == "clone";
7363     Standard_Boolean toDelete = aCommand == "-delete"
7364                              || aCommand == "delete";
7365     TCollection_AsciiString aPlane (theArgVec[2]);
7366
7367     if (toCreate)
7368     {
7369       if (aRegPlanes.IsBound (aPlane))
7370       {
7371         std::cout << "Warning: existing plane has been overridden.\n";
7372         toDelete = true;
7373       }
7374       else
7375       {
7376         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7377         return 0;
7378       }
7379     }
7380     else if (toClone) // toClone
7381     {
7382       if (!aRegPlanes.IsBound (aPlane))
7383       {
7384         std::cout << "Error: no such plane.\n";
7385         return 1;
7386       }
7387       else if (theArgsNb < 4)
7388       {
7389         std::cout << "Syntax error: enter name for new plane.\n";
7390         return 1;
7391       }
7392
7393       TCollection_AsciiString aClone (theArgVec[3]);
7394       if (aRegPlanes.IsBound (aClone))
7395       {
7396         std::cout << "Error: plane name is in use.\n";
7397         return 1;
7398       }
7399
7400       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
7401
7402       aRegPlanes.Bind (aClone, aClipPlane->Clone());
7403       return 0;
7404     }
7405
7406     if (toDelete)
7407     {
7408       if (aPlane == "ALL"
7409        || aPlane == "all"
7410        || aPlane == "*")
7411       {
7412         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
7413         {
7414           aPlane = aPlaneIter.Key();
7415           removePlane (aRegPlanes, aPlane);
7416           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
7417         }
7418       }
7419       else
7420       {
7421         removePlane (aRegPlanes, aPlane);
7422       }
7423     }
7424
7425     if (toCreate)
7426     {
7427       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7428     }
7429     return 0;
7430   }
7431
7432   // set / unset plane command
7433   if (aCommand == "set"
7434    || aCommand == "unset")
7435   {
7436     if (theArgsNb < 5)
7437     {
7438       std::cout << "Syntax error: need more arguments.\n";
7439       return 1;
7440     }
7441
7442     // redirect to new syntax
7443     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
7444     anArgVec.SetValue (1, theArgVec[0]);
7445     anArgVec.SetValue (2, theArgVec[2]);
7446     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
7447     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
7448     {
7449       anArgVec.SetValue (anIt, theArgVec[anIt]);
7450     }
7451
7452     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
7453   }
7454
7455   // change plane command
7456   TCollection_AsciiString aPlaneName;
7457   Handle(Graphic3d_ClipPlane) aClipPlane;
7458   Standard_Integer anArgIter = 0;
7459   if (aCommand == "-change"
7460    || aCommand == "change")
7461   {
7462     // old syntax support
7463     if (theArgsNb < 3)
7464     {
7465       std::cout << "Syntax error: need more arguments.\n";
7466       return 1;
7467     }
7468
7469     anArgIter  = 3;
7470     aPlaneName = theArgVec[2];
7471     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
7472     {
7473       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
7474       return 1;
7475     }
7476   }
7477   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
7478   {
7479     anArgIter  = 2;
7480     aPlaneName = theArgVec[1];
7481   }
7482   else
7483   {
7484     anArgIter  = 2;
7485     aPlaneName = theArgVec[1];
7486     aClipPlane = new Graphic3d_ClipPlane();
7487     aRegPlanes.Bind (aPlaneName, aClipPlane);
7488     theDi << "Created new plane " << aPlaneName << ".\n";
7489   }
7490
7491   if (theArgsNb - anArgIter < 1)
7492   {
7493     std::cout << "Syntax error: need more arguments.\n";
7494     return 1;
7495   }
7496
7497   for (; anArgIter < theArgsNb; ++anArgIter)
7498   {
7499     const char**     aChangeArgs   = theArgVec + anArgIter;
7500     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
7501     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
7502     aChangeArg.LowerCase();
7503
7504     Standard_Boolean toEnable = Standard_True;
7505     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
7506     {
7507       aClipPlane->SetOn (toEnable);
7508     }
7509     else if (aChangeArg == "-equation"
7510           || aChangeArg == "equation")
7511     {
7512       if (aNbChangeArgs < 5)
7513       {
7514         std::cout << "Syntax error: need more arguments.\n";
7515         return 1;
7516       }
7517
7518       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
7519       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
7520       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
7521       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
7522       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
7523       anArgIter += 4;
7524     }
7525     else if (aChangeArg == "-capping"
7526           || aChangeArg == "capping")
7527     {
7528       if (aNbChangeArgs < 2)
7529       {
7530         std::cout << "Syntax error: need more arguments.\n";
7531         return 1;
7532       }
7533
7534       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7535       {
7536         aClipPlane->SetCapping (toEnable);
7537         anArgIter += 1;
7538       }
7539       else
7540       {
7541         // just skip otherwise (old syntax)
7542       }
7543     }
7544     else if (aChangeArg == "-useobjectmaterial"
7545           || aChangeArg == "-useobjectmat"
7546           || aChangeArg == "-useobjmat"
7547           || aChangeArg == "-useobjmaterial")
7548     {
7549       if (aNbChangeArgs < 2)
7550       {
7551         std::cout << "Syntax error: need more arguments.\n";
7552         return 1;
7553       }
7554
7555       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7556       {
7557         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
7558         anArgIter += 1;
7559       }
7560     }
7561     else if (aChangeArg == "-useobjecttexture"
7562           || aChangeArg == "-useobjecttex"
7563           || aChangeArg == "-useobjtexture"
7564           || aChangeArg == "-useobjtex")
7565     {
7566       if (aNbChangeArgs < 2)
7567       {
7568         std::cout << "Syntax error: need more arguments.\n";
7569         return 1;
7570       }
7571
7572       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7573       {
7574         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
7575         anArgIter += 1;
7576       }
7577     }
7578     else if (aChangeArg == "-useobjectshader"
7579           || aChangeArg == "-useobjshader")
7580     {
7581       if (aNbChangeArgs < 2)
7582       {
7583         std::cout << "Syntax error: need more arguments.\n";
7584         return 1;
7585       }
7586
7587       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7588       {
7589         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
7590         anArgIter += 1;
7591       }
7592     }
7593     else if (aChangeArg == "-color"
7594           || aChangeArg == "color")
7595     {
7596       Quantity_Color aColor;
7597       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
7598                                                            aChangeArgs + 1,
7599                                                            aColor);
7600       if (aNbParsed == 0)
7601       {
7602         std::cout << "Syntax error: need more arguments.\n";
7603         return 1;
7604       }
7605
7606       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
7607       aMat.SetAmbientColor (aColor);
7608       aMat.SetDiffuseColor (aColor);
7609       aClipPlane->SetCappingMaterial (aMat);
7610       anArgIter += aNbParsed;
7611     }
7612     else if (aChangeArg == "-texname"
7613           || aChangeArg == "texname")
7614     {
7615       if (aNbChangeArgs < 2)
7616       {
7617         std::cout << "Syntax error: need more arguments.\n";
7618         return 1;
7619       }
7620
7621       TCollection_AsciiString aTextureName (aChangeArgs[1]);
7622       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
7623       if (!aTexture->IsDone())
7624       {
7625         aClipPlane->SetCappingTexture (NULL);
7626       }
7627       else
7628       {
7629         aTexture->EnableModulate();
7630         aTexture->EnableRepeat();
7631         aClipPlane->SetCappingTexture (aTexture);
7632       }
7633       anArgIter += 1;
7634     }
7635     else if (aChangeArg == "-texscale"
7636           || aChangeArg == "texscale")
7637     {
7638       if (aClipPlane->CappingTexture().IsNull())
7639       {
7640         std::cout << "Error: no texture is set.\n";
7641         return 1;
7642       }
7643
7644       if (aNbChangeArgs < 3)
7645       {
7646         std::cout << "Syntax error: need more arguments.\n";
7647         return 1;
7648       }
7649
7650       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7651       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7652       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
7653       anArgIter += 2;
7654     }
7655     else if (aChangeArg == "-texorigin"
7656           || aChangeArg == "texorigin") // texture origin
7657     {
7658       if (aClipPlane->CappingTexture().IsNull())
7659       {
7660         std::cout << "Error: no texture is set.\n";
7661         return 1;
7662       }
7663
7664       if (aNbChangeArgs < 3)
7665       {
7666         std::cout << "Syntax error: need more arguments.\n";
7667         return 1;
7668       }
7669
7670       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7671       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7672
7673       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
7674       anArgIter += 2;
7675     }
7676     else if (aChangeArg == "-texrotate"
7677           || aChangeArg == "texrotate") // texture rotation
7678     {
7679       if (aClipPlane->CappingTexture().IsNull())
7680       {
7681         std::cout << "Error: no texture is set.\n";
7682         return 1;
7683       }
7684
7685       if (aNbChangeArgs < 2)
7686       {
7687         std::cout << "Syntax error: need more arguments.\n";
7688         return 1;
7689       }
7690
7691       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7692       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
7693       anArgIter += 1;
7694     }
7695     else if (aChangeArg == "-hatch"
7696           || aChangeArg == "hatch")
7697     {
7698       if (aNbChangeArgs < 2)
7699       {
7700         std::cout << "Syntax error: need more arguments.\n";
7701         return 1;
7702       }
7703
7704       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
7705       aHatchStr.LowerCase();
7706       if (aHatchStr == "on")
7707       {
7708         aClipPlane->SetCappingHatchOn();
7709       }
7710       else if (aHatchStr == "off")
7711       {
7712         aClipPlane->SetCappingHatchOff();
7713       }
7714       else
7715       {
7716         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
7717       }
7718       anArgIter += 1;
7719     }
7720     else if (aChangeArg == "-delete"
7721           || aChangeArg == "delete")
7722     {
7723       removePlane (aRegPlanes, aPlaneName);
7724       return 0;
7725     }
7726     else if (aChangeArg == "-set"
7727           || aChangeArg == "-unset")
7728     {
7729       // set / unset plane command
7730       Standard_Boolean toSet = aChangeArg == "-set";
7731       Standard_Integer anIt = 1;
7732       for (; anIt < aNbChangeArgs; ++anIt)
7733       {
7734         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
7735         if (anEntityName.IsEmpty()
7736          || anEntityName.Value (1) == '-')
7737         {
7738           break;
7739         }
7740         else if (ViewerTest_myViews.IsBound1 (anEntityName))
7741         {
7742           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
7743           if (toSet)
7744           {
7745             aView->AddClipPlane (aClipPlane);
7746           }
7747           else
7748           {
7749             aView->RemoveClipPlane (aClipPlane);
7750           }
7751           continue;
7752         }
7753         else if (GetMapOfAIS().IsBound2 (anEntityName))
7754         {
7755           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
7756           if (toSet)
7757           {
7758             aIObj->AddClipPlane (aClipPlane);
7759           }
7760           else
7761           {
7762             aIObj->RemoveClipPlane (aClipPlane);
7763           }
7764         }
7765         else
7766         {
7767           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
7768           return 1;
7769         }
7770       }
7771
7772       if (anIt == 1)
7773       {
7774         // apply to active view
7775         if (toSet)
7776         {
7777           anActiveView->AddClipPlane (aClipPlane);
7778         }
7779         else
7780         {
7781           anActiveView->RemoveClipPlane (aClipPlane);
7782         }
7783       }
7784       else
7785       {
7786         anArgIter = anArgIter + anIt - 1;
7787       }
7788     }
7789     else
7790     {
7791       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
7792       return 1;
7793     }
7794   }
7795
7796   ViewerTest::RedrawAllViews();
7797   return 0;
7798 }
7799
7800 //===============================================================================================
7801 //function : VZRange
7802 //purpose  :
7803 //===============================================================================================
7804 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7805 {
7806   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7807
7808   if (aCurrentView.IsNull())
7809   {
7810     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7811     return 1;
7812   }
7813
7814   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
7815
7816   if (theArgsNb < 2)
7817   {
7818     theDi << "ZNear: " << aCamera->ZNear() << "\n";
7819     theDi << "ZFar: " << aCamera->ZFar() << "\n";
7820     return 0;
7821   }
7822
7823   if (theArgsNb == 3)
7824   {
7825     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
7826     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
7827
7828     if (aNewZNear >= aNewZFar)
7829     {
7830       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
7831       return 1;
7832     }
7833
7834     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
7835     {
7836       std::cout << theArgVec[0] << ": invalid arguments: ";
7837       std::cout << "znear, zfar should be positive for perspective camera.\n";
7838       return 1;
7839     }
7840
7841     aCamera->SetZRange (aNewZNear, aNewZFar);
7842   }
7843   else
7844   {
7845     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7846     return 1;
7847   }
7848
7849   aCurrentView->Redraw();
7850
7851   return 0;
7852 }
7853
7854 //===============================================================================================
7855 //function : VAutoZFit
7856 //purpose  :
7857 //===============================================================================================
7858 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7859 {
7860   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7861
7862   if (aCurrentView.IsNull())
7863   {
7864     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7865     return 1;
7866   }
7867
7868   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
7869
7870   if (theArgsNb > 3)
7871   {
7872     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7873     return 1;
7874   }
7875
7876   if (theArgsNb < 2)
7877   {
7878     theDi << "Auto z-fit mode: \n"
7879           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
7880           << "Scale: " << aScale << "\n";
7881     return 0;
7882   }
7883
7884   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
7885
7886   if (theArgsNb >= 3)
7887   {
7888     aScale = Draw::Atoi (theArgVec[2]);
7889   }
7890
7891   aCurrentView->SetAutoZFitMode (isOn, aScale);
7892   aCurrentView->AutoZFit();
7893   aCurrentView->Redraw();
7894
7895   return 0;
7896 }
7897
7898 //! Auxiliary function to print projection type
7899 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
7900 {
7901   switch (theProjType)
7902   {
7903     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
7904     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
7905     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
7906     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
7907     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
7908   }
7909   return "UNKNOWN";
7910 }
7911
7912 //===============================================================================================
7913 //function : VCamera
7914 //purpose  :
7915 //===============================================================================================
7916 static int VCamera (Draw_Interpretor& theDI,
7917                     Standard_Integer  theArgsNb,
7918                     const char**      theArgVec)
7919 {
7920   Handle(V3d_View) aView = ViewerTest::CurrentView();
7921   if (aView.IsNull())
7922   {
7923     std::cout << "Error: no active view.\n";
7924     return 1;
7925   }
7926
7927   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7928   if (theArgsNb < 2)
7929   {
7930     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7931     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7932     theDI << "Distance:   " << aCamera->Distance() << "\n";
7933     theDI << "IOD:        " << aCamera->IOD() << "\n";
7934     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7935     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7936     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7937     return 0;
7938   }
7939
7940   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7941   {
7942     Standard_CString        anArg = theArgVec[anArgIter];
7943     TCollection_AsciiString anArgCase (anArg);
7944     anArgCase.LowerCase();
7945     if (anArgCase == "-proj"
7946      || anArgCase == "-projection"
7947      || anArgCase == "-projtype"
7948      || anArgCase == "-projectiontype")
7949     {
7950       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7951     }
7952     else if (anArgCase == "-ortho"
7953           || anArgCase == "-orthographic")
7954     {
7955       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
7956     }
7957     else if (anArgCase == "-persp"
7958           || anArgCase == "-perspective"
7959           || anArgCase == "-perspmono"
7960           || anArgCase == "-perspectivemono"
7961           || anArgCase == "-mono")
7962     {
7963       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7964     }
7965     else if (anArgCase == "-stereo"
7966           || anArgCase == "-stereoscopic"
7967           || anArgCase == "-perspstereo"
7968           || anArgCase == "-perspectivestereo")
7969     {
7970       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7971     }
7972     else if (anArgCase == "-left"
7973           || anArgCase == "-lefteye"
7974           || anArgCase == "-monoleft"
7975           || anArgCase == "-monolefteye"
7976           || anArgCase == "-perpsleft"
7977           || anArgCase == "-perpslefteye")
7978     {
7979       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
7980     }
7981     else if (anArgCase == "-right"
7982           || anArgCase == "-righteye"
7983           || anArgCase == "-monoright"
7984           || anArgCase == "-monorighteye"
7985           || anArgCase == "-perpsright")
7986     {
7987       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
7988     }
7989     else if (anArgCase == "-dist"
7990           || anArgCase == "-distance")
7991     {
7992       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7993       if (anArgValue != NULL
7994       && *anArgValue != '-')
7995       {
7996         ++anArgIter;
7997         aCamera->SetDistance (Draw::Atof (anArgValue));
7998         continue;
7999       }
8000       theDI << aCamera->Distance() << " ";
8001     }
8002     else if (anArgCase == "-iod")
8003     {
8004       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8005       if (anArgValue != NULL
8006       && *anArgValue != '-')
8007       {
8008         ++anArgIter;
8009         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8010         continue;
8011       }
8012       theDI << aCamera->IOD() << " ";
8013     }
8014     else if (anArgCase == "-iodtype")
8015     {
8016       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8017       TCollection_AsciiString anValueCase (anArgValue);
8018       anValueCase.LowerCase();
8019       if (anValueCase == "abs"
8020        || anValueCase == "absolute")
8021       {
8022         ++anArgIter;
8023         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8024         continue;
8025       }
8026       else if (anValueCase == "rel"
8027             || anValueCase == "relative")
8028       {
8029         ++anArgIter;
8030         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8031         continue;
8032       }
8033       else if (*anArgValue != '-')
8034       {
8035         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8036         return 1;
8037       }
8038       switch (aCamera->GetIODType())
8039       {
8040         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8041         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8042       }
8043     }
8044     else if (anArgCase == "-zfocus")
8045     {
8046       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8047       if (anArgValue != NULL
8048       && *anArgValue != '-')
8049       {
8050         ++anArgIter;
8051         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8052         continue;
8053       }
8054       theDI << aCamera->ZFocus() << " ";
8055     }
8056     else if (anArgCase == "-zfocustype")
8057     {
8058       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8059       TCollection_AsciiString anValueCase (anArgValue);
8060       anValueCase.LowerCase();
8061       if (anValueCase == "abs"
8062        || anValueCase == "absolute")
8063       {
8064         ++anArgIter;
8065         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8066         continue;
8067       }
8068       else if (anValueCase == "rel"
8069             || anValueCase == "relative")
8070       {
8071         ++anArgIter;
8072         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8073         continue;
8074       }
8075       else if (*anArgValue != '-')
8076       {
8077         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8078         return 1;
8079       }
8080       switch (aCamera->ZFocusType())
8081       {
8082         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8083         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8084       }
8085     }
8086     else if (anArgCase == "-fov"
8087           || anArgCase == "-fovy")
8088     {
8089       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8090       if (anArgValue != NULL
8091       && *anArgValue != '-')
8092       {
8093         ++anArgIter;
8094         aCamera->SetFOVy (Draw::Atof (anArgValue));
8095         continue;
8096       }
8097       theDI << aCamera->FOVy() << " ";
8098     }
8099     else
8100     {
8101       std::cout << "Error: unknown argument '" << anArg << "'\n";
8102       return 1;
8103     }
8104   }
8105
8106   aView->AutoZFit();
8107   aView->Redraw();
8108
8109   return 0;
8110 }
8111
8112 //! Parse stereo output mode
8113 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8114                                          Graphic3d_StereoMode& theMode)
8115 {
8116   TCollection_AsciiString aFlag (theArg);
8117   aFlag.LowerCase();
8118   if (aFlag == "quadbuffer")
8119   {
8120     theMode = Graphic3d_StereoMode_QuadBuffer;
8121   }
8122   else if (aFlag == "anaglyph")
8123   {
8124     theMode = Graphic3d_StereoMode_Anaglyph;
8125   }
8126   else if (aFlag == "row"
8127         || aFlag == "rowinterlaced")
8128   {
8129     theMode = Graphic3d_StereoMode_RowInterlaced;
8130   }
8131   else if (aFlag == "col"
8132         || aFlag == "colinterlaced"
8133         || aFlag == "columninterlaced")
8134   {
8135     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8136   }
8137   else if (aFlag == "chess"
8138         || aFlag == "chessboard")
8139   {
8140     theMode = Graphic3d_StereoMode_ChessBoard;
8141   }
8142   else if (aFlag == "sbs"
8143         || aFlag == "sidebyside")
8144   {
8145     theMode = Graphic3d_StereoMode_SideBySide;
8146   }
8147   else if (aFlag == "ou"
8148         || aFlag == "overunder")
8149   {
8150     theMode = Graphic3d_StereoMode_OverUnder;
8151   }
8152   else if (aFlag == "pageflip"
8153         || aFlag == "softpageflip")
8154   {
8155     theMode = Graphic3d_StereoMode_SoftPageFlip;
8156   }
8157   else
8158   {
8159     return Standard_False;
8160   }
8161   return Standard_True;
8162 }
8163
8164 //! Parse anaglyph filter
8165 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8166                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8167 {
8168   TCollection_AsciiString aFlag (theArg);
8169   aFlag.LowerCase();
8170   if (aFlag == "redcyansimple")
8171   {
8172     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8173   }
8174   else if (aFlag == "redcyan"
8175         || aFlag == "redcyanoptimized")
8176   {
8177     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8178   }
8179   else if (aFlag == "yellowbluesimple")
8180   {
8181     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8182   }
8183   else if (aFlag == "yellowblue"
8184         || aFlag == "yellowblueoptimized")
8185   {
8186     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8187   }
8188   else if (aFlag == "greenmagenta"
8189         || aFlag == "greenmagentasimple")
8190   {
8191     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8192   }
8193   else
8194   {
8195     return Standard_False;
8196   }
8197   return Standard_True;
8198 }
8199
8200 //==============================================================================
8201 //function : VStereo
8202 //purpose  :
8203 //==============================================================================
8204
8205 static int VStereo (Draw_Interpretor& theDI,
8206                     Standard_Integer  theArgNb,
8207                     const char**      theArgVec)
8208 {
8209   Handle(V3d_View) aView = ViewerTest::CurrentView();
8210   if (theArgNb < 2)
8211   {
8212     if (aView.IsNull())
8213     {
8214       std::cout << "Error: no active viewer!\n";
8215       return 0;
8216     }
8217
8218     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8219     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8220     if (isActive)
8221     {
8222       TCollection_AsciiString aMode;
8223       switch (aView->RenderingParams().StereoMode)
8224       {
8225         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8226         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8227         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8228         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8229         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8230         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8231         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8232         case Graphic3d_StereoMode_Anaglyph  :
8233           aMode = "anaglyph";
8234           switch (aView->RenderingParams().AnaglyphFilter)
8235           {
8236             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8237             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8238             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8239             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8240             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8241             default: break;
8242           }
8243         default: break;
8244       }
8245       theDI << "Mode " << aMode << "\n";
8246     }
8247     return 0;
8248   }
8249
8250   Handle(Graphic3d_Camera) aCamera;
8251   Graphic3d_RenderingParams*   aParams   = NULL;
8252   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8253   if (!aView.IsNull())
8254   {
8255     aParams   = &aView->ChangeRenderingParams();
8256     aMode     = aParams->StereoMode;
8257     aCamera   = aView->Camera();
8258   }
8259
8260   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8261   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8262   {
8263     Standard_CString        anArg = theArgVec[anArgIter];
8264     TCollection_AsciiString aFlag (anArg);
8265     aFlag.LowerCase();
8266     if (anUpdateTool.parseRedrawMode (aFlag))
8267     {
8268       continue;
8269     }
8270     else if (aFlag == "0"
8271           || aFlag == "off")
8272     {
8273       if (++anArgIter < theArgNb)
8274       {
8275         std::cout << "Error: wrong number of arguments!\n";
8276         return 1;
8277       }
8278
8279       if (!aCamera.IsNull()
8280        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8281       {
8282         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8283       }
8284       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8285       return 0;
8286     }
8287     else if (aFlag == "1"
8288           || aFlag == "on")
8289     {
8290       if (++anArgIter < theArgNb)
8291       {
8292         std::cout << "Error: wrong number of arguments!\n";
8293         return 1;
8294       }
8295
8296       if (!aCamera.IsNull())
8297       {
8298         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8299       }
8300       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8301       return 0;
8302     }
8303     else if (aFlag == "-reverse"
8304           || aFlag == "-reversed"
8305           || aFlag == "-swap")
8306     {
8307       Standard_Boolean toEnable = Standard_True;
8308       if (++anArgIter < theArgNb
8309       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8310       {
8311         --anArgIter;
8312       }
8313       aParams->ToReverseStereo = toEnable;
8314     }
8315     else if (aFlag == "-noreverse"
8316           || aFlag == "-noswap")
8317     {
8318       Standard_Boolean toDisable = Standard_True;
8319       if (++anArgIter < theArgNb
8320       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
8321       {
8322         --anArgIter;
8323       }
8324       aParams->ToReverseStereo = !toDisable;
8325     }
8326     else if (aFlag == "-mode"
8327           || aFlag == "-stereomode")
8328     {
8329       if (++anArgIter >= theArgNb
8330       || !parseStereoMode (theArgVec[anArgIter], aMode))
8331       {
8332         std::cout << "Error: syntax error at '" << anArg << "'\n";
8333         return 1;
8334       }
8335
8336       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8337       {
8338         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8339       }
8340     }
8341     else if (aFlag == "-anaglyph"
8342           || aFlag == "-anaglyphfilter")
8343     {
8344       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8345       if (++anArgIter >= theArgNb
8346       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
8347       {
8348         std::cout << "Error: syntax error at '" << anArg << "'\n";
8349         return 1;
8350       }
8351
8352       aMode = Graphic3d_StereoMode_Anaglyph;
8353       aParams->AnaglyphFilter = aFilter;
8354     }
8355     else if (parseStereoMode (anArg, aMode)) // short syntax
8356     {
8357       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8358       {
8359         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8360       }
8361     }
8362     else
8363     {
8364       std::cout << "Error: syntax error at '" << anArg << "'\n";
8365       return 1;
8366     }
8367   }
8368
8369   if (!aView.IsNull())
8370   {
8371     aParams->StereoMode = aMode;
8372     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8373   }
8374   return 0;
8375 }
8376
8377 //===============================================================================================
8378 //function : VDefaults
8379 //purpose  :
8380 //===============================================================================================
8381 static int VDefaults (Draw_Interpretor& theDi,
8382                       Standard_Integer  theArgsNb,
8383                       const char**      theArgVec)
8384 {
8385   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
8386   if (aCtx.IsNull())
8387   {
8388     std::cerr << "No active viewer!\n";
8389     return 1;
8390   }
8391
8392   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
8393   if (theArgsNb < 2)
8394   {
8395     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
8396     {
8397       theDi << "DeflType:           relative\n"
8398             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
8399     }
8400     else
8401     {
8402       theDi << "DeflType:           absolute\n"
8403             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
8404     }
8405     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
8406     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
8407     return 0;
8408   }
8409
8410   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8411   {
8412     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8413     anArg.UpperCase();
8414     if (anArg == "-ABSDEFL"
8415      || anArg == "-ABSOLUTEDEFLECTION"
8416      || anArg == "-DEFL"
8417      || anArg == "-DEFLECTION")
8418     {
8419       if (++anArgIter >= theArgsNb)
8420       {
8421         std::cout << "Error: wrong syntax at " << anArg << "\n";
8422         return 1;
8423       }
8424       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
8425       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
8426     }
8427     else if (anArg == "-RELDEFL"
8428           || anArg == "-RELATIVEDEFLECTION"
8429           || anArg == "-DEVCOEFF"
8430           || anArg == "-DEVIATIONCOEFF"
8431           || anArg == "-DEVIATIONCOEFFICIENT")
8432     {
8433       if (++anArgIter >= theArgsNb)
8434       {
8435         std::cout << "Error: wrong syntax at " << anArg << "\n";
8436         return 1;
8437       }
8438       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
8439       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
8440     }
8441     else if (anArg == "-ANGDEFL"
8442           || anArg == "-ANGULARDEFL"
8443           || anArg == "-ANGULARDEFLECTION")
8444     {
8445       if (++anArgIter >= theArgsNb)
8446       {
8447         std::cout << "Error: wrong syntax at " << anArg << "\n";
8448         return 1;
8449       }
8450       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
8451       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
8452     }
8453     else if (anArg == "-AUTOTR"
8454           || anArg == "-AUTOTRIANG"
8455           || anArg == "-AUTOTRIANGULATION")
8456     {
8457       if (++anArgIter >= theArgsNb)
8458       {
8459         std::cout << "Error: wrong syntax at " << anArg << "\n";
8460         return 1;
8461       }
8462       TCollection_AsciiString aValue (theArgVec[anArgIter]);
8463       aValue.LowerCase();
8464       if (aValue == "on"
8465        || aValue == "1")
8466       {
8467         aDefParams->SetAutoTriangulation (Standard_True);
8468       }
8469       else if (aValue == "off"
8470             || aValue == "0")
8471       {
8472         aDefParams->SetAutoTriangulation (Standard_False);
8473       }
8474     }
8475     else
8476     {
8477       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
8478     }
8479   }
8480
8481   return 0;
8482 }
8483
8484 //! Auxiliary method
8485 inline void addLight (const Handle(V3d_Light)& theLightNew,
8486                       const Standard_Boolean   theIsGlobal)
8487 {
8488   if (theLightNew.IsNull())
8489   {
8490     return;
8491   }
8492
8493   if (theIsGlobal)
8494   {
8495     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
8496   }
8497   else
8498   {
8499     ViewerTest::CurrentView()->SetLightOn (theLightNew);
8500   }
8501 }
8502
8503 //! Auxiliary method
8504 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
8505 {
8506   TCollection_AsciiString anArgNextCase (theArgNext);
8507   anArgNextCase.UpperCase();
8508   if (anArgNextCase.Length() > 5
8509    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
8510   {
8511     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
8512   }
8513   else
8514   {
8515     return theArgNext.IntegerValue();
8516   }
8517 }
8518
8519 //===============================================================================================
8520 //function : VLight
8521 //purpose  :
8522 //===============================================================================================
8523 static int VLight (Draw_Interpretor& theDi,
8524                    Standard_Integer  theArgsNb,
8525                    const char**      theArgVec)
8526 {
8527   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8528   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8529   if (aView.IsNull()
8530    || aViewer.IsNull())
8531   {
8532     std::cerr << "No active viewer!\n";
8533     return 1;
8534   }
8535
8536   Standard_Real        anXYZ[3];
8537   Quantity_Coefficient anAtten[2];
8538   if (theArgsNb < 2)
8539   {
8540     // print lights info
8541     Standard_Integer aLightId = 0;
8542     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
8543     {
8544       Handle(V3d_Light) aLight = aLightIter.Value();
8545       const Quantity_Color aColor = aLight->Color();
8546       theDi << "Light" << aLightId << "\n";
8547       switch (aLight->Type())
8548       {
8549         case V3d_AMBIENT:
8550         {
8551           theDi << "  Type:       Ambient\n";
8552           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8553           break;
8554         }
8555         case V3d_DIRECTIONAL:
8556         {
8557           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
8558           theDi << "  Type:       Directional\n";
8559           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8560           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8561           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8562           if (!aLightDir.IsNull())
8563           {
8564             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8565             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8566             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8567             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8568           }
8569           break;
8570         }
8571         case V3d_POSITIONAL:
8572         {
8573           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
8574           theDi << "  Type:       Positional\n";
8575           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8576           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8577           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8578           if (!aLightPos.IsNull())
8579           {
8580             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8581             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8582             aLightPos->Attenuation (anAtten[0], anAtten[1]);
8583             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8584           }
8585           break;
8586         }
8587         case V3d_SPOT:
8588         {
8589           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
8590           theDi << "  Type:       Spot\n";
8591           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8592           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8593           if (!aLightSpot.IsNull())
8594           {
8595             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8596             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8597             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8598             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8599             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8600             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8601             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
8602             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
8603           }
8604           break;
8605         }
8606         default:
8607         {
8608           theDi << "  Type:       UNKNOWN\n";
8609           break;
8610         }
8611       }
8612       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
8613     }
8614   }
8615
8616   Handle(V3d_Light) aLightNew;
8617   Handle(V3d_Light) aLightOld;
8618   Standard_Boolean  isGlobal = Standard_True;
8619   Standard_Boolean  toCreate = Standard_False;
8620   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8621   {
8622     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
8623     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
8624     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
8625     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
8626     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
8627
8628     TCollection_AsciiString aName, aValue;
8629     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
8630     TCollection_AsciiString anArgCase (anArg);
8631     anArgCase.UpperCase();
8632     if (anArgCase.IsEqual ("NEW")
8633      || anArgCase.IsEqual ("ADD")
8634      || anArgCase.IsEqual ("CREATE"))
8635     {
8636       toCreate = Standard_True;
8637     }
8638     else if (anArgCase.IsEqual ("GLOB")
8639           || anArgCase.IsEqual ("GLOBAL"))
8640     {
8641       isGlobal = Standard_True;
8642     }
8643     else if (anArgCase.IsEqual ("LOC")
8644           || anArgCase.IsEqual ("LOCAL"))
8645     {
8646       isGlobal = Standard_False;
8647     }
8648     else if (anArgCase.IsEqual ("DEF")
8649           || anArgCase.IsEqual ("DEFAULTS"))
8650     {
8651       toCreate = Standard_False;
8652       aViewer->SetDefaultLights();
8653     }
8654     else if (anArgCase.IsEqual ("CLR")
8655           || anArgCase.IsEqual ("CLEAR"))
8656     {
8657       toCreate = Standard_False;
8658       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
8659       {
8660         Handle(V3d_Light) aLight = aLightIter.Value();
8661         aViewer->DelLight (aLight);
8662         aLightIter = aView->ActiveLightIterator();
8663       }
8664     }
8665     else if (anArgCase.IsEqual ("AMB")
8666           || anArgCase.IsEqual ("AMBIENT")
8667           || anArgCase.IsEqual ("AMBLIGHT"))
8668     {
8669       addLight (aLightNew, isGlobal);
8670       if (!toCreate)
8671       {
8672         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8673         return 1;
8674       }
8675       toCreate  = Standard_False;
8676       aLightNew = new V3d_AmbientLight (aViewer);
8677     }
8678     else if (anArgCase.IsEqual ("DIRECTIONAL")
8679           || anArgCase.IsEqual ("DIRLIGHT"))
8680     {
8681       addLight (aLightNew, isGlobal);
8682       if (!toCreate)
8683       {
8684         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8685         return 1;
8686       }
8687       toCreate  = Standard_False;
8688       aLightNew = new V3d_DirectionalLight (aViewer);
8689     }
8690     else if (anArgCase.IsEqual ("SPOT")
8691           || anArgCase.IsEqual ("SPOTLIGHT"))
8692     {
8693       addLight (aLightNew, isGlobal);
8694       if (!toCreate)
8695       {
8696         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8697         return 1;
8698       }
8699       toCreate  = Standard_False;
8700       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
8701     }
8702     else if (anArgCase.IsEqual ("POSLIGHT")
8703           || anArgCase.IsEqual ("POSITIONAL"))
8704     {
8705       addLight (aLightNew, isGlobal);
8706       if (!toCreate)
8707       {
8708         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8709         return 1;
8710       }
8711       toCreate  = Standard_False;
8712       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
8713     }
8714     else if (anArgCase.IsEqual ("CHANGE"))
8715     {
8716       addLight (aLightNew, isGlobal);
8717       aLightNew.Nullify();
8718       if (++anArgIt >= theArgsNb)
8719       {
8720         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8721         return 1;
8722       }
8723
8724       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
8725       Standard_Integer aLightIt = 0;
8726       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8727       {
8728         if (aLightIt == aLightId)
8729         {
8730           aLightOld = aLightIter.Value();
8731           break;
8732         }
8733       }
8734
8735       if (aLightOld.IsNull())
8736       {
8737         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
8738         return 1;
8739       }
8740     }
8741     else if (anArgCase.IsEqual ("DEL")
8742           || anArgCase.IsEqual ("DELETE"))
8743     {
8744       Handle(V3d_Light) aLightDel;
8745       if (++anArgIt >= theArgsNb)
8746       {
8747         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8748         return 1;
8749       }
8750
8751       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8752       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
8753       Standard_Integer aLightIt = 0;
8754       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8755       {
8756         aLightDel = aLightIter.Value();
8757         if (aLightIt == aLightDelId)
8758         {
8759           break;
8760         }
8761       }
8762       if (!aLightDel.IsNull())
8763       {
8764         aViewer->DelLight (aLightDel);
8765       }
8766     }
8767     else if (anArgCase.IsEqual ("COLOR")
8768           || anArgCase.IsEqual ("COLOUR"))
8769     {
8770       if (++anArgIt >= theArgsNb)
8771       {
8772         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8773         return 1;
8774       }
8775
8776       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8777       anArgNext.UpperCase();
8778       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
8779       if (!aLightCurr.IsNull())
8780       {
8781         aLightCurr->SetColor (aColor);
8782       }
8783     }
8784     else if (anArgCase.IsEqual ("POS")
8785           || anArgCase.IsEqual ("POSITION"))
8786     {
8787       if ((anArgIt + 3) >= theArgsNb)
8788       {
8789         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8790         return 1;
8791       }
8792
8793       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8794       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8795       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8796       if (!aLightDir.IsNull())
8797       {
8798         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8799       }
8800       else if (!aLightPos.IsNull())
8801       {
8802         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8803       }
8804       else if (!aLightSpot.IsNull())
8805       {
8806         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8807       }
8808       else
8809       {
8810         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8811         return 1;
8812       }
8813     }
8814     else if (anArgCase.IsEqual ("DIR")
8815           || anArgCase.IsEqual ("DIRECTION"))
8816     {
8817       if ((anArgIt + 3) >= theArgsNb)
8818       {
8819         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8820         return 1;
8821       }
8822
8823       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8824       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8825       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8826       if (!aLightDir.IsNull())
8827       {
8828         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8829       }
8830       else if (!aLightSpot.IsNull())
8831       {
8832         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8833       }
8834       else
8835       {
8836         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8837         return 1;
8838       }
8839     }
8840     else if (anArgCase.IsEqual ("SM")
8841           || anArgCase.IsEqual ("SMOOTHNESS"))
8842     {
8843       if (++anArgIt >= theArgsNb)
8844       {
8845         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8846         return 1;
8847       }
8848
8849       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
8850
8851       if (fabs (aSmoothness) < Precision::Confusion())
8852       {
8853         aLightCurr->SetIntensity (1.f);
8854       }
8855       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
8856       {
8857         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
8858       }
8859       else
8860       {
8861         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
8862         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
8863       }
8864
8865       if (!aLightPos.IsNull())
8866       {
8867         aLightPos->SetSmoothRadius (aSmoothness);
8868       }
8869       else if (!aLightDir.IsNull())
8870       {
8871         aLightDir->SetSmoothAngle (aSmoothness);
8872       }
8873     }
8874     else if (anArgCase.IsEqual ("INT")
8875           || anArgCase.IsEqual ("INTENSITY"))
8876     {
8877       if (++anArgIt >= theArgsNb)
8878       {
8879         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8880         return 1;
8881       }
8882
8883       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
8884
8885       if (!aLightCurr.IsNull())
8886       {
8887         aLightCurr->SetIntensity (aIntensity);
8888       }
8889     }
8890     else if (anArgCase.IsEqual ("ANG")
8891           || anArgCase.IsEqual ("ANGLE"))
8892     {
8893       if (++anArgIt >= theArgsNb)
8894       {
8895         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8896         return 1;
8897       }
8898
8899       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
8900
8901       if (!aLightSpot.IsNull())
8902       {
8903         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
8904       }
8905     }
8906     else if (anArgCase.IsEqual ("CONSTATTEN")
8907           || anArgCase.IsEqual ("CONSTATTENUATION"))
8908     {
8909       if (++anArgIt >= theArgsNb)
8910       {
8911         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8912         return 1;
8913       }
8914
8915       if (!aLightPos.IsNull())
8916       {
8917         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8918         anAtten[0] = Atof (theArgVec[anArgIt]);
8919         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8920       }
8921       else if (!aLightSpot.IsNull())
8922       {
8923         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8924         anAtten[0] = Atof (theArgVec[anArgIt]);
8925         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8926       }
8927       else
8928       {
8929         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8930         return 1;
8931       }
8932     }
8933     else if (anArgCase.IsEqual ("LINATTEN")
8934           || anArgCase.IsEqual ("LINEARATTEN")
8935           || anArgCase.IsEqual ("LINEARATTENUATION"))
8936     {
8937       if (++anArgIt >= theArgsNb)
8938       {
8939         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8940         return 1;
8941       }
8942
8943       if (!aLightPos.IsNull())
8944       {
8945         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8946         anAtten[1] = Atof (theArgVec[anArgIt]);
8947         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8948       }
8949       else if (!aLightSpot.IsNull())
8950       {
8951         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8952         anAtten[1] = Atof (theArgVec[anArgIt]);
8953         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8954       }
8955       else
8956       {
8957         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8958         return 1;
8959       }
8960     }
8961     else if (anArgCase.IsEqual ("EXP")
8962           || anArgCase.IsEqual ("EXPONENT")
8963           || anArgCase.IsEqual ("SPOTEXP")
8964           || anArgCase.IsEqual ("SPOTEXPONENT"))
8965     {
8966       if (++anArgIt >= theArgsNb)
8967       {
8968         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8969         return 1;
8970       }
8971
8972       if (!aLightSpot.IsNull())
8973       {
8974         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
8975       }
8976       else
8977       {
8978         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8979         return 1;
8980       }
8981     }
8982     else if (anArgCase.IsEqual ("HEAD")
8983           || anArgCase.IsEqual ("HEADLIGHT"))
8984     {
8985       if (++anArgIt >= theArgsNb)
8986       {
8987         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8988         return 1;
8989       }
8990
8991       if (aLightAmb.IsNull()
8992        && !aLightCurr.IsNull())
8993       {
8994         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
8995       }
8996       else
8997       {
8998         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8999         return 1;
9000       }
9001     }
9002     else
9003     {
9004       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9005     }
9006   }
9007
9008   addLight (aLightNew, isGlobal);
9009   aViewer->UpdateLights();
9010
9011   return 0;
9012 }
9013
9014 //=======================================================================
9015 //function : VRenderParams
9016 //purpose  : Enables/disables rendering features
9017 //=======================================================================
9018
9019 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9020                                        Standard_Integer  theArgNb,
9021                                        const char**      theArgVec)
9022 {
9023   Handle(V3d_View) aView = ViewerTest::CurrentView();
9024   if (aView.IsNull())
9025   {
9026     std::cerr << "Error: no active viewer!\n";
9027     return 1;
9028   }
9029
9030   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9031   TCollection_AsciiString aCmdName (theArgVec[0]);
9032   aCmdName.LowerCase();
9033   if (aCmdName == "vraytrace")
9034   {
9035     if (theArgNb == 1)
9036     {
9037       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9038       return 0;
9039     }
9040     else if (theArgNb == 2)
9041     {
9042       TCollection_AsciiString aValue (theArgVec[1]);
9043       aValue.LowerCase();
9044       if (aValue == "on"
9045        || aValue == "1")
9046       {
9047         aParams.Method = Graphic3d_RM_RAYTRACING;
9048         aView->Redraw();
9049         return 0;
9050       }
9051       else if (aValue == "off"
9052             || aValue == "0")
9053       {
9054         aParams.Method = Graphic3d_RM_RASTERIZATION;
9055         aView->Redraw();
9056         return 0;
9057       }
9058       else
9059       {
9060         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9061         return 1;
9062       }
9063     }
9064     else
9065     {
9066       std::cout << "Error: wrong number of arguments\n";
9067       return 1;
9068     }
9069   }
9070
9071   if (theArgNb < 2)
9072   {
9073     theDI << "renderMode:  ";
9074     switch (aParams.Method)
9075     {
9076       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9077       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9078     }
9079     theDI << "\n";
9080     theDI << "msaa:         " <<  aParams.NbMsaaSamples                               << "\n";
9081     theDI << "rayDepth:     " <<  aParams.RaytracingDepth                             << "\n";
9082     theDI << "fsaa:         " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9083     theDI << "shadows:      " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9084     theDI << "reflections:  " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9085     theDI << "gleam:        " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9086     theDI << "GI:           " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9087     theDI << "blocked RNG:  " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9088     theDI << "iss:          " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9089     theDI << "iss debug:    " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9090     theDI << "shadingModel: ";
9091     switch (aView->ShadingModel())
9092     {
9093       case V3d_COLOR:   theDI << "color";   break;
9094       case V3d_FLAT:    theDI << "flat";    break;
9095       case V3d_GOURAUD: theDI << "gouraud"; break;
9096       case V3d_PHONG:   theDI << "phong";   break;
9097     }
9098     theDI << "\n";
9099     return 0;
9100   }
9101
9102   Standard_Boolean toPrint = Standard_False;
9103   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9104   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9105   {
9106     Standard_CString        anArg (theArgVec[anArgIter]);
9107     TCollection_AsciiString aFlag (anArg);
9108     aFlag.LowerCase();
9109     if (anUpdateTool.parseRedrawMode (aFlag))
9110     {
9111       continue;
9112     }
9113     else if (aFlag == "-echo"
9114           || aFlag == "-print")
9115     {
9116       toPrint = Standard_True;
9117       anUpdateTool.Invalidate();
9118     }
9119     else if (aFlag == "-mode"
9120           || aFlag == "-rendermode"
9121           || aFlag == "-render_mode")
9122     {
9123       if (toPrint)
9124       {
9125         switch (aParams.Method)
9126         {
9127           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9128           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9129         }
9130         continue;
9131       }
9132       else
9133       {
9134         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9135         return 1;
9136       }
9137     }
9138     else if (aFlag == "-ray"
9139           || aFlag == "-raytrace")
9140     {
9141       if (toPrint)
9142       {
9143         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9144         continue;
9145       }
9146
9147       aParams.Method = Graphic3d_RM_RAYTRACING;
9148     }
9149     else if (aFlag == "-rast"
9150           || aFlag == "-raster"
9151           || aFlag == "-rasterization")
9152     {
9153       if (toPrint)
9154       {
9155         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9156         continue;
9157       }
9158
9159       aParams.Method = Graphic3d_RM_RASTERIZATION;
9160     }
9161     else if (aFlag == "-msaa")
9162     {
9163       if (toPrint)
9164       {
9165         theDI << aParams.NbMsaaSamples << " ";
9166         continue;
9167       }
9168       else if (++anArgIter >= theArgNb)
9169       {
9170         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9171         return 1;
9172       }
9173
9174       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9175       if (aNbSamples < 0)
9176       {
9177         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9178         return 1;
9179       }
9180       else
9181       {
9182         aParams.NbMsaaSamples = aNbSamples;
9183       }
9184     }
9185     else if (aFlag == "-raydepth"
9186           || aFlag == "-ray_depth")
9187     {
9188       if (toPrint)
9189       {
9190         theDI << aParams.RaytracingDepth << " ";
9191         continue;
9192       }
9193       else if (++anArgIter >= theArgNb)
9194       {
9195         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9196         return 1;
9197       }
9198
9199       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9200
9201       // We allow RaytracingDepth be more than 10 in case of GI enabled
9202       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9203       {
9204         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9205         return 1;
9206       }
9207       else
9208       {
9209         aParams.RaytracingDepth = aDepth;
9210       }
9211     }
9212     else if (aFlag == "-shad"
9213           || aFlag == "-shadows")
9214     {
9215       if (toPrint)
9216       {
9217         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
9218         continue;
9219       }
9220
9221       Standard_Boolean toEnable = Standard_True;
9222       if (++anArgIter < theArgNb
9223       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9224       {
9225         --anArgIter;
9226       }
9227       aParams.IsShadowEnabled = toEnable;
9228     }
9229     else if (aFlag == "-refl"
9230           || aFlag == "-reflections")
9231     {
9232       if (toPrint)
9233       {
9234         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
9235         continue;
9236       }
9237
9238       Standard_Boolean toEnable = Standard_True;
9239       if (++anArgIter < theArgNb
9240       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9241       {
9242         --anArgIter;
9243       }
9244       aParams.IsReflectionEnabled = toEnable;
9245     }
9246     else if (aFlag == "-fsaa")
9247     {
9248       if (toPrint)
9249       {
9250         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
9251         continue;
9252       }
9253
9254       Standard_Boolean toEnable = Standard_True;
9255       if (++anArgIter < theArgNb
9256       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9257       {
9258         --anArgIter;
9259       }
9260       aParams.IsAntialiasingEnabled = toEnable;
9261     }
9262     else if (aFlag == "-gleam")
9263     {
9264       if (toPrint)
9265       {
9266         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
9267         continue;
9268       }
9269
9270       Standard_Boolean toEnable = Standard_True;
9271       if (++anArgIter < theArgNb
9272       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9273       {
9274         --anArgIter;
9275       }
9276       aParams.IsTransparentShadowEnabled = toEnable;
9277     }
9278     else if (aFlag == "-gi")
9279     {
9280       if (toPrint)
9281       {
9282         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
9283         continue;
9284       }
9285
9286       Standard_Boolean toEnable = Standard_True;
9287       if (++anArgIter < theArgNb
9288       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9289       {
9290         --anArgIter;
9291       }
9292       aParams.IsGlobalIlluminationEnabled = toEnable;
9293       if (!toEnable)
9294       {
9295         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
9296       }
9297     }
9298     else if (aFlag == "-blockedrng"
9299           || aFlag == "-brng")
9300     {
9301       if (toPrint)
9302       {
9303         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
9304         continue;
9305       }
9306
9307       Standard_Boolean toEnable = Standard_True;
9308       if (++anArgIter < theArgNb
9309         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9310       {
9311         --anArgIter;
9312       }
9313       aParams.CoherentPathTracingMode = toEnable;
9314     }
9315     else if (aFlag == "-iss")
9316     {
9317       if (toPrint)
9318       {
9319         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
9320         continue;
9321       }
9322
9323       Standard_Boolean toEnable = Standard_True;
9324       if (++anArgIter < theArgNb
9325         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9326       {
9327         --anArgIter;
9328       }
9329       aParams.AdaptiveScreenSampling = toEnable;
9330     }
9331     else if (aFlag == "-issd")
9332     {
9333       if (toPrint)
9334       {
9335         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
9336         continue;
9337       }
9338
9339       Standard_Boolean toEnable = Standard_True;
9340       if (++anArgIter < theArgNb
9341         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9342       {
9343         --anArgIter;
9344       }
9345       aParams.ShowSamplingTiles = toEnable;
9346     }
9347     else if (aFlag == "-env")
9348     {
9349       if (toPrint)
9350       {
9351         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
9352         continue;
9353       }
9354
9355       Standard_Boolean toEnable = Standard_True;
9356       if (++anArgIter < theArgNb
9357         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9358       {
9359         --anArgIter;
9360       }
9361       aParams.UseEnvironmentMapBackground = toEnable;
9362     }
9363     else if (aFlag == "-shademodel"
9364           || aFlag == "-shadingmodel"
9365           || aFlag == "-shading")
9366     {
9367       if (toPrint)
9368       {
9369         switch (aView->ShadingModel())
9370         {
9371           case V3d_COLOR:   theDI << "color ";   break;
9372           case V3d_FLAT:    theDI << "flat ";    break;
9373           case V3d_GOURAUD: theDI << "gouraud "; break;
9374           case V3d_PHONG:   theDI << "phong ";   break;
9375         }
9376         continue;
9377       }
9378
9379       if (++anArgIter >= theArgNb)
9380       {
9381         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9382       }
9383
9384       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9385       aMode.LowerCase();
9386       if (aMode == "color"
9387        || aMode == "none")
9388       {
9389         aView->SetShadingModel (V3d_COLOR);
9390       }
9391       else if (aMode == "flat"
9392             || aMode == "facet")
9393       {
9394         aView->SetShadingModel (V3d_FLAT);
9395       }
9396       else if (aMode == "gouraud"
9397             || aMode == "vertex"
9398             || aMode == "vert")
9399       {
9400         aView->SetShadingModel (V3d_GOURAUD);
9401       }
9402       else if (aMode == "phong"
9403             || aMode == "fragment"
9404             || aMode == "frag"
9405             || aMode == "pixel")
9406       {
9407         aView->SetShadingModel (V3d_PHONG);
9408       }
9409       else
9410       {
9411         std::cout << "Error: unknown shading model '" << aMode << "'\n";
9412         return 1;
9413       }
9414     }
9415     else if (aFlag == "-resolution")
9416     {
9417       if (++anArgIter >= theArgNb)
9418       {
9419         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9420         return 1;
9421       }
9422
9423       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
9424       if (aResolution.IsIntegerValue())
9425       {
9426         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
9427       }
9428       else
9429       {
9430         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9431         return 1;
9432       }
9433     }
9434     else if (aFlag == "-rebuildglsl"
9435           || aFlag == "-rebuild")
9436     {
9437       if (toPrint)
9438       {
9439         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
9440         continue;
9441       }
9442
9443       Standard_Boolean toEnable = Standard_True;
9444       if (++anArgIter < theArgNb
9445           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9446       {
9447         --anArgIter;
9448       }
9449       aParams.RebuildRayTracingShaders = toEnable;
9450     }
9451     else
9452     {
9453       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
9454       return 1;
9455     }
9456   }
9457
9458   return 0;
9459 }
9460
9461 //=======================================================================
9462 //function : VProgressiveMode
9463 //purpose  :
9464 //=======================================================================
9465 #if defined(_WIN32)
9466 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
9467                                           Standard_Integer  /*theNbArgs*/,
9468                                           const char**      /*theArgs*/)
9469 {
9470   Handle(V3d_View) aView = ViewerTest::CurrentView();
9471   if (aView.IsNull())
9472   {
9473     std::cerr << "Error: no active viewer!\n";
9474     return 1;
9475   }
9476
9477   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
9478
9479   for (;;)
9480   {
9481     aView->Redraw();
9482
9483     Standard_Boolean toExit = Standard_False;
9484
9485     MSG aMsg;
9486     while (PeekMessage (&aMsg, NULL, 0, 0, PM_REMOVE))
9487     {
9488       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
9489       {
9490         toExit = Standard_True;
9491       }
9492
9493       TranslateMessage (&aMsg);
9494       DispatchMessage  (&aMsg);
9495     }
9496
9497     if (toExit)
9498     {
9499       break;
9500     }
9501   }
9502
9503   return 0;
9504 }
9505 #endif
9506
9507 //=======================================================================
9508 //function : VFrustumCulling
9509 //purpose  : enables/disables view volume's culling.
9510 //=======================================================================
9511 static int VFrustumCulling (Draw_Interpretor& theDI,
9512                             Standard_Integer  theArgNb,
9513                             const char**      theArgVec)
9514 {
9515   Handle(V3d_View) aView = ViewerTest::CurrentView();
9516   if (aView.IsNull())
9517   {
9518     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
9519     return 1;
9520   }
9521
9522   if (theArgNb < 2)
9523   {
9524     theDI << (aView->IsCullingEnabled() ? "on" : "off");
9525     return 0;
9526   }
9527   else if (theArgNb != 2)
9528   {
9529     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
9530     return 1;
9531   }
9532
9533   TCollection_AsciiString aModeStr (theArgVec[1]);
9534   aModeStr.LowerCase();
9535   Standard_Boolean toEnable = 0;
9536   if (aModeStr == "on")
9537   {
9538     toEnable = 1;
9539   }
9540   else if (aModeStr == "off")
9541   {
9542     toEnable = 0;
9543   }
9544   else
9545   {
9546     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9547   }
9548
9549   aView->SetFrustumCulling (toEnable);
9550   aView->Redraw();
9551   return 0;
9552 }
9553
9554 //=======================================================================
9555 //function : VHighlightSelected
9556 //purpose  : 
9557 //=======================================================================
9558 static int VHighlightSelected (Draw_Interpretor& theDI,
9559                                Standard_Integer  theArgNb,
9560                                const char**      theArgVec)
9561 {
9562   if (ViewerTest::GetAISContext().IsNull())
9563   {
9564     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
9565     return 1;
9566   }
9567
9568   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9569
9570   if (theArgNb < 2)
9571   {
9572     theDI << (aContext->ToHilightSelected() ? "on" : "off");
9573     return 0;
9574   }
9575
9576   if (theArgNb != 2)
9577   {
9578     std::cout  << theArgVec[0] << " error : wrong number of parameters."
9579           << "Type 'help" << theArgVec[0] << "' for more information.";
9580     return 1;
9581   }
9582
9583   // Parse parameter
9584   TCollection_AsciiString aMode (theArgVec[1]);
9585   aMode.LowerCase();
9586   Standard_Boolean toEnable = Standard_False;
9587   if (aMode.IsEqual ("on"))
9588   {
9589     toEnable = Standard_True;
9590   }
9591   else if (aMode.IsEqual ("off"))
9592   {
9593     toEnable = Standard_False;
9594   }
9595   else
9596   {
9597     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9598   }
9599
9600   if (toEnable != aContext->ToHilightSelected())
9601   {
9602     aContext->SetToHilightSelected (toEnable);
9603
9604     // Move cursor to null position and  back to process updating of detection
9605     // and highlighting of selected object immediatly.
9606     Standard_Integer aPixX = 0;
9607     Standard_Integer aPixY = 0;
9608     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
9609
9610     anEventManager->GetCurrentPosition (aPixX, aPixY);
9611     anEventManager->MoveTo (0, 0);
9612     anEventManager->MoveTo (aPixX, aPixY);
9613   }
9614
9615   return 0;
9616 }
9617
9618 //=======================================================================
9619 //function : VXRotate
9620 //purpose  :
9621 //=======================================================================
9622 static Standard_Integer VXRotate (Draw_Interpretor& di,
9623                                    Standard_Integer argc,
9624                                    const char ** argv)
9625 {
9626   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9627   if (aContext.IsNull())
9628   {
9629     di << argv[0] << "ERROR : use 'vinit' command before \n";
9630     return 1;
9631   }
9632   
9633   if (argc != 3)
9634   {
9635     di << "ERROR : Usage : " << argv[0] << " name angle\n";
9636     return 1;
9637   }
9638
9639   TCollection_AsciiString aName (argv[1]);
9640   Standard_Real anAngle = Draw::Atof (argv[2]);
9641
9642   // find object
9643   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
9644   Handle(AIS_InteractiveObject) anIObj;
9645   if (!aMap.IsBound2 (aName) )
9646   {
9647     di << "Use 'vdisplay' before\n";
9648     return 1;
9649   }
9650   else
9651   {
9652     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
9653
9654     gp_Trsf aTransform;
9655     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
9656     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
9657
9658     aContext->SetLocation (anIObj, aTransform);
9659     aContext->UpdateCurrentViewer();
9660   }
9661
9662   return 0;
9663 }
9664
9665 //===============================================================================================
9666 //class   : ViewerTest_AISManipulator
9667 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
9668 //===============================================================================================
9669 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9670
9671 class ViewerTest_AISManipulator : public AIS_Manipulator
9672 {
9673 public:
9674
9675   ViewerTest_AISManipulator() : AIS_Manipulator()
9676   {
9677     GetMapOfAISManipulators().Add (this);
9678   }
9679
9680   virtual ~ViewerTest_AISManipulator()
9681   {
9682     GetMapOfAISManipulators().Remove (this);
9683   }
9684
9685   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9686 };
9687
9688 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9689 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9690
9691 //===============================================================================================
9692 //function : VManipulator
9693 //purpose  :
9694 //===============================================================================================
9695 static int VManipulator (Draw_Interpretor& theDi,
9696                          Standard_Integer  theArgsNb,
9697                          const char**      theArgVec)
9698 {
9699   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9700   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9701   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
9702   if (aView.IsNull()
9703    || aViewer.IsNull())
9704   {
9705     std::cerr << "No active viewer!\n";
9706     return 1;
9707   }
9708
9709   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
9710   Standard_Integer anArgIter = 1;
9711   for (; anArgIter < theArgsNb; ++anArgIter)
9712   {
9713     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
9714   }
9715
9716   ViewerTest_CmdParser aCmd;
9717   aCmd.AddDescription ("Manages manipulator for interactive objects:");
9718   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
9719   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
9720   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
9721   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
9722   aCmd.AddOption ("detach",         "...       - detach manipulator");
9723
9724   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
9725   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
9726   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
9727
9728   aCmd.AddOption ("move",   "... x y z - move object");
9729   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
9730   aCmd.AddOption ("scale",  "... factor - scale object");
9731
9732   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
9733   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
9734   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
9735   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
9736   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
9737   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
9738   aCmd.AddOption ("size",              "... size - set size of manipulator");
9739   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
9740
9741   aCmd.Parse (theArgsNb, theArgVec);
9742
9743   if (aCmd.HasOption ("help"))
9744   {
9745     theDi.PrintHelp (theArgVec[0]);
9746     return 0;
9747   }
9748
9749   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
9750
9751   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
9752
9753   if (aName.IsEmpty())
9754   {
9755     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
9756     return 1;
9757   }
9758
9759   // ----------------------------------
9760   // detach existing manipulator object
9761   // ----------------------------------
9762
9763   if (aCmd.HasOption ("detach"))
9764   {
9765     if (!aMapAIS.IsBound2 (aName))
9766     {
9767       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
9768       return 1;
9769     }
9770
9771     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9772     if (aManipulator.IsNull())
9773     {
9774       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9775       return 1;
9776     }
9777
9778     aManipulator->Detach();
9779     aMapAIS.UnBind2 (aName);
9780     ViewerTest::GetAISContext()->Remove (aManipulator);
9781
9782     return 0;
9783   }
9784
9785   // -----------------------------------------------
9786   // find or create manipulator if it does not exist
9787   // -----------------------------------------------
9788
9789   Handle(AIS_Manipulator) aManipulator;
9790   if (!aMapAIS.IsBound2 (aName))
9791   {
9792     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
9793
9794     aManipulator = new ViewerTest_AISManipulator();
9795     aMapAIS.Bind (aManipulator, aName);
9796   }
9797   else
9798   {
9799     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9800     if (aManipulator.IsNull())
9801     {
9802       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9803       return 1;
9804     }
9805   }
9806
9807   // -----------------------------------------
9808   // change properties of manipulator instance
9809   // -----------------------------------------
9810
9811   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
9812   {
9813     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
9814   }
9815   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
9816   {
9817     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
9818   }
9819   if (aCmd.HasOption ("followRotation", 1, Standard_True))
9820   {
9821     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
9822   }
9823   if (aCmd.HasOption ("gap", 1, Standard_True))
9824   {
9825     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
9826   }
9827   if (aCmd.HasOption ("part", 3, Standard_True))
9828   {
9829     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
9830     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
9831     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
9832     if (aMode < 1 || aMode > 3)
9833     {
9834       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
9835       return 1;
9836     }
9837
9838     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
9839   }
9840   if (aCmd.HasOption ("pos", 3, Standard_True))
9841   {
9842     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
9843     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
9844     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
9845
9846     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
9847   }
9848   if (aCmd.HasOption ("size", 1, Standard_True))
9849   {
9850     aManipulator->SetSize (aCmd.ArgFloat ("size"));
9851   }
9852   if (aCmd.HasOption ("zoomable", 1, Standard_True))
9853   {
9854     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
9855
9856     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
9857     {
9858       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
9859       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
9860     }
9861   }
9862
9863   // ---------------------------------------------------
9864   // attach, detach or access manipulator from an object
9865   // ---------------------------------------------------
9866
9867   if (aCmd.HasOption ("attach"))
9868   {
9869     // Find an object and attach manipulator to it
9870     if (!aCmd.HasOption ("attach", 1, Standard_True))
9871     {
9872       return 1;
9873     }
9874
9875     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
9876     if (!aMapAIS.IsBound2 (anObjName))
9877     {
9878       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
9879       return 1;
9880     }
9881
9882     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
9883     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
9884     for (; anIt.More(); anIt.Next())
9885     {
9886       if (anIt.Value()->IsAttached()
9887        && anIt.Value()->Object() == anObject)
9888       {
9889         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
9890         return 1;
9891       }
9892     }
9893
9894     AIS_Manipulator::OptionsForAttach anOptions;
9895     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
9896     {
9897       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
9898     }
9899     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
9900     {
9901       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
9902     }
9903     if (aCmd.HasOption ("enableModes", 1, Standard_True))
9904     {
9905       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
9906     }
9907
9908     aManipulator->Attach (anObject, anOptions);
9909   }
9910
9911   // --------------------------------------
9912   // apply transformation using manipulator
9913   // --------------------------------------
9914
9915   if (aCmd.HasOption ("startTransform", 2, Standard_True))
9916   {
9917     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
9918   }
9919   if (aCmd.HasOption ("transform", 2, Standard_True))
9920   {
9921     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
9922   }
9923   if (aCmd.HasOption ("stopTransform"))
9924   {
9925     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
9926
9927     aManipulator->StopTransform (toApply);
9928   }
9929
9930   gp_Trsf aT;
9931   if (aCmd.HasOption ("move", 3, Standard_True))
9932   {
9933     aT.SetTranslationPart (aCmd.ArgVec ("move"));
9934   }
9935   if (aCmd.HasOption ("rotate", 7, Standard_True))
9936   {
9937     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
9938   }
9939   if (aCmd.HasOption ("scale", 1))
9940   {
9941     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
9942   }
9943
9944   if (aT.Form() != gp_Identity)
9945   {
9946     aManipulator->Transform (aT);
9947   }
9948
9949   ViewerTest::GetAISContext()->Redisplay (aManipulator);
9950
9951   return 0;
9952 }
9953
9954 //===============================================================================================
9955 //function : parseColor
9956 //purpose  :
9957 //===============================================================================================
9958 static Standard_Boolean parseColor (ViewerTest_CmdParser& theParser,
9959                                     const std::string&    theOptionName,
9960                                     Quantity_Color&       theColor)
9961 {
9962   std::string aColorArg = theParser.Arg (theOptionName, 0);
9963   if (std::isdigit (aColorArg[0]))
9964   {
9965     Graphic3d_Vec3d aColor = theParser.ArgVec3d (theOptionName);
9966     if (aColor.x() < 0.0 || aColor.x() > 1.0
9967       || aColor.y() < 0.0 || aColor.y() > 1.0
9968       || aColor.z() < 0.0 || aColor.z() > 1.0)
9969     {
9970       std::cerr << "Error: RGB color values should be within range 0..1!\n";
9971       return Standard_False;
9972     }
9973     theColor.SetValues (aColor.x(), aColor.y(), aColor.z(), Quantity_TOC_RGB);
9974   }
9975   else
9976   {
9977     Quantity_NameOfColor aName = Quantity_NOC_BLACK;
9978     if (!Quantity_Color::ColorFromName (aColorArg.c_str(), aName))
9979     {
9980       std::cerr << "Name: " << theParser.Arg (theOptionName, 0)
9981                 << " does not correspond to any color in Quantity_NameOfColor!"
9982                 << std::endl;
9983       return Standard_False;
9984     }
9985     theColor.SetValues (aName);
9986   }
9987
9988   return Standard_True;
9989 }
9990
9991 //===============================================================================================
9992 //function : VSelectionProperties
9993 //purpose  :
9994 //===============================================================================================
9995 static int VSelectionProperties (Draw_Interpretor& theDi,
9996                                  Standard_Integer  theArgsNb,
9997                                  const char**      theArgVec)
9998 {
9999   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10000   if (aCtx.IsNull())
10001   {
10002     std::cerr << "No active viewer!\n";
10003     return 1;
10004   }
10005
10006   ViewerTest_CmdParser aCmd;
10007
10008   aCmd.AddOption ("autoActivate");
10009   aCmd.AddOption ("pixTol");
10010
10011   aCmd.AddOption ("selColor");
10012   aCmd.AddOption ("hiColor");
10013   aCmd.AddOption ("selTransp");
10014   aCmd.AddOption ("hiTransp");
10015
10016   aCmd.AddOption ("print");
10017
10018   aCmd.Parse (theArgsNb, theArgVec);
10019
10020   if (aCmd.HasOption ("help"))
10021   {
10022     theDi.PrintHelp (theArgVec[0]);
10023     return 0;
10024   }
10025
10026   if (aCmd.HasOption ("autoActivate", 1, Standard_False))
10027   {
10028     aCtx->SetAutoActivateSelection (aCmd.ArgBool ("autoActivate"));
10029   }
10030   if (aCmd.HasOption ("pixTol", 1, Standard_False))
10031   {
10032     aCtx->SetPixelTolerance (aCmd.ArgInt ("pixTol"));
10033   }
10034
10035   const Handle(Graphic3d_HighlightStyle)& aHiStyle  = aCtx->HighlightStyle();
10036   const Handle(Graphic3d_HighlightStyle)& aSelStyle = aCtx->SelectionStyle();
10037   Standard_Boolean toRedraw = Standard_False;
10038   if (aCmd.HasOption ("selColor"))
10039   {
10040     Quantity_Color aNewColor;
10041     if (!parseColor (aCmd, "selColor", aNewColor))
10042       return 1;
10043     aSelStyle->SetColor (aNewColor);
10044     toRedraw = Standard_True;
10045   }
10046   if (aCmd.HasOption ("hiColor"))
10047   {
10048     Quantity_Color aNewColor;
10049     if (!parseColor (aCmd, "hiColor", aNewColor))
10050       return 1;
10051     aHiStyle->SetColor (aNewColor);
10052   }
10053   if (aCmd.HasOption ("selTransp"))
10054   {
10055     aSelStyle->SetTransparency (aCmd.ArgFloat ("selTransp"));
10056     toRedraw = Standard_True;
10057   }
10058   if (aCmd.HasOption ("hiTransp"))
10059   {
10060     aHiStyle->SetTransparency (aCmd.ArgFloat ("hiTransp"));
10061   }
10062
10063   if (aCmd.HasOption ("print") || theArgsNb == 1)
10064   {
10065     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
10066     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
10067     theDi << "Selection color                : " << Quantity_Color::StringName (aCtx->SelectionStyle()->Color().Name()) << "\n";
10068     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aCtx->HighlightStyle()->Color().Name()) << "\n";
10069     theDi << "Selection transparency         : " << aCtx->SelectionStyle()->Transparency() << "\n";
10070     theDi << "Dynamic highlight transparency : " << aCtx->HighlightStyle()->Transparency() << "\n";
10071   }
10072
10073   if (aCtx->NbSelected() != 0 && toRedraw)
10074   {
10075     aCtx->HilightSelected (Standard_True);
10076   }
10077
10078   return 0;
10079 }
10080
10081 //=======================================================================
10082 //function : ViewerCommands
10083 //purpose  :
10084 //=======================================================================
10085
10086 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
10087 {
10088
10089   const char *group = "ZeViewer";
10090   theCommands.Add("vinit",
10091 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10092     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10093 #else
10094     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10095 #endif
10096     " - Creates new View window with specified name view_name.\n"
10097     "By default the new view is created in the viewer and in"
10098     " graphic driver shared with active view.\n"
10099     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
10100     "If driverName isn't specified the driver will be shared with active view.\n"
10101     "If viewerName isn't specified the viewer will be shared with active view.\n"
10102 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10103     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
10104     "is used in creation of graphic driver\n"
10105 #endif
10106     " - l, t: pixel position of left top corner of the window\n"
10107     " - w,h: width and heigth of window respectively.\n"
10108     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
10109     __FILE__,VInit,group);
10110   theCommands.Add("vclose" ,
10111     "[view_id [keep_context=0|1]]\n"
10112     "or vclose ALL - to remove all created views\n"
10113     " - removes view(viewer window) defined by its view_id.\n"
10114     " - keep_context: by default 0; if 1 and the last view is deleted"
10115     " the current context is not removed.",
10116     __FILE__,VClose,group);
10117   theCommands.Add("vactivate" ,
10118     "view_id"
10119     " - activates view(viewer window) defined by its view_id",
10120     __FILE__,VActivate,group);
10121   theCommands.Add("vviewlist",
10122     "vviewlist [format={tree, long}]"
10123     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
10124     " - format: format of result output, if tree the output is a tree view;"
10125     "otherwise it's a list of full view names. By default format = tree",
10126     __FILE__,VViewList,group);
10127   theCommands.Add("vhelp" ,
10128     "vhelp            : display help on the viewer commands",
10129     __FILE__,VHelp,group);
10130   theCommands.Add("vtop" ,
10131     "vtop or <T>      : Top view. Orientation +X+Y" ,
10132     __FILE__,VTop,group);
10133   theCommands.Add("vbottom" ,
10134     "vbottom          : Bottom view. Orientation +X-Y" ,
10135     __FILE__,VBottom,group);
10136   theCommands.Add("vleft" ,
10137     "vleft            : Left view. Orientation -Y+Z" ,
10138     __FILE__,VLeft,group);
10139   theCommands.Add("vright" ,
10140     "vright           : Right view. Orientation +Y+Z" ,
10141     __FILE__,VRight,group);
10142   theCommands.Add("vaxo" ,
10143     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
10144     __FILE__,VAxo,group);
10145   theCommands.Add("vfront" ,
10146     "vfront           : Front view. Orientation +X+Z" ,
10147     __FILE__,VFront,group);
10148   theCommands.Add("vback" ,
10149     "vback            : Back view. Orientation -X+Z" ,
10150     __FILE__,VBack,group);
10151   theCommands.Add("vpick" ,
10152     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
10153     VPick,group);
10154   theCommands.Add("vfit",
10155     "vfit or <F> [-selected] [-noupdate]"
10156     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
10157     __FILE__,VFit,group);
10158   theCommands.Add ("vfitarea",
10159     "vfitarea x1 y1 x2 y2"
10160     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
10161     "\n\t\t: Fit view to show area located between two points"
10162     "\n\t\t: given in world 2D or 3D corrdinates.",
10163     __FILE__, VFitArea, group);
10164   theCommands.Add ("vzfit", "vzfit [scale]\n"
10165     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
10166     "   \"scale\" - specifies factor to scale computed z range.\n",
10167     __FILE__, VZFit, group);
10168   theCommands.Add("vrepaint",
10169     "vrepaint        : vrepaint, force redraw",
10170     __FILE__,VRepaint,group);
10171   theCommands.Add("vclear",
10172     "vclear          : vclear"
10173     "\n\t\t: remove all the object from the viewer",
10174     __FILE__,VClear,group);
10175   theCommands.Add("vsetbg",
10176     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
10177     __FILE__,VSetBg,group);
10178   theCommands.Add("vsetbgmode",
10179     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
10180     __FILE__,VSetBgMode,group);
10181   theCommands.Add("vsetgradientbg",
10182     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
10183     __FILE__,VSetGradientBg,group);
10184   theCommands.Add("vsetgrbgmode",
10185     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
10186     __FILE__,VSetGradientBgMode,group);
10187   theCommands.Add("vsetcolorbg",
10188     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
10189     __FILE__,VSetColorBg,group);
10190   theCommands.Add("vsetdefaultbg",
10191     "vsetdefaultbg r g b\n"
10192     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
10193     "\n\t\t: Set default viewer background fill color (flat/gradient).",
10194     __FILE__,VSetDefaultBg,group);
10195   theCommands.Add("vscale",
10196     "vscale          : vscale X Y Z",
10197     __FILE__,VScale,group);
10198   theCommands.Add("vzbufftrihedron",
10199             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
10200     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
10201     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
10202     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
10203     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
10204     "\n\t\t: Displays a trihedron",
10205     __FILE__,VZBuffTrihedron,group);
10206   theCommands.Add("vrotate",
10207     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
10208     "\n                : Option -mouseStart starts rotation according to the mouse position"
10209     "\n                : Option -mouseMove continues rotation with angle computed"
10210     "\n                : from last and new mouse position."
10211     "\n                : vrotate AX AY AZ [X Y Z]",
10212     __FILE__,VRotate,group);
10213   theCommands.Add("vzoom",
10214     "vzoom           : vzoom coef",
10215     __FILE__,VZoom,group);
10216   theCommands.Add("vpan",
10217     "vpan            : vpan dx dy",
10218     __FILE__,VPan,group);
10219   theCommands.Add("vexport",
10220     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
10221     " : exports the view to a vector file of a given format"
10222     " : notice that EMF format requires patched gl2ps",
10223     __FILE__,VExport,group);
10224   theCommands.Add("vcolorscale",
10225     "vcolorscale     : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16  -textpos "
10226     "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n"
10227     "-demo/-demoversion draw a demoversion of color scale.\n"
10228     "-show/display display color scale.\n"
10229     "-hide/erase erase color scale.\n"
10230     "Please note that -show/-hide option must be the first argument!\n"
10231     "-color Index R G B: set color for indexed interval\n"
10232     "-color Index ColorName: set color for indexed interval\n"
10233     "-colors R G B R G B ...: set colors for all intervals\n"
10234     "-colors ColorName1 ColorName2 ...: set colors for all intervals\n"
10235     "-colors supports both color names and rgb values in one call\n"
10236     "-label Index Text: set label for indexed interval\n"
10237     "-labels Text Text Text ...: set labels for all intervals\n"
10238     "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n"
10239     "Available text positions: left, right, center, none;\n",
10240     __FILE__,VColorScale,group);
10241   theCommands.Add("vgraduatedtrihedron",
10242     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
10243     "\t[-namefont Name] [-valuesfont Name]\n"
10244     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
10245     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
10246     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
10247     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
10248     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
10249     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
10250     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
10251     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
10252     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
10253     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
10254     " - Displays or erases graduated trihedron"
10255     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
10256     " - namefont - font of axes names. Default: Arial\n"
10257     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
10258     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
10259     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
10260     " - valuesfont - font of axes values. Default: Arial\n"
10261     " - xcolor, ycolor, zcolor - color of axis and values\n"
10262     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
10263     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
10264     __FILE__,VGraduatedTrihedron,group);
10265   theCommands.Add("vtile" ,
10266             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
10267     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
10268     "\n\t\t:  -totalSize the size of virtual bigger viewport"
10269     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
10270     "\n\t\t:  -lowerLeft tile offset as lower left corner"
10271     "\n\t\t:  -upperLeft tile offset as upper left corner",
10272     __FILE__, VTile, group);
10273   theCommands.Add("vzlayer",
10274               "vzlayer [layerId]"
10275       "\n\t\t:         [-add|-delete|-get|-settings]"
10276       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
10277       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
10278       "\n\t\t: ZLayer list management:"
10279       "\n\t\t:   -add      add new z layer to viewer and print its id"
10280       "\n\t\t:   -delete   delete z layer"
10281       "\n\t\t:   -get      print sequence of z layers"
10282       "\n\t\t:   -settings print status of z layer settings"
10283       "\n\t\t:   -disable  disables given setting"
10284       "\n\t\t:   -enable   enables  given setting",
10285     __FILE__,VZLayer,group);
10286   theCommands.Add("vlayerline",
10287     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
10288     __FILE__,VLayerLine,group);
10289   theCommands.Add ("vgrid",
10290     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
10291     " : Mode - rectangular or circular"
10292     " : Type - lines or points",
10293     __FILE__, VGrid, group);
10294   theCommands.Add ("vpriviledgedplane",
10295     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
10296     "\n\t\t:   Ox, Oy, Oz - plane origin"
10297     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
10298     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
10299     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
10300     __FILE__, VPriviledgedPlane, group);
10301   theCommands.Add ("vconvert",
10302     "vconvert v [Mode={window|view}]"
10303     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
10304     "\n\t\t: vconvert x y z [Mode={window|grid}]"
10305     "\n\t\t:   window - convert to window coordinates, pixels"
10306     "\n\t\t:   view   - convert to view projection plane"
10307     "\n\t\t:   grid   - convert to model coordinates, given on grid"
10308     "\n\t\t:   ray    - convert projection ray to model coordiantes"
10309     "\n\t\t: - vconvert v window : convert view to window;"
10310     "\n\t\t: - vconvert v view   : convert window to view;"
10311     "\n\t\t: - vconvert x y window : convert view to window;"
10312     "\n\t\t: - vconvert x y view : convert window to view;"
10313     "\n\t\t: - vconvert x y : convert window to model;"
10314     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
10315     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
10316     "\n\t\t: - vconvert x y z window : convert model to window;"
10317     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
10318     "\n\t\t: Converts the given coordinates to window/view/model space.",
10319     __FILE__, VConvert, group);
10320   theCommands.Add ("vfps",
10321     "vfps [framesNb=100] : estimate average frame rate for active view",
10322     __FILE__, VFps, group);
10323   theCommands.Add ("vgldebug",
10324             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
10325     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
10326     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
10327     "\n\t\t: Debug context can be requested only on Windows"
10328     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
10329     "\n\t\t:  -sync     - request synchronized debug GL context"
10330     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
10331     "\n\t\t:              which are suppressed by default,"
10332     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
10333     "\n\t\t:              which are suppressed by default",
10334     __FILE__, VGlDebug, group);
10335   theCommands.Add ("vvbo",
10336     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
10337     __FILE__, VVbo, group);
10338   theCommands.Add ("vstereo",
10339             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
10340     "\n\t\t:         [-anaglyph Filter]"
10341     "\n\t\t: Control stereo output mode. Available modes for -mode:"
10342     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
10343     "\n\t\t:                     requires driver support."
10344     "\n\t\t:                     Should be called BEFORE vinit!"
10345     "\n\t\t:  anaglyph         - Anaglyph glasses"
10346     "\n\t\t:  rowInterlaced    - row-interlaced display"
10347     "\n\t\t:  columnInterlaced - column-interlaced display"
10348     "\n\t\t:  chessBoard       - chess-board output"
10349     "\n\t\t:  sideBySide       - horizontal pair"
10350     "\n\t\t:  overUnder        - vertical   pair"
10351     "\n\t\t: Available Anaglyph filters for -anaglyph:"
10352     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
10353     "\n\t\t:  greenMagentaSimple",
10354     __FILE__, VStereo, group);
10355   theCommands.Add ("vcaps",
10356             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
10357     "\n\t\t:       [-compatibleProfile {0|1}]"
10358     "\n\t\t:       [-vsync {0|1}]"
10359     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
10360     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
10361     "\n\t\t: Modify particular graphic driver options:"
10362     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
10363     "\n\t\t:             built-in GLSL programs"
10364     "\n\t\t:            (requires compatible profile)"
10365     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
10366     "\n\t\t:             arrays to GPU memory)"
10367     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
10368     "\n\t\t:  vsync    - switch VSync on or off"
10369     "\n\t\t: Context creation options:"
10370     "\n\t\t:  softMode          - software OpenGL implementation"
10371     "\n\t\t:  compatibleProfile - backward-compatible profile"
10372     "\n\t\t:  quadbuffer        - QuadBuffer"
10373     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
10374     "\n\t\t: rendering paths producing the same visual result when"
10375     "\n\t\t: possible."
10376     "\n\t\t: Command is intended for testing old hardware compatibility.",
10377     __FILE__, VCaps, group);
10378   theCommands.Add ("vmemgpu",
10379     "vmemgpu [f]: print system-dependent GPU memory information if available;"
10380     " with f option returns free memory in bytes",
10381     __FILE__, VMemGpu, group);
10382   theCommands.Add ("vreadpixel",
10383     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
10384     " : Read pixel value for active view",
10385     __FILE__, VReadPixel, group);
10386   theCommands.Add("diffimage",
10387     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
10388     __FILE__, VDiffImage, group);
10389   theCommands.Add ("vselect",
10390     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
10391     "- emulates different types of selection:\n"
10392     "- 1) single click selection\n"
10393     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
10394     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
10395     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
10396     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
10397     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
10398     " (partial inclusion - overlap - is not allowed by default)\n"
10399     "- 5) any of these selections with shift button pressed",
10400     __FILE__, VSelect, group);
10401   theCommands.Add ("vmoveto",
10402     "vmoveto x y"
10403     "- emulates cursor movement to pixel postion (x,y)",
10404     __FILE__, VMoveTo, group);
10405   theCommands.Add ("vviewparams",
10406               "vviewparams [-args] [-scale [s]]"
10407       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
10408       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
10409       "\n\t\t: Manage current view parameters or prints all"
10410       "\n\t\t: current values when called without argument."
10411       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
10412       "\n\t\t:   -eye  [x y z] prints or sets eye location"
10413       "\n\t\t:   -at   [x y z] prints or sets center of look"
10414       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
10415       "\n\t\t:   -proj [x y z] prints or sets direction of look"
10416       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
10417       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
10418       "\n\t\t:                 or changes the size of its maximum dimension"
10419       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
10420     __FILE__, VViewParams, group);
10421
10422   theCommands.Add("vanimation", "Alias for vanim",
10423     __FILE__, VAnimation, group);
10424
10425   theCommands.Add("vanim",
10426             "List existing animations:"
10427     "\n\t\t:  vanim"
10428     "\n\t\t: Animation playback:"
10429     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
10430     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
10431     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
10432     "\n\t\t:   -freeLook skip camera animations"
10433     "\n\t\t:   -lockLoop disable any interactions"
10434     "\n\t\t:"
10435     "\n\t\t: Animation definition:"
10436     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
10437     "\n\t\t:        [start TimeSec] [duration TimeSec]"
10438     "\n\t\t:"
10439     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
10440     "\n\t\t: specifies nested animations."
10441     "\n\t\t: There is no syntax to explicitly add new animation,"
10442     "\n\t\t: and all non-existing animations within the name will be"
10443     "\n\t\t: implicitly created on first use (including parents)."
10444     "\n\t\t:"
10445     "\n\t\t: Each animation might define the SINGLE action (see below),"
10446     "\n\t\t: like camera transition, object transformation or custom callback."
10447     "\n\t\t: Child animations can be used for defining concurrent actions."
10448     "\n\t\t:"
10449     "\n\t\t: Camera animation:"
10450     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
10451     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
10452     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
10453     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
10454     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
10455     "\n\t\t:   -atX    camera Center positions pair"
10456     "\n\t\t:   -upX    camera Up directions pair"
10457     "\n\t\t:   -scaleX camera Scale factors pair"
10458     "\n\t\t: Object animation:"
10459     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
10460     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
10461     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
10462     "\n\t\t:   -locX   object Location points pair (translation)"
10463     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
10464     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
10465     "\n\t\t: Custom callback:"
10466     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
10467     "\n\t\t:   %Pts        overall animation presentation timestamp"
10468     "\n\t\t:   %LocalPts   local animation timestamp"
10469     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
10470     __FILE__, VAnimation, group);
10471
10472   theCommands.Add("vchangeselected",
10473     "vchangeselected shape"
10474     "- adds to shape to selection or remove one from it",
10475                 __FILE__, VChangeSelected, group);
10476   theCommands.Add ("vnbselected",
10477     "vnbselected"
10478     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
10479   theCommands.Add ("vcamera",
10480               "vcamera [-ortho] [-projtype]"
10481       "\n\t\t:         [-persp]"
10482       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
10483       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
10484       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
10485       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
10486       "\n\t\t: Manage camera parameters."
10487       "\n\t\t: Prints current value when option called without argument."
10488       "\n\t\t: Orthographic camera:"
10489       "\n\t\t:   -ortho      activate orthographic projection"
10490       "\n\t\t: Perspective camera:"
10491       "\n\t\t:   -persp      activate perspective  projection (mono)"
10492       "\n\t\t:   -fovy       field of view in y axis, in degrees"
10493       "\n\t\t:   -distance   distance of eye from camera center"
10494       "\n\t\t: Stereoscopic camera:"
10495       "\n\t\t:   -stereo     perspective  projection (stereo)"
10496       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
10497       "\n\t\t:   -rightEye   perspective  projection (right eye)"
10498       "\n\t\t:   -iod        intraocular distance value"
10499       "\n\t\t:   -iodType    distance type, absolute or relative"
10500       "\n\t\t:   -zfocus     stereographic focus value"
10501       "\n\t\t:   -zfocusType focus type, absolute or relative",
10502     __FILE__, VCamera, group);
10503   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
10504     "- vautozfit [on={1|0}] [scale]\n"
10505     "    Prints or changes parameters of automatic z-fit mode:\n"
10506     "   \"on\" - turns automatic z-fit on or off\n"
10507     "   \"scale\" - specifies factor to scale computed z range.\n",
10508     __FILE__, VAutoZFit, group);
10509   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
10510     "   vzrange                - without parameters shows current values\n"
10511     "   vzrange [znear] [zfar] - applies provided values to view",
10512     __FILE__,VZRange, group);
10513   theCommands.Add ("vpurgedisplay",
10514     "vpurgedisplay"
10515     "- removes structures which don't belong to objects displayed in neutral point",
10516     __FILE__, VPurgeDisplay, group);
10517   theCommands.Add("vsetviewsize",
10518     "vsetviewsize size",
10519     __FILE__,VSetViewSize,group);
10520   theCommands.Add("vmoveview",
10521     "vmoveview Dx Dy Dz [Start = 1|0]",
10522     __FILE__,VMoveView,group);
10523   theCommands.Add("vtranslateview",
10524     "vtranslateview Dx Dy Dz [Start = 1|0)]",
10525     __FILE__,VTranslateView,group);
10526   theCommands.Add("vturnview",
10527     "vturnview Ax Ay Az [Start = 1|0]",
10528     __FILE__,VTurnView,group);
10529   theCommands.Add("vtextureenv",
10530     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
10531     "or user-defined file and optionally applying texture mapping parameters\n"
10532     "                  Usage:\n"
10533     "                  vtextureenv off - disables environment mapping\n"
10534     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
10535     "                              std_texture = (0..7)\n"
10536     "                              rep         = {clamp|repeat}\n"
10537     "                              mod         = {decal|modulate}\n"
10538     "                              flt         = {nearest|bilinear|trilinear}\n"
10539     "                              ss, st      - scale factors for s and t texture coordinates\n"
10540     "                              ts, tt      - translation for s and t texture coordinates\n"
10541     "                              rot         - texture rotation angle in degrees",
10542     __FILE__, VTextureEnv, group);
10543   theCommands.Add("vhlr" ,
10544     "is_enabled={on|off} [show_hidden={1|0}]"
10545     " - Hidden line removal algorithm:"
10546     " - is_enabled: if is on HLR algorithm is applied\n"
10547     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
10548     __FILE__,VHLR,group);
10549   theCommands.Add("vhlrtype" ,
10550     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
10551     " - Changes the type of HLR algorithm using for shapes."
10552     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
10553     "   if equals to polyalgo, polygonal HLR algorithm is applied."
10554     "If shapes are not given HLR algoithm of given type is applied"
10555     " to all shapes in the view\n",
10556     __FILE__,VHLRType,group);
10557   theCommands.Add("vclipplane",
10558               "vclipplane planeName [{0|1}]"
10559       "\n\t\t:   [-equation A B C D]"
10560       "\n\t\t:   [-set|-unset [objects|views]]"
10561       "\n\t\t:   [-maxPlanes]"
10562       "\n\t\t:   [-capping {0|1}]"
10563       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
10564       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
10565       "\n\t\t:       [-texRotate Angle]"
10566       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
10567       "\n\t\t:       [-useObjShader {0|1}]"
10568       "\n\t\t: Clipping planes management:"
10569       "\n\t\t:   -maxPlanes   print plane limit for view"
10570       "\n\t\t:   -delete      delete plane with given name"
10571       "\n\t\t:   {off|on|0|1} turn clipping on/off"
10572       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
10573       "\n\t\t:                applied to active View when list is omitted"
10574       "\n\t\t:   -equation A B C D change plane equation"
10575       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
10576       "\n\t\t: Capping options:"
10577       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
10578       "\n\t\t:   -color R G B          set capping color"
10579       "\n\t\t:   -texName Texture      set capping texture"
10580       "\n\t\t:   -texScale SX SY       set capping tex scale"
10581       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
10582       "\n\t\t:   -texRotate Angle      set capping tex rotation"
10583       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
10584       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
10585       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
10586       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
10587       __FILE__, VClipPlane, group);
10588   theCommands.Add("vdefaults",
10589                "vdefaults [-absDefl value]"
10590        "\n\t\t:           [-devCoeff value]"
10591        "\n\t\t:           [-angDefl value]"
10592        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
10593     , __FILE__, VDefaults, group);
10594   theCommands.Add("vlight",
10595     "tool to manage light sources, without arguments shows list of lights."
10596     "\n    Main commands: "
10597     "\n      'clear' to clear lights"
10598     "\n      '{def}aults' to load deafault lights"
10599     "\n      'add' (or 'new') <type> to add any light source"
10600     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
10601     "\n      'change' <lightId> to edit light source with specified lightId"
10602     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
10603     "\n        {pos}ition X Y Z"
10604     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
10605     "\n        color colorName"
10606     "\n        {head}light 0|1"
10607     "\n        {sm}oothness value"
10608     "\n        {int}ensity value"
10609     "\n        {constAtten}uation value"
10610     "\n        {linearAtten}uation value"
10611     "\n        angle angleDeg"
10612     "\n        {spotexp}onent value"
10613     "\n        local|global"
10614     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
10615     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
10616     __FILE__, VLight, group);
10617   theCommands.Add("vraytrace",
10618             "vraytrace [0|1]"
10619     "\n\t\t: Turns on/off ray-tracing renderer."
10620     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
10621     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
10622     __FILE__, VRenderParams, group);
10623   theCommands.Add("vrenderparams",
10624     "\n    Manages rendering parameters: "
10625     "\n      '-raster'               Disables GPU ray-tracing"
10626     "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
10627     "\n      '-rayTrace'             Enables  GPU ray-tracing"
10628     "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
10629     "\n      '-shadows      on|off'  Enables/disables shadows rendering"
10630     "\n      '-reflections  on|off'  Enables/disables specular reflections"
10631     "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
10632     "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
10633     "\n      '-gi           on|off'  Enables/disables global illumination effects"
10634     "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
10635     "\n      '-env          on|off'  Enables/disables environment map background"
10636     "\n      '-iss          on|off'  Enables/disables adaptive screen sampling (PT mode)"
10637     "\n      '-issd         on|off'  Shows screen sampling distribution in ISS mode"
10638     "\n      '-rebuildGlsl  on|off'  Rebuild Ray-Tracing GLSL programs (for debugging)"
10639     "\n      '-shadingModel model'   Controls shading model from enumeration"
10640     "\n                              color, flat, gouraud, phong"
10641     "\n      '-resolution   value'   Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
10642     "\n    Unlike vcaps, these parameters dramatically change visual properties."
10643     "\n    Command is intended to control presentation quality depending on"
10644     "\n    hardware capabilities and performance.",
10645     __FILE__, VRenderParams, group);
10646   theCommands.Add("vfrustumculling",
10647     "vfrustumculling [toEnable]: enables/disables objects clipping",
10648     __FILE__,VFrustumCulling,group);
10649   theCommands.Add("vhighlightselected",
10650     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
10651     "Without arguments it shows if highlighting of selected objects is enabled now.",
10652     __FILE__,VHighlightSelected,group);
10653   theCommands.Add ("vplace",
10654             "vplace dx dy"
10655     "\n\t\t: Places the point (in pixels) at the center of the window",
10656     __FILE__, VPlace, group);
10657   theCommands.Add("vxrotate",
10658     "vxrotate",
10659     __FILE__,VXRotate,group);
10660
10661     theCommands.Add("vmanipulator",
10662       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
10663       "\n    tool to create and manage AIS manipulators."
10664       "\n    Options: "
10665       "\n      '-attach AISObject'                 attach manipulator to AISObject"
10666       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
10667       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
10668       "\n      '-enableModes    {0|1}'             enable modes when attaching"
10669       "\n      '-detach'                           detach manipulator"
10670       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
10671       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
10672       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
10673       "\n      '-move x y z'                     - move attached object"
10674       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
10675       "\n      '-scale factor'                   - scale attached object"
10676       "\n      '-autoActivate      {0|1}'        - set activation on detection"
10677       "\n      '-followTranslation {0|1}'        - set following translation transform"
10678       "\n      '-followRotation    {0|1}'        - set following rotation transform"
10679       "\n      '-gap value'                      - set gap between sub-parts"
10680       "\n      '-part axis mode    {0|1}'        - set visual part"
10681       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
10682       "\n      '-size value'                     - set size of manipulator"
10683       "\n      '-zoomable {0|1}'                 - set zoom persistence",
10684     __FILE__, VManipulator, group);
10685
10686   theCommands.Add("vselprops",
10687     "\n    vselprops [options]"
10688     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
10689     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
10690     "\n    -pixTol    value        : sets up pixel tolerance"
10691     "\n    -selColor  {name|r g b} : sets selection color"
10692     "\n    -hiColor   {name|r g b} : sets dynamic highlight color"
10693     "\n    -selTransp value        : sets transparency coefficient for selection"
10694     "\n    -hiTransp  value        : sets transparency coefficient for dynamic highlight"
10695     "\n    -print                  : prints current state of all mentioned parameters",
10696     __FILE__, VSelectionProperties, group);
10697
10698 #if defined(_WIN32)
10699   theCommands.Add("vprogressive",
10700     "vprogressive",
10701     __FILE__, VProgressiveMode, group);
10702 #endif
10703 }