ff91e617b2f9c7de16b97f425490c118fd132b90
[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 #include <AIS_ColorScale.hxx>
19 #include <AIS_Manipulator.hxx>
20 #include <AIS_RubberBand.hxx>
21 #include <AIS_Shape.hxx>
22 #include <AIS_InteractiveObject.hxx>
23 #include <AIS_ListOfInteractive.hxx>
24 #include <AIS_ListIteratorOfListOfInteractive.hxx>
25 #include <DBRep.hxx>
26 #include <Graphic3d_ArrayOfPolylines.hxx>
27 #include <Graphic3d_AspectMarker3d.hxx>
28 #include <Graphic3d_ExportFormat.hxx>
29 #include <Graphic3d_NameOfTextureEnv.hxx>
30 #include <Graphic3d_GraduatedTrihedron.hxx>
31 #include <Graphic3d_TextureEnv.hxx>
32 #include <Graphic3d_TextureParams.hxx>
33 #include <Graphic3d_TypeOfTextureFilter.hxx>
34 #include <Graphic3d_AspectFillArea3d.hxx>
35 #include <ViewerTest.hxx>
36 #include <ViewerTest_AutoUpdater.hxx>
37 #include <ViewerTest_EventManager.hxx>
38 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
39 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
40 #include <ViewerTest_CmdParser.hxx>
41 #include <V3d_AmbientLight.hxx>
42 #include <V3d_DirectionalLight.hxx>
43 #include <V3d_PositionalLight.hxx>
44 #include <V3d_SpotLight.hxx>
45 #include <NCollection_DoubleMap.hxx>
46 #include <NCollection_List.hxx>
47 #include <NCollection_Vector.hxx>
48 #include <AIS_InteractiveContext.hxx>
49 #include <Draw_Interpretor.hxx>
50 #include <Draw.hxx>
51 #include <Draw_Appli.hxx>
52 #include <Image_AlienPixMap.hxx>
53 #include <OpenGl_GraphicDriver.hxx>
54 #include <OSD_Timer.hxx>
55 #include <TColStd_HSequenceOfAsciiString.hxx>
56 #include <TColStd_SequenceOfInteger.hxx>
57 #include <TColStd_HSequenceOfReal.hxx>
58 #include <TColgp_Array1OfPnt2d.hxx>
59 #include <TColStd_MapOfAsciiString.hxx>
60 #include <Aspect_TypeOfLine.hxx>
61 #include <Image_Diff.hxx>
62 #include <Aspect_DisplayConnection.hxx>
63 #include <gp_Pnt.hxx>
64 #include <gp_Dir.hxx>
65 #include <gp_Pln.hxx>
66 #include <PrsMgr_PresentableObject.hxx>
67 #include <Graphic3d_ClipPlane.hxx>
68 #include <NCollection_DataMap.hxx>
69 #include <Graphic3d_Texture2Dmanual.hxx>
70 #include <Prs3d_ShadingAspect.hxx>
71 #include <Prs3d_Drawer.hxx>
72 #include <Prs3d_LineAspect.hxx>
73 #include <Prs3d_Root.hxx>
74
75 #ifdef _WIN32
76 #undef DrawText
77 #endif
78
79 #include <cstdlib>
80
81 #if defined(_WIN32)
82   #include <WNT_WClass.hxx>
83   #include <WNT_Window.hxx>
84 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
85   #include <Cocoa_Window.hxx>
86 #else
87   #include <Xw_Window.hxx>
88   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
89   #include <X11/Xutil.h>
90   #include <tk.h>
91 #endif
92
93 // Auxiliary definitions
94 static const char THE_KEY_DELETE = 127;
95
96 //==============================================================================
97 //  VIEWER GLOBAL VARIABLES
98 //==============================================================================
99
100 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
101 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
102
103 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
104 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
105
106 extern int VErase (Draw_Interpretor& theDI,
107                    Standard_Integer  theArgNb,
108                    const char**      theArgVec);
109
110 #if defined(_WIN32)
111 static Handle(WNT_Window)& VT_GetWindow() {
112   static Handle(WNT_Window) WNTWin;
113   return WNTWin;
114 }
115 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
116 static Handle(Cocoa_Window)& VT_GetWindow()
117 {
118   static Handle(Cocoa_Window) aWindow;
119   return aWindow;
120 }
121 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
122 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
123 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
124
125 #else
126 static Handle(Xw_Window)& VT_GetWindow(){
127   static Handle(Xw_Window) XWWin;
128   return XWWin;
129 }
130
131 static void VProcessEvents(ClientData,int);
132 #endif
133
134 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
135 {
136   static Handle(Aspect_DisplayConnection) aDisplayConnection;
137   return aDisplayConnection;
138 }
139
140 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
141 {
142   GetDisplayConnection() = theDisplayConnection;
143 }
144
145 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
146 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
147 {
148   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
149 #if defined(_WIN32)
150   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
151   if (!aWindow.IsNull())
152     return aWindow->HWindow();
153 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
154   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156   return aWindow->XWindow();
157 #endif
158   return aWindowHandle;
159 }
160 #endif
161
162 static Standard_Boolean MyHLRIsOn = Standard_False;
163
164 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
165 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
166 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
167 static OpenGl_Caps ViewerTest_myDefaultCaps;
168
169 static void OSWindowSetup();
170
171 static struct
172 {
173   Quantity_Color FlatColor;
174   Quantity_Color GradientColor1;
175   Quantity_Color GradientColor2;
176   Aspect_GradientFillMethod FillMethod;
177 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
178
179 //==============================================================================
180 //  EVENT GLOBAL VARIABLES
181 //==============================================================================
182
183 static int Start_Rot = 0;
184 int X_Motion = 0; // Current cursor position
185 int Y_Motion = 0;
186 int X_ButtonPress = 0; // Last ButtonPress position
187 int Y_ButtonPress = 0;
188 Standard_Boolean IsDragged = Standard_False;
189 Standard_Boolean DragFirst = Standard_False;
190
191
192 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
193 {
194   static Handle(AIS_RubberBand) aBand;
195   if (aBand.IsNull())
196   {
197     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
198     aBand->SetDisplayMode (0);
199   }
200   return aBand;
201 }
202
203 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
204
205 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
206 {
207   static ViewerTest_MapOfAISManipulators aMap;
208   return aMap;
209 }
210
211 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
212 {
213   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
214   for (; anIt.More(); anIt.Next())
215   {
216     if (anIt.Value()->HasActiveMode())
217     {
218       return anIt.Value();
219     }
220   }
221   return NULL;
222 }
223
224 //==============================================================================
225
226 #ifdef _WIN32
227 static LRESULT WINAPI ViewerWindowProc(
228                                        HWND hwnd,
229                                        UINT uMsg,
230                                        WPARAM wParam,
231                                        LPARAM lParam );
232 static LRESULT WINAPI AdvViewerWindowProc(
233   HWND hwnd,
234   UINT uMsg,
235   WPARAM wParam,
236   LPARAM lParam );
237 #endif
238
239
240 //==============================================================================
241 //function : WClass
242 //purpose  :
243 //==============================================================================
244
245 const Handle(MMgt_TShared)& ViewerTest::WClass()
246 {
247   static Handle(MMgt_TShared) theWClass;
248 #if defined(_WIN32)
249   if (theWClass.IsNull())
250   {
251     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
252       CS_VREDRAW | CS_HREDRAW, 0, 0,
253       ::LoadCursor (NULL, IDC_ARROW));
254   }
255 #endif
256   return theWClass;
257 }
258
259 //==============================================================================
260 //function : CreateName
261 //purpose  : Create numerical name for new object in theMap
262 //==============================================================================
263 template <typename ObjectType>
264 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
265                                     const TCollection_AsciiString& theDefaultString)
266 {
267   if (theObjectMap.IsEmpty())
268     return theDefaultString + TCollection_AsciiString(1);
269
270   Standard_Integer aNextKey = 1;
271   Standard_Boolean isFound = Standard_False;
272   while (!isFound)
273   {
274     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
275     // Look for objects with default names
276     if (theObjectMap.IsBound1(aStringKey))
277     {
278       aNextKey++;
279     }
280     else
281       isFound = Standard_True;
282   }
283
284   return theDefaultString + TCollection_AsciiString(aNextKey);
285 }
286
287 //==============================================================================
288 //structure : ViewerTest_Names
289 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
290 //==============================================================================
291 struct ViewerTest_Names
292 {
293 private:
294   TCollection_AsciiString myDriverName;
295   TCollection_AsciiString myViewerName;
296   TCollection_AsciiString myViewName;
297
298 public:
299
300   const TCollection_AsciiString& GetDriverName () const
301   {
302     return myDriverName;
303   }
304   void SetDriverName (const TCollection_AsciiString& theDriverName)
305   {
306     myDriverName = theDriverName;
307   }
308   const TCollection_AsciiString& GetViewerName () const
309   {
310     return myViewerName;
311   }
312   void SetViewerName (const TCollection_AsciiString& theViewerName)
313   {
314     myViewerName = theViewerName;
315   }
316   const TCollection_AsciiString& GetViewName () const
317   {
318     return myViewName;
319   }
320   void SetViewName (const TCollection_AsciiString& theViewName)
321   {
322     myViewName = theViewName;
323   }
324
325   //===========================================================================
326   //function : Constructor for ViewerTest_Names
327   //purpose  : Get view, viewer, driver names from custom string
328   //===========================================================================
329
330   ViewerTest_Names (const TCollection_AsciiString& theInputString)
331   {
332     TCollection_AsciiString aName(theInputString);
333     if (theInputString.IsEmpty())
334     {
335       // Get current configuration
336       if (ViewerTest_myDrivers.IsEmpty())
337         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
338           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
339       else
340         myDriverName = ViewerTest_myDrivers.Find2
341         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
342
343       if(ViewerTest_myContexts.IsEmpty())
344       {
345         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
346           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
347       }
348       else
349         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
350
351         myViewName = CreateName <Handle(V3d_View)>
352           (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
353     }
354     else
355     {
356       // There is at least view name
357       Standard_Integer aParserNumber = 0;
358       for (Standard_Integer i = 0; i < 3; ++i)
359       {
360         Standard_Integer aParserPos = aName.SearchFromEnd("/");
361         if(aParserPos != -1)
362         {
363           aParserNumber++;
364           aName.Split(aParserPos-1);
365         }
366         else
367           break;
368       }
369       if (aParserNumber == 0)
370       {
371         // Only view name
372         if (!ViewerTest::GetAISContext().IsNull())
373         {
374           myDriverName = ViewerTest_myDrivers.Find2
375           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
376           myViewerName = ViewerTest_myContexts.Find2
377           (ViewerTest::GetAISContext());
378         }
379         else
380         {
381           // There is no opened contexts here, need to create names for viewer and driver
382           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
383             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
384
385           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
386             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
387         }
388         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
389       }
390       else if (aParserNumber == 1)
391       {
392         // Here is viewerName/viewName
393         if (!ViewerTest::GetAISContext().IsNull())
394           myDriverName = ViewerTest_myDrivers.Find2
395           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
396         else
397         {
398           // There is no opened contexts here, need to create name for driver
399           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
400             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
401         }
402         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
403
404         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
405       }
406       else
407       {
408         //Here is driverName/viewerName/viewName
409         myDriverName = TCollection_AsciiString(aName);
410
411         TCollection_AsciiString aViewerName(theInputString);
412         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
413         myViewerName = TCollection_AsciiString(aViewerName);
414
415         myViewName = TCollection_AsciiString(theInputString);
416       }
417     }
418   }
419 };
420
421 //==============================================================================
422 //function : FindContextByView
423 //purpose  : Find AIS_InteractiveContext by View
424 //==============================================================================
425
426 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
427 {
428   Handle(AIS_InteractiveContext) anAISContext;
429
430   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
431        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
432   {
433     if (anIter.Value()->CurrentViewer() == theView->Viewer())
434        return anIter.Key2();
435   }
436   return anAISContext;
437 }
438
439
440 //==============================================================================
441 //function : SetWindowTitle
442 //purpose  : Set window title
443 //==============================================================================
444
445 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
446                      Standard_CString theTitle)
447 {
448 #if defined(_WIN32)
449   SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
450     theTitle);
451 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
452   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
453 #else
454   if(GetDisplayConnection()->GetDisplay())
455   {
456     Window aWindow =
457       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
458     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
459   }
460 #endif
461 }
462
463 //==============================================================================
464 //function : IsWindowOverlapped
465 //purpose  : Check if theWindow overlapp another view
466 //==============================================================================
467
468 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
469                                      const Standard_Integer thePxTop,
470                                      const Standard_Integer thePxRight,
471                                      const Standard_Integer thePxBottom,
472                                      TCollection_AsciiString& theViewId)
473 {
474   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
475       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
476   {
477     Standard_Integer aTop = 0,
478       aLeft = 0,
479       aRight = 0,
480       aBottom = 0;
481     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
482     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
483         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
484         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
485         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
486     {
487       theViewId = anIter.Key1();
488       return Standard_True;
489     }
490   }
491   return Standard_False;
492 }
493
494 // Workaround: to create and delete non-orthographic views outside ViewerTest
495 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
496 {
497   ViewerTest_myViews.UnBind1 (theName);
498 }
499
500 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
501                                const Handle(V3d_View)& theView)
502 {
503   ViewerTest_myViews.Bind (theName, theView);
504 }
505
506 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
507 {
508   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
509 }
510 //==============================================================================
511 //function : ViewerInit
512 //purpose  : Create the window viewer and initialize all the global variable
513 //==============================================================================
514
515 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
516                                                 const Standard_Integer thePxTop,
517                                                 const Standard_Integer thePxWidth,
518                                                 const Standard_Integer thePxHeight,
519                                                 Standard_CString theViewName,
520                                                 Standard_CString theDisplayName)
521 {
522   // Default position and dimension of the viewer window.
523   // Note that left top corner is set to be sufficiently small to have
524   // window fit in the small screens (actual for remote desktops, see #23003).
525   // The position corresponds to the window's client area, thus some
526   // gap is added for window frame to be visible.
527   Standard_Integer aPxLeft   = 20;
528   Standard_Integer aPxTop    = 40;
529   Standard_Integer aPxWidth  = 409;
530   Standard_Integer aPxHeight = 409;
531   Standard_Boolean toCreateViewer = Standard_False;
532
533   Handle(OpenGl_GraphicDriver) aGraphicDriver;
534   ViewerTest_Names aViewNames(theViewName);
535   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
536     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
537
538   if (thePxLeft != 0)
539     aPxLeft = thePxLeft;
540   if (thePxTop != 0)
541     aPxTop = thePxTop;
542   if (thePxWidth != 0)
543     aPxWidth = thePxWidth;
544   if (thePxHeight != 0)
545     aPxHeight = thePxHeight;
546
547   // Get graphic driver (create it or get from another view)
548   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
549   {
550     // Get connection string
551   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
552     TCollection_AsciiString aDisplayName(theDisplayName);
553     if (!aDisplayName.IsEmpty())
554       SetDisplayConnection (new Aspect_DisplayConnection ());
555     else
556       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
557   #else
558     (void)theDisplayName; // avoid warning on unused argument
559     SetDisplayConnection (new Aspect_DisplayConnection ());
560   #endif
561     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
562     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
563     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
564     toCreateViewer = Standard_True;
565   }
566   else
567   {
568     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
569   }
570
571   //Dispose the window if input parameters are default
572   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
573   {
574     Standard_Integer aTop = 0,
575                      aLeft = 0,
576                      aRight = 0,
577                      aBottom = 0,
578                      aScreenWidth = 0,
579                      aScreenHeight = 0;
580
581     // Get screen resolution
582 #if defined(_WIN32) || defined(__WIN32__)
583     RECT aWindowSize;
584     GetClientRect(GetDesktopWindow(), &aWindowSize);
585     aScreenHeight = aWindowSize.bottom;
586     aScreenWidth = aWindowSize.right;
587 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
588     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
589 #else
590     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
591     aScreenWidth = WidthOfScreen(aScreen);
592     aScreenHeight = HeightOfScreen(aScreen);
593 #endif
594
595     TCollection_AsciiString anOverlappedViewId("");
596
597     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
598     {
599       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
600
601       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
602         && aRight + 2*aPxWidth + 40 > aScreenWidth)
603       {
604         if (aBottom + aPxHeight + 40 > aScreenHeight)
605         {
606           aPxLeft = 20;
607           aPxTop = 40;
608           break;
609         }
610         aPxLeft = 20;
611         aPxTop = aBottom + 40;
612       }
613       else
614         aPxLeft = aRight + 20;
615     }
616   }
617
618   // Get viewer name
619   TCollection_AsciiString aTitle("3D View - ");
620   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
621
622   // Change name of current active window
623   if (!ViewerTest::CurrentView().IsNull())
624   {
625     TCollection_AsciiString anActiveWindowTitle("3D View - ");
626     anActiveWindowTitle = anActiveWindowTitle
627       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
628     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
629   }
630
631   // Create viewer
632   Handle(V3d_Viewer) a3DViewer;
633   // If it's the single view, we first look for empty context
634   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
635   {
636     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
637       anIter(ViewerTest_myContexts);
638     if (anIter.More())
639       ViewerTest::SetAISContext (anIter.Value());
640     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
641   }
642   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
643   {
644     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
645     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
646   }
647   else if (a3DViewer.IsNull())
648   {
649     toCreateViewer = Standard_True;
650     TCollection_ExtendedString NameOfWindow("Viewer3D");
651     a3DViewer = new V3d_Viewer(aGraphicDriver, NameOfWindow.ToExtString());
652     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
653     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
654                                            ViewerTest_DefaultBackground.GradientColor2,
655                                            ViewerTest_DefaultBackground.FillMethod);
656   }
657
658   // AIS context setup
659   if (ViewerTest::GetAISContext().IsNull() ||
660       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
661   {
662     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
663     ViewerTest::SetAISContext (aContext);
664     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
665   }
666   else
667   {
668     ViewerTest::ResetEventManager();
669   }
670
671   // Create window
672 #if defined(_WIN32)
673   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
674                                     Handle(WNT_WClass)::DownCast (WClass()),
675                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
676                                     aPxLeft, aPxTop,
677                                     aPxWidth, aPxHeight,
678                                     Quantity_NOC_BLACK);
679 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
680   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
681                                      aPxLeft, aPxTop,
682                                      aPxWidth, aPxHeight);
683   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
684 #else
685   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
686                                   aTitle.ToCString(),
687                                   aPxLeft, aPxTop,
688                                   aPxWidth, aPxHeight);
689 #endif
690   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
691
692   // View setup
693   Handle(V3d_View) aView = a3DViewer->CreateView();
694   aView->SetWindow (VT_GetWindow());
695   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
696
697   ViewerTest::CurrentView(aView);
698   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
699
700   // Setup for X11 or NT
701   OSWindowSetup();
702
703   // Set parameters for V3d_View and V3d_Viewer
704   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
705   aV3dView->SetComputedMode(Standard_False);
706   MyHLRIsOn = aV3dView->ComputedMode();
707
708   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
709   if (toCreateViewer)
710   {
711     a3DViewer->SetDefaultLights();
712     a3DViewer->SetLightOn();
713   }
714
715   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
716   #if TCL_MAJOR_VERSION  < 8
717   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
718       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
719   #else
720   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
721       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
722   #endif
723   #endif
724
725   VT_GetWindow()->Map();
726
727   // Set the handle of created view in the event manager
728   ViewerTest::ResetEventManager();
729
730   ViewerTest::CurrentView()->Redraw();
731
732   aView.Nullify();
733   a3DViewer.Nullify();
734
735   return aViewNames.GetViewName();
736 }
737
738 //==============================================================================
739 //function : RedrawAllViews
740 //purpose  : Redraw all created views
741 //==============================================================================
742 void ViewerTest::RedrawAllViews()
743 {
744   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
745   for (; aViewIt.More(); aViewIt.Next())
746   {
747     const Handle(V3d_View)& aView = aViewIt.Key2();
748     aView->Redraw();
749   }
750 }
751
752 //==============================================================================
753 //function : Vinit
754 //purpose  : Create the window viewer and initialize all the global variable
755 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
756 //==============================================================================
757
758 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
759 {
760   if (theArgsNb > 9)
761   {
762     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
763               << "Type help for more information.\n";
764     return 1;
765   }
766
767   TCollection_AsciiString aViewName, aDisplayName;
768   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
769   TCollection_AsciiString aName, aValue;
770   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
771   {
772     const TCollection_AsciiString anArg = theArgVec[anArgIt];
773     TCollection_AsciiString anArgCase = anArg;
774     anArgCase.UpperCase();
775     if (ViewerTest::SplitParameter (anArg, aName, aValue))
776     {
777       aName.UpperCase();
778       if (aName.IsEqual ("NAME"))
779       {
780         aViewName = aValue;
781       }
782       else if (aName.IsEqual ("L")
783             || aName.IsEqual ("LEFT"))
784       {
785         aPxLeft = aValue.IntegerValue();
786       }
787       else if (aName.IsEqual ("T")
788             || aName.IsEqual ("TOP"))
789       {
790         aPxTop = aValue.IntegerValue();
791       }
792     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
793       else if (aName.IsEqual ("DISP")
794             || aName.IsEqual ("DISPLAY"))
795       {
796         aDisplayName = aValue;
797       }
798     #endif
799       else if (aName.IsEqual ("W")
800             || aName.IsEqual ("WIDTH"))
801       {
802         aPxWidth = aValue.IntegerValue();
803       }
804       else if (aName.IsEqual ("H")
805             || aName.IsEqual ("HEIGHT"))
806       {
807         aPxHeight = aValue.IntegerValue();
808       }
809       else
810       {
811         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
812       }
813     }
814     else if (aViewName.IsEmpty())
815     {
816       aViewName = anArg;
817     }
818     else
819     {
820       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
821     }
822   }
823
824   ViewerTest_Names aViewNames (aViewName);
825   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
826   {
827     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
828     theDi.Eval (aCommand.ToCString());
829     return 0;
830   }
831
832   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
833                                                             aViewName.ToCString(),
834                                                             aDisplayName.ToCString());
835   theDi << aViewId;
836   return 0;
837 }
838
839 //==============================================================================
840 //function : VHLR
841 //purpose  : hidden lines removal algorithm
842 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
843 //==============================================================================
844
845 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
846 {
847   if (ViewerTest::CurrentView().IsNull())
848   {
849     di << argv[0] << ": Call vinit before this command, please.\n";
850     return 1;
851   }
852
853   if (argc < 2)
854   {
855     di << argv[0] << ": Wrong number of command arguments.\n"
856       << "Type help " << argv[0] << " for more information.\n";
857     return 1;
858   }
859
860   // Enable or disable HLR mode.
861   Standard_Boolean isHLROn =
862     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
863
864   if (isHLROn != MyHLRIsOn)
865   {
866     MyHLRIsOn = isHLROn;
867     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
868   }
869
870   // Show or hide hidden lines in HLR mode.
871   Standard_Boolean isCurrentShowHidden
872     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
873
874   Standard_Boolean isShowHidden =
875     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
876                 : isCurrentShowHidden;
877
878
879   if (isShowHidden != isCurrentShowHidden)
880   {
881     if (isShowHidden)
882     {
883       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
884     }
885     else
886     {
887       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
888     }
889
890     // Redisplay shapes.
891     if (MyHLRIsOn)
892     {
893       AIS_ListOfInteractive aListOfShapes;
894       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
895
896       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
897       {
898         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
899         if (aShape.IsNull())
900         {
901           continue;
902         }
903         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
904       }
905     }
906   }
907
908   ViewerTest::CurrentView()->Update();
909   return 0;
910 }
911
912 //==============================================================================
913 //function : VHLRType
914 //purpose  : change type of using HLR algorithm
915 //==============================================================================
916
917 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
918 {
919   if (ViewerTest::CurrentView().IsNull())
920   {
921     di << argv[0] << ": Call vinit before this command, please.\n";
922     return 1;
923   }
924
925   if (argc < 2)
926   {
927     di << argv[0] << ": Wrong number of command arguments.\n"
928       << "Type help " << argv[0] << " for more information.\n";
929     return 1;
930   }
931
932   Prs3d_TypeOfHLR aTypeOfHLR =
933     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
934
935   if (argc == 2)
936   {
937     AIS_ListOfInteractive aListOfShapes;
938     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
939     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
940     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
941       anIter.More(); anIter.Next())
942     {
943       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
944       if (aShape.IsNull())
945         continue;
946       if (aShape->TypeOfHLR() != aTypeOfHLR)
947         aShape->SetTypeOfHLR (aTypeOfHLR);
948       if (MyHLRIsOn)
949         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
950     }
951     ViewerTest::CurrentView()->Update();
952     return 0;
953   }
954   else
955   {
956     for (Standard_Integer i = 2; i < argc; ++i)
957     {
958       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
959       TCollection_AsciiString aName (argv[i]);
960
961       if (!aMap.IsBound2 (aName))
962       {
963         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
964         continue;
965       }
966       Handle(AIS_Shape) anAISObject =
967         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
968       if (anAISObject.IsNull())
969         continue;
970       anAISObject->SetTypeOfHLR (aTypeOfHLR);
971       if (MyHLRIsOn)
972         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
973     }
974     ViewerTest::CurrentView()->Update();
975   }
976
977   return 0;
978 }
979
980 //==============================================================================
981 //function : FindViewIdByWindowHandle
982 //purpose  : Find theView Id in the map of views by window handle
983 //==============================================================================
984 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
985 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
986 {
987   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
988        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
989   {
990     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
991     if (aWindowHandle == theWindowHandle)
992       return anIter.Key1();
993   }
994   return TCollection_AsciiString("");
995 }
996 #endif
997
998 //==============================================================================
999 //function : ActivateView
1000 //purpose  : Make the view active
1001 //==============================================================================
1002
1003 void ActivateView (const TCollection_AsciiString& theViewName)
1004 {
1005   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1006   if (!aView.IsNull())
1007   {
1008     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1009     if (!anAISContext.IsNull())
1010     {
1011       if (!ViewerTest::CurrentView().IsNull())
1012       {
1013         TCollection_AsciiString aTitle("3D View - ");
1014         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1015         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1016       }
1017
1018       ViewerTest::CurrentView (aView);
1019       // Update degenerate mode
1020       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1021       ViewerTest::SetAISContext (anAISContext);
1022       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1023       aTitle = aTitle + theViewName + "(*)";
1024       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1025 #if defined(_WIN32) || defined(__WIN32__)
1026       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1027 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1028       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1029 #else
1030       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1031 #endif
1032       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1033       ViewerTest::CurrentView()->Redraw();
1034     }
1035   }
1036 }
1037
1038 //==============================================================================
1039 //function : RemoveView
1040 //purpose  :
1041 //==============================================================================
1042 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1043                              const Standard_Boolean  theToRemoveContext)
1044 {
1045   if (!ViewerTest_myViews.IsBound2 (theView))
1046   {
1047     return;
1048   }
1049
1050   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1051   RemoveView (aViewName, theToRemoveContext);
1052 }
1053
1054 //==============================================================================
1055 //function : RemoveView
1056 //purpose  : Close and remove view from display, clear maps if neccessary
1057 //==============================================================================
1058 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1059 {
1060   if (!ViewerTest_myViews.IsBound1(theViewName))
1061   {
1062     cout << "Wrong view name\n";
1063     return;
1064   }
1065
1066   // Activate another view if it's active now
1067   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1068   {
1069     if (ViewerTest_myViews.Extent() > 1)
1070     {
1071       TCollection_AsciiString aNewViewName;
1072       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
1073            anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1074         if (anIter.Key1() != theViewName)
1075         {
1076           aNewViewName = anIter.Key1();
1077           break;
1078         }
1079         ActivateView (aNewViewName);
1080     }
1081     else
1082     {
1083       Handle(V3d_View) anEmptyView;
1084 #if defined(_WIN32) || defined(__WIN32__)
1085       Handle(WNT_Window) anEmptyWindow;
1086 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1087       Handle(Cocoa_Window) anEmptyWindow;
1088 #else
1089       Handle(Xw_Window) anEmptyWindow;
1090 #endif
1091       VT_GetWindow() = anEmptyWindow;
1092       ViewerTest::CurrentView (anEmptyView);
1093       if (isContextRemoved)
1094       {
1095         Handle(AIS_InteractiveContext) anEmptyContext;
1096         ViewerTest::SetAISContext(anEmptyContext);
1097       }
1098     }
1099   }
1100
1101   // Delete view
1102   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1103   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1104
1105   // Remove view resources
1106   ViewerTest_myViews.UnBind1(theViewName);
1107   aView->Remove();
1108
1109 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1110   XFlush (GetDisplayConnection()->GetDisplay());
1111 #endif
1112
1113   // Keep context opened only if the closed view is last to avoid
1114   // unused empty contexts
1115   if (!aCurrentContext.IsNull())
1116   {
1117     // Check if there are more difined views in the viewer
1118     aCurrentContext->CurrentViewer()->InitDefinedViews();
1119     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1120     {
1121       // Remove driver if there is no viewers that use it
1122       Standard_Boolean isRemoveDriver = Standard_True;
1123       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1124           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1125       {
1126         if (aCurrentContext != anIter.Key2() &&
1127           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1128         {
1129           isRemoveDriver = Standard_False;
1130           break;
1131         }
1132       }
1133       if(isRemoveDriver)
1134       {
1135         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1136       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1137         #if TCL_MAJOR_VERSION  < 8
1138         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1139         #else
1140         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1141         #endif
1142       #endif
1143       }
1144
1145       ViewerTest_myContexts.UnBind2(aCurrentContext);
1146     }
1147   }
1148   cout << "3D View - " << theViewName << " was deleted.\n";
1149
1150 }
1151
1152 //==============================================================================
1153 //function : VClose
1154 //purpose  : Remove the view defined by its name
1155 //==============================================================================
1156
1157 static int VClose (Draw_Interpretor& /*theDi*/,
1158                    Standard_Integer  theArgsNb,
1159                    const char**      theArgVec)
1160 {
1161   NCollection_List<TCollection_AsciiString> aViewList;
1162   if (theArgsNb > 1)
1163   {
1164     TCollection_AsciiString anArg (theArgVec[1]);
1165     anArg.UpperCase();
1166     if (anArg.IsEqual ("ALL")
1167      || anArg.IsEqual ("*"))
1168     {
1169       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1170            anIter.More(); anIter.Next())
1171       {
1172         aViewList.Append (anIter.Key1());
1173       }
1174       if (aViewList.IsEmpty())
1175       {
1176         std::cout << "No view to close\n";
1177         return 0;
1178       }
1179     }
1180     else
1181     {
1182       ViewerTest_Names aViewName (theArgVec[1]);
1183       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1184       {
1185         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1186         return 1;
1187       }
1188       aViewList.Append (aViewName.GetViewName());
1189     }
1190   }
1191   else
1192   {
1193     // close active view
1194     if (ViewerTest::CurrentView().IsNull())
1195     {
1196       std::cerr << "No active view!\n";
1197       return 1;
1198     }
1199     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1200   }
1201
1202   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1203   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1204        anIter.More(); anIter.Next())
1205   {
1206     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1207   }
1208
1209   return 0;
1210 }
1211
1212 //==============================================================================
1213 //function : VActivate
1214 //purpose  : Activate the view defined by its ID
1215 //==============================================================================
1216
1217 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1218 {
1219   if (theArgsNb > 2)
1220   {
1221     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1222     << "Usage: " << theArgVec[0] << " ViewID\n";
1223     return 1;
1224   }
1225   if(theArgsNb == 1)
1226   {
1227     theDi.Eval("vviewlist");
1228     return 0;
1229   }
1230
1231   TCollection_AsciiString aNameString(theArgVec[1]);
1232   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1233   {
1234     TCollection_AsciiString aTitle("3D View - ");
1235     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1236     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1237     Handle(V3d_View) anEmptyView;
1238 #if defined(_WIN32) || defined(__WIN32__)
1239     Handle(WNT_Window) anEmptyWindow;
1240 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1241     Handle(Cocoa_Window) anEmptyWindow;
1242 #else
1243     Handle(Xw_Window) anEmptyWindow;
1244 #endif
1245     VT_GetWindow() = anEmptyWindow;
1246     ViewerTest::CurrentView (anEmptyView);
1247     ViewerTest::ResetEventManager();
1248     theDi << theArgVec[0] << ": all views are inactive\n";
1249     return 0;
1250   }
1251
1252   ViewerTest_Names aViewNames(aNameString);
1253
1254   // Check if this view exists in the viewer with the driver
1255   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1256   {
1257     theDi << "Wrong view name\n";
1258     return 1;
1259   }
1260
1261   // Check if it is active already
1262   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1263   {
1264     theDi << theArgVec[0] << ": the view is active already\n";
1265     return 0;
1266   }
1267
1268   ActivateView (aViewNames.GetViewName());
1269   return 0;
1270 }
1271
1272 //==============================================================================
1273 //function : VViewList
1274 //purpose  : Print current list of views per viewer and graphic driver ID
1275 //           shared between viewers
1276 //==============================================================================
1277
1278 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1279 {
1280   if (theArgsNb > 2)
1281   {
1282     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1283           << "Usage: " << theArgVec[0] << " name";
1284     return 1;
1285   }
1286   if (ViewerTest_myContexts.Size() < 1)
1287     return 0;
1288
1289   Standard_Boolean isTreeView =
1290     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1291
1292   if (isTreeView)
1293     theDi << theArgVec[0] <<":\n";
1294
1295     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
1296       aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
1297     {
1298       if (isTreeView)
1299         theDi << aDriverIter.Key1() << ":\n";
1300
1301       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1302         aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1303       {
1304         if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1305         {
1306           if (isTreeView)
1307           {
1308             TCollection_AsciiString aContextName(aContextIter.Key1());
1309             theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1310           }
1311
1312           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1313             aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
1314           {
1315             if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1316             {
1317               TCollection_AsciiString aViewName(aViewIter.Key1());
1318               if (isTreeView)
1319               {
1320                 if (aViewIter.Value() == ViewerTest::CurrentView())
1321                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1322                 else
1323                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1324               }
1325               else
1326               {
1327                 theDi << aViewName << " ";
1328               }
1329             }
1330           }
1331         }
1332       }
1333     }
1334   return 0;
1335 }
1336
1337 //==============================================================================
1338 //function : VT_ProcessKeyPress
1339 //purpose  : Handle KeyPress event from a CString
1340 //==============================================================================
1341 void VT_ProcessKeyPress (const char* buf_ret)
1342 {
1343   //cout << "KeyPress" << endl;
1344   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1345   // Letter in alphabetic order
1346
1347   if (!strcasecmp (buf_ret, "A"))
1348   {
1349     // AXO
1350     aView->SetProj(V3d_XposYnegZpos);
1351   }
1352   else if (!strcasecmp (buf_ret, "D"))
1353   {
1354     // Reset
1355     aView->Reset();
1356   }
1357   else if (!strcasecmp (buf_ret, "F"))
1358   {
1359     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1360     {
1361       ViewerTest::GetAISContext()->FitSelected (aView);
1362     }
1363     else
1364     {
1365       // FitAll
1366       aView->FitAll();
1367     }
1368   }
1369   else if (!strcasecmp (buf_ret, "H"))
1370   {
1371     // HLR
1372     cout << "HLR" << endl;
1373     aView->SetComputedMode (!aView->ComputedMode());
1374     MyHLRIsOn = aView->ComputedMode();
1375   }
1376   else if (!strcasecmp (buf_ret, "P"))
1377   {
1378     // Type of HLR
1379     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1380     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1381       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1382     else
1383       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1384     if (aContext->NbSelected()==0)
1385     {
1386       AIS_ListOfInteractive aListOfShapes;
1387       aContext->DisplayedObjects(aListOfShapes);
1388       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1389         anIter.More(); anIter.Next())
1390       {
1391         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1392         if (aShape.IsNull())
1393           continue;
1394         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1395           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1396         else
1397           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1398         aContext->Redisplay (aShape, Standard_False);
1399       }
1400     }
1401     else
1402     {
1403       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1404       {
1405         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1406         if (aShape.IsNull())
1407           continue;
1408         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1409           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1410         else
1411           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1412         aContext->Redisplay (aShape, Standard_False);
1413       }
1414     }
1415
1416     aContext->UpdateCurrentViewer();
1417
1418   }
1419   else if (!strcasecmp (buf_ret, "S"))
1420   {
1421     std::cout << "setup Shaded display mode" << std::endl;
1422
1423     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1424     if(Ctx->NbSelected()==0)
1425       Ctx->SetDisplayMode(AIS_Shaded);
1426     else{
1427       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1428         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1429       Ctx->UpdateCurrentViewer();
1430     }
1431   }
1432   else if (!strcasecmp (buf_ret, "U"))
1433   {
1434     // Unset display mode
1435     std::cout << "reset display mode to defaults" << std::endl;
1436
1437     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1438     if(Ctx->NbSelected()==0)
1439       Ctx->SetDisplayMode(AIS_WireFrame);
1440     else{
1441       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1442         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1443       Ctx->UpdateCurrentViewer();
1444     }
1445
1446   }
1447   else if (!strcasecmp (buf_ret, "T"))
1448   {
1449     // Top
1450     aView->SetProj(V3d_Zpos);
1451   }
1452   else if (!strcasecmp (buf_ret, "B"))
1453   {
1454     // Bottom
1455     aView->SetProj(V3d_Zneg);
1456   }
1457   else if (!strcasecmp (buf_ret, "L"))
1458   {
1459     // Left
1460     aView->SetProj(V3d_Xneg);
1461   }
1462   else if (!strcasecmp (buf_ret, "R"))
1463   {
1464     // Right
1465     aView->SetProj(V3d_Xpos);
1466   }
1467   else if (!strcasecmp (buf_ret, "W"))
1468   {
1469     std::cout << "setup WireFrame display mode" << std::endl;
1470     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1471     if(Ctx->NbSelected()==0)
1472       Ctx->SetDisplayMode(AIS_WireFrame);
1473     else{
1474       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1475         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1476       Ctx->UpdateCurrentViewer();
1477     }
1478   }
1479   else if (!strcasecmp (buf_ret, ","))
1480   {
1481     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1482   }
1483   else if (!strcasecmp (buf_ret, "."))
1484   {
1485     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1486   }
1487   else if (!strcasecmp (buf_ret, "/"))
1488   {
1489     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1490     if (aCamera->IsStereo())
1491     {
1492       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1493       aView->Redraw();
1494     }
1495   }
1496   else if (!strcasecmp (buf_ret, "*"))
1497   {
1498     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1499     if (aCamera->IsStereo())
1500     {
1501       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1502       aView->Redraw();
1503     }
1504   }
1505   else if (*buf_ret == THE_KEY_DELETE)
1506   {
1507     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1508     if (!aCtx.IsNull()
1509      && aCtx->NbSelected() > 0)
1510     {
1511       Draw_Interprete ("verase");
1512     }
1513   }
1514   else
1515   {
1516     // Number
1517     Standard_Integer Num = Draw::Atoi(buf_ret);
1518     if(Num>=0 && Num<=7)
1519       ViewerTest::StandardModeActivation(Num);
1520   }
1521 }
1522
1523 //==============================================================================
1524 //function : VT_ProcessExpose
1525 //purpose  : Redraw the View on an Expose Event
1526 //==============================================================================
1527 void VT_ProcessExpose()
1528 {
1529   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1530   if (!aView3d.IsNull())
1531   {
1532     aView3d->Redraw();
1533   }
1534 }
1535
1536 //==============================================================================
1537 //function : VT_ProcessConfigure
1538 //purpose  : Resize the View on an Configure Event
1539 //==============================================================================
1540 void VT_ProcessConfigure()
1541 {
1542   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1543   if (aView3d.IsNull())
1544   {
1545     return;
1546   }
1547
1548   aView3d->MustBeResized();
1549   aView3d->Update();
1550   aView3d->Redraw();
1551 }
1552
1553 //==============================================================================
1554 //function : VT_ProcessButton1Press
1555 //purpose  : Picking
1556 //==============================================================================
1557 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1558                                          const char**     theArgVec,
1559                                          Standard_Boolean theToPick,
1560                                          Standard_Boolean theIsShift)
1561 {
1562   if (theToPick)
1563   {
1564     Standard_Real X, Y, Z;
1565     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1566
1567     Draw::Set (theArgVec[1], X);
1568     Draw::Set (theArgVec[2], Y);
1569     Draw::Set (theArgVec[3], Z);
1570   }
1571
1572   if (theIsShift)
1573   {
1574     ViewerTest::CurrentEventManager()->ShiftSelect();
1575   }
1576   else
1577   {
1578     ViewerTest::CurrentEventManager()->Select();
1579   }
1580
1581   return Standard_False;
1582 }
1583
1584 //==============================================================================
1585 //function : VT_ProcessButton1Release
1586 //purpose  : End selecting
1587 //==============================================================================
1588 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1589 {
1590   if (IsDragged)
1591   {
1592     IsDragged = Standard_False;
1593     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1594     if (theIsShift)
1595     {
1596       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1597                        X_Motion, Y_Motion);
1598     }
1599     else
1600     {
1601       EM->Select (X_ButtonPress, Y_ButtonPress,
1602                   X_Motion, Y_Motion);
1603     }
1604   }
1605 }
1606
1607 //==============================================================================
1608 //function : VT_ProcessButton3Press
1609 //purpose  : Start Rotation
1610 //==============================================================================
1611 void VT_ProcessButton3Press()
1612 {
1613   Start_Rot = 1;
1614   if (MyHLRIsOn)
1615   {
1616     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1617   }
1618   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1619 }
1620
1621 //==============================================================================
1622 //function : VT_ProcessButton3Release
1623 //purpose  : End rotation
1624 //==============================================================================
1625 void VT_ProcessButton3Release()
1626 {
1627   if (Start_Rot)
1628   {
1629     Start_Rot = 0;
1630     if (MyHLRIsOn)
1631     {
1632       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1633     }
1634   }
1635 }
1636
1637 //==============================================================================
1638 //function : ProcessControlButton1Motion
1639 //purpose  : Zoom
1640 //==============================================================================
1641
1642 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1643 static void ProcessControlButton1Motion()
1644 {
1645   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1646
1647   X_ButtonPress = X_Motion;
1648   Y_ButtonPress = Y_Motion;
1649 }
1650 #endif
1651
1652 //==============================================================================
1653 //function : VT_ProcessControlButton2Motion
1654 //purpose  : Panning
1655 //==============================================================================
1656 void VT_ProcessControlButton2Motion()
1657 {
1658   Standard_Integer aDx = X_Motion - X_ButtonPress;
1659   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1660
1661   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1662
1663   ViewerTest::CurrentView()->Pan (aDx, aDy);
1664
1665   X_ButtonPress = X_Motion;
1666   Y_ButtonPress = Y_Motion;
1667 }
1668
1669 //==============================================================================
1670 //function : VT_ProcessControlButton3Motion
1671 //purpose  : Rotation
1672 //==============================================================================
1673 void VT_ProcessControlButton3Motion()
1674 {
1675   if (Start_Rot)
1676   {
1677     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1678   }
1679 }
1680
1681 //==============================================================================
1682 //function : VT_ProcessMotion
1683 //purpose  :
1684 //==============================================================================
1685 void VT_ProcessMotion()
1686 {
1687   //pre-hilights detected objects at mouse position
1688
1689   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1690   EM->MoveTo(X_Motion, Y_Motion);
1691 }
1692
1693
1694 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1695 {
1696   Xpix = X_Motion;Ypix=Y_Motion;
1697 }
1698
1699 //==============================================================================
1700 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1701 //purpose  : Switches to an axonometric, top, left and other views
1702 //==============================================================================
1703
1704 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1705 {
1706   if ( ViewerTest::CurrentView().IsNull() )
1707   {
1708     di<<"Call vinit before this command, please\n";
1709     return 1;
1710   }
1711
1712   ViewerTest::CurrentView()->SetProj(ori);
1713   return 0;
1714 }
1715
1716 //==============================================================================
1717 //function : VAxo
1718 //purpose  : Switch to an Axonometric view
1719 //Draw arg : No args
1720 //==============================================================================
1721
1722 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1723 {
1724   return ViewProject(di, V3d_XposYnegZpos);
1725 }
1726
1727 //==============================================================================
1728 //function : VTop
1729 //purpose  : Switch to a Top View
1730 //Draw arg : No args
1731 //==============================================================================
1732
1733 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1734 {
1735   return ViewProject(di, V3d_Zpos);
1736 }
1737
1738 //==============================================================================
1739 //function : VBottom
1740 //purpose  : Switch to a Bottom View
1741 //Draw arg : No args
1742 //==============================================================================
1743
1744 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1745 {
1746   return ViewProject(di, V3d_Zneg);
1747 }
1748
1749 //==============================================================================
1750 //function : VLeft
1751 //purpose  : Switch to a Left View
1752 //Draw arg : No args
1753 //==============================================================================
1754
1755 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1756 {
1757   return ViewProject(di, V3d_Xneg);
1758 }
1759
1760 //==============================================================================
1761 //function : VRight
1762 //purpose  : Switch to a Right View
1763 //Draw arg : No args
1764 //==============================================================================
1765
1766 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1767 {
1768   return ViewProject(di, V3d_Xpos);
1769 }
1770
1771 //==============================================================================
1772 //function : VFront
1773 //purpose  : Switch to a Front View
1774 //Draw arg : No args
1775 //==============================================================================
1776
1777 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1778 {
1779   return ViewProject(di, V3d_Yneg);
1780 }
1781
1782 //==============================================================================
1783 //function : VBack
1784 //purpose  : Switch to a Back View
1785 //Draw arg : No args
1786 //==============================================================================
1787
1788 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1789 {
1790   return ViewProject(di, V3d_Ypos);
1791 }
1792
1793 //==============================================================================
1794 //function : VHelp
1795 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1796 //Draw arg : No args
1797 //==============================================================================
1798
1799 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1800 {
1801
1802   di << "Q : Quit the application\n";
1803
1804   di << "=========================\n";
1805   di << "F : FitAll\n";
1806   di << "T : TopView\n";
1807   di << "B : BottomView\n";
1808   di << "R : RightView\n";
1809   di << "L : LeftView\n";
1810   di << "A : AxonometricView\n";
1811   di << "D : ResetView\n";
1812
1813   di << "=========================\n";
1814   di << "S : Shading\n";
1815   di << "W : Wireframe\n";
1816   di << "H : HidelLineRemoval\n";
1817   di << "U : Unset display mode\n";
1818   di << "Delete : Remove selection from viewer\n";
1819
1820   di << "=========================\n";
1821   di << "Selection mode \n";
1822   di << "0 : Shape\n";
1823   di << "1 : Vertex\n";
1824   di << "2 : Edge\n";
1825   di << "3 : Wire\n";
1826   di << "4 : Face\n";
1827   di << "5 : Shell\n";
1828   di << "6 : Solid\n";
1829   di << "7 : Compound\n";
1830
1831   di << "=========================\n";
1832   di << "Z : Switch Z clipping On/Off\n";
1833   di << ", : Hilight next detected\n";
1834   di << ". : Hilight previous detected\n";
1835
1836   return 0;
1837 }
1838
1839 #ifdef _WIN32
1840
1841 static Standard_Boolean Ppick = 0;
1842 static Standard_Integer Pargc = 0;
1843 static const char**           Pargv = NULL;
1844
1845
1846 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1847                                           UINT Msg,
1848                                           WPARAM wParam,
1849                                           LPARAM lParam )
1850 {
1851   if (!ViewerTest_myViews.IsEmpty()) {
1852
1853     WPARAM fwKeys = wParam;
1854
1855     switch( Msg ) {
1856     case WM_CLOSE:
1857        {
1858          // Delete view from map of views
1859          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1860          return 0;
1861        }
1862        break;
1863     case WM_ACTIVATE:
1864       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1865         || ViewerTest::CurrentView().IsNull())
1866       {
1867         // Activate inactive window
1868         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1869         {
1870           ActivateView (FindViewIdByWindowHandle(hwnd));
1871         }
1872       }
1873       break;
1874
1875     case WM_LBUTTONUP:
1876       if (IsDragged && !DragFirst)
1877       {
1878         if (!GetActiveAISManipulator().IsNull())
1879         {
1880           GetActiveAISManipulator()->StopTransform();
1881           ViewerTest::GetAISContext()->ClearSelected();
1882         }
1883
1884         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1885         {
1886           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1887           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1888         }
1889
1890         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1891       }
1892       IsDragged = Standard_False;
1893       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1894
1895     case WM_RBUTTONUP:
1896       if (IsDragged && !DragFirst)
1897       {
1898         if (!GetActiveAISManipulator().IsNull())
1899         {
1900           GetActiveAISManipulator()->StopTransform (Standard_False);
1901           ViewerTest::GetAISContext()->ClearSelected();
1902         }
1903         IsDragged = Standard_False;
1904       }
1905       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1906
1907     case WM_LBUTTONDOWN:
1908       if (!GetActiveAISManipulator().IsNull())
1909       {
1910         IsDragged = ( fwKeys == MK_LBUTTON );
1911       }
1912       else
1913       {
1914         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1915       }
1916
1917       if (IsDragged)
1918       {
1919         DragFirst = Standard_True;
1920         X_ButtonPress = LOWORD(lParam);
1921         Y_ButtonPress = HIWORD(lParam);
1922       }
1923       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1924
1925     case WM_MOUSEMOVE:
1926       if (IsDragged)
1927       {
1928         X_Motion = LOWORD (lParam);
1929         Y_Motion = HIWORD (lParam);
1930         if (!GetActiveAISManipulator().IsNull())
1931         {
1932           if (DragFirst)
1933           {
1934             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1935           }
1936           else
1937           {
1938             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1939             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1940           }
1941         }
1942         else
1943         {
1944           bool toRedraw = false;
1945           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1946           {
1947             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1948             toRedraw = true;
1949           }
1950
1951           RECT aRect;
1952           if (GetClientRect (hwnd, &aRect))
1953           {
1954             int aHeight = aRect.bottom - aRect.top;
1955             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1956             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1957             toRedraw = true;
1958           }
1959           if (toRedraw)
1960           {
1961             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1962           }
1963         }
1964
1965         DragFirst = Standard_False;
1966       }
1967       else
1968         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1969       break;
1970
1971     default:
1972       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1973     }
1974     return 0;
1975   }
1976   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1977 }
1978
1979
1980 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
1981                                        UINT Msg,
1982                                        WPARAM wParam,
1983                                        LPARAM lParam )
1984 {
1985   static int Up = 1;
1986   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
1987   if (aView.IsNull())
1988   {
1989     return DefWindowProc( hwnd, Msg, wParam, lParam );
1990   }
1991
1992     PAINTSTRUCT    ps;
1993
1994     switch( Msg ) {
1995     case WM_PAINT:
1996       BeginPaint(hwnd, &ps);
1997       EndPaint(hwnd, &ps);
1998       VT_ProcessExpose();
1999       break;
2000
2001     case WM_SIZE:
2002       VT_ProcessConfigure();
2003       break;
2004     case WM_MOVE:
2005     case WM_MOVING:
2006     case WM_SIZING:
2007       switch (aView->RenderingParams().StereoMode)
2008       {
2009         case Graphic3d_StereoMode_RowInterlaced:
2010         case Graphic3d_StereoMode_ColumnInterlaced:
2011         case Graphic3d_StereoMode_ChessBoard:
2012           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2013           break;
2014         default:
2015           break;
2016       }
2017       break;
2018
2019     case WM_KEYDOWN:
2020       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2021       {
2022         char c[2];
2023         c[0] = (char) wParam;
2024         c[1] = '\0';
2025         if (wParam == VK_DELETE)
2026         {
2027           c[0] = THE_KEY_DELETE;
2028         }
2029         // comma
2030         else if (wParam == VK_OEM_COMMA)
2031         {
2032           c[0] = ',';
2033         }
2034         // dot
2035         else if (wParam == VK_OEM_PERIOD)
2036         {
2037           c[0] = '.';
2038         }
2039         else if (wParam == VK_DIVIDE)
2040         {
2041           c[0] = '/';
2042         }
2043         // dot
2044         else if (wParam == VK_MULTIPLY)
2045         {
2046           c[0] = '*';
2047         }
2048         VT_ProcessKeyPress (c);
2049       }
2050       break;
2051
2052     case WM_LBUTTONUP:
2053     case WM_MBUTTONUP:
2054     case WM_RBUTTONUP:
2055       Up = 1;
2056       VT_ProcessButton3Release();
2057       break;
2058
2059     case WM_LBUTTONDOWN:
2060     case WM_MBUTTONDOWN:
2061     case WM_RBUTTONDOWN:
2062       {
2063         WPARAM fwKeys = wParam;
2064
2065         Up = 0;
2066
2067         X_ButtonPress = LOWORD(lParam);
2068         Y_ButtonPress = HIWORD(lParam);
2069
2070         if (Msg == WM_LBUTTONDOWN)
2071         {
2072           if ((fwKeys & MK_CONTROL) != 0)
2073           {
2074             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2075           }
2076           else
2077           {
2078             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2079           }
2080         }
2081         else if (Msg == WM_RBUTTONDOWN)
2082         {
2083           // Start rotation
2084           VT_ProcessButton3Press();
2085         }
2086       }
2087       break;
2088
2089     case WM_MOUSEWHEEL:
2090     {
2091       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2092       if (wParam & MK_CONTROL)
2093       {
2094         if (aView->Camera()->IsStereo())
2095         {
2096           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2097           if (aFocus > 0.2
2098            && aFocus < 2.0)
2099           {
2100             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2101             aView->Redraw();
2102           }
2103         }
2104       }
2105       else
2106       {
2107         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2108       }
2109       break;
2110     }
2111
2112     case WM_MOUSEMOVE:
2113       {
2114         //cout << "\t WM_MOUSEMOVE" << endl;
2115         WPARAM fwKeys = wParam;
2116         X_Motion = LOWORD(lParam);
2117         Y_Motion = HIWORD(lParam);
2118
2119         if ( Up &&
2120           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2121           {
2122             Up = 0;
2123             X_ButtonPress = LOWORD(lParam);
2124             Y_ButtonPress = HIWORD(lParam);
2125
2126             if ((fwKeys & MK_RBUTTON) != 0) {
2127               // Start rotation
2128               VT_ProcessButton3Press();
2129             }
2130           }
2131
2132           if ((fwKeys & MK_CONTROL) != 0)
2133           {
2134             if ((fwKeys & MK_LBUTTON) != 0)
2135             {
2136               ProcessControlButton1Motion();
2137             }
2138             else if ((fwKeys & MK_MBUTTON) != 0
2139                  || ((fwKeys & MK_LBUTTON) != 0
2140                   && (fwKeys & MK_RBUTTON) != 0))
2141             {
2142               VT_ProcessControlButton2Motion();
2143             }
2144             else if ((fwKeys & MK_RBUTTON) != 0)
2145             {
2146               VT_ProcessControlButton3Motion();
2147             }
2148           }
2149           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2150           {
2151             VT_ProcessMotion();
2152           }
2153       }
2154       break;
2155
2156     default:
2157       return( DefWindowProc( hwnd, Msg, wParam, lParam ));
2158     }
2159     return 0L;
2160 }
2161
2162
2163
2164
2165 //==============================================================================
2166 //function : ViewerMainLoop
2167 //purpose  : Get a Event on the view and dispatch it
2168 //==============================================================================
2169
2170
2171 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2172 {
2173   Ppick = (argc > 0)? 1 : 0;
2174   Pargc = argc;
2175   Pargv = argv;
2176
2177   if ( Ppick ) {
2178     MSG msg;
2179     msg.wParam = 1;
2180
2181     cout << "Start picking" << endl;
2182
2183     while ( Ppick == 1 ) {
2184       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2185       if (GetMessage(&msg, NULL, 0, 0) ) {
2186         TranslateMessage(&msg);
2187         DispatchMessage(&msg);
2188       }
2189     }
2190
2191     cout << "Picking done" << endl;
2192   }
2193
2194   return Ppick;
2195 }
2196
2197 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2198
2199 int min( int a, int b )
2200 {
2201   if( a<b )
2202     return a;
2203   else
2204     return b;
2205 }
2206
2207 int max( int a, int b )
2208 {
2209   if( a>b )
2210     return a;
2211   else
2212     return b;
2213 }
2214
2215 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2216
2217 {
2218   static XEvent aReport;
2219   Standard_Boolean pick = argc > 0;
2220   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2221   XNextEvent (aDisplay, &aReport);
2222
2223   // Handle event for the chosen display connection
2224   switch (aReport.type) {
2225       case ClientMessage:
2226         {
2227           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2228           {
2229             // Close the window
2230             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2231           }
2232         }
2233         return 0;
2234      case FocusIn:
2235       {
2236          // Activate inactive view
2237          Window aWindow = GetWindowHandle(VT_GetWindow());
2238          if(aWindow != aReport.xfocus.window)
2239          {
2240            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2241          }
2242       }
2243       break;
2244       case Expose:
2245         {
2246           VT_ProcessExpose();
2247         }
2248         break;
2249       case ConfigureNotify:
2250         {
2251           VT_ProcessConfigure();
2252         }
2253         break;
2254       case KeyPress:
2255         {
2256
2257           KeySym ks_ret ;
2258           char buf_ret[11] ;
2259           int ret_len ;
2260           XComposeStatus status_in_out;
2261
2262           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2263             (char *) buf_ret , 10 ,
2264             &ks_ret , &status_in_out ) ;
2265
2266
2267           buf_ret[ret_len] = '\0' ;
2268
2269           if (ret_len)
2270           {
2271             VT_ProcessKeyPress (buf_ret);
2272           }
2273         }
2274         break;
2275       case ButtonPress:
2276         {
2277           X_ButtonPress = aReport.xbutton.x;
2278           Y_ButtonPress = aReport.xbutton.y;
2279
2280           if (aReport.xbutton.button == Button1)
2281           {
2282             if (aReport.xbutton.state & ControlMask)
2283             {
2284               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2285             }
2286             else
2287             {
2288               IsDragged = Standard_True;
2289               DragFirst = Standard_True;
2290             }
2291           }
2292           else if (aReport.xbutton.button == Button3)
2293           {
2294             // Start rotation
2295             VT_ProcessButton3Press();
2296           }
2297         }
2298         break;
2299       case ButtonRelease:
2300         {
2301           if( IsDragged )
2302           {
2303             if( !DragFirst )
2304             {
2305               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2306               {
2307                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2308                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2309               }
2310             }
2311
2312             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2313             if( aContext.IsNull() )
2314             {
2315               cout << "The context is null. Please use vinit before createmesh" << endl;
2316               return 0;
2317             }
2318
2319             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2320             if( aReport.xbutton.button==1 )
2321               if( DragFirst )
2322                 if( ShiftPressed )
2323                 {
2324                   aContext->ShiftSelect();
2325                 }
2326                 else
2327                 {
2328                   aContext->Select();
2329                 }
2330               else
2331                 if( ShiftPressed )
2332                 {
2333                   aContext->ShiftSelect( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2334                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2335                     ViewerTest::CurrentView());
2336                 }
2337                 else
2338                 {
2339                   aContext->Select( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2340                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2341                     ViewerTest::CurrentView() );
2342                 }
2343             else
2344               VT_ProcessButton3Release();
2345
2346             IsDragged = Standard_False;
2347           }
2348           else
2349             VT_ProcessButton3Release();
2350         }
2351         break;
2352       case MotionNotify:
2353         {
2354           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2355           {
2356             break;
2357           }
2358           if( IsDragged )
2359           {
2360             if( !DragFirst )
2361             {
2362               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2363               {
2364                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2365               }
2366             }
2367
2368             X_Motion = aReport.xmotion.x;
2369             Y_Motion = aReport.xmotion.y;
2370             DragFirst = Standard_False;
2371
2372             Window aWindow = GetWindowHandle(VT_GetWindow());
2373             Window aRoot;
2374             int anX, anY;
2375             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2376             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2377             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2378             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2379             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2380           }
2381           else
2382           {
2383             X_Motion = aReport.xmotion.x;
2384             Y_Motion = aReport.xmotion.y;
2385
2386             // remove all the ButtonMotionMaskr
2387             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2388
2389             if ( aReport.xmotion.state & ControlMask ) {
2390               if ( aReport.xmotion.state & Button1Mask ) {
2391                 ProcessControlButton1Motion();
2392               }
2393               else if ( aReport.xmotion.state & Button2Mask ) {
2394                 VT_ProcessControlButton2Motion();
2395               }
2396               else if ( aReport.xmotion.state & Button3Mask ) {
2397                 VT_ProcessControlButton3Motion();
2398               }
2399             }
2400             else
2401             {
2402               VT_ProcessMotion();
2403             }
2404           }
2405         }
2406         break;
2407 }
2408 return pick;
2409 }
2410
2411 //==============================================================================
2412 //function : VProcessEvents
2413 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2414 //       event in the Viewer window
2415 //==============================================================================
2416
2417 static void VProcessEvents(ClientData,int)
2418 {
2419   NCollection_Vector<int> anEventNumbers;
2420   // Get number of messages from every display
2421   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2422        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2423   {
2424     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2425   }
2426     // Handle events for every display
2427   int anEventIter = 0;
2428   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2429        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2430   {
2431     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2432          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2433     {
2434       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2435       int anEventResult = ViewerMainLoop( 0, NULL);
2436       // If window is closed or context was not found finish current event processing loop
2437       if (!anEventResult)
2438         return;
2439     }
2440   }
2441
2442   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2443
2444 }
2445 #endif
2446
2447 //==============================================================================
2448 //function : OSWindowSetup
2449 //purpose  : Setup for the X11 window to be able to cath the event
2450 //==============================================================================
2451
2452
2453 static void OSWindowSetup()
2454 {
2455 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2456   // X11
2457
2458   Window  window   = VT_GetWindow()->XWindow();
2459   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2460   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2461   XSynchronize(aDisplay, 1);
2462
2463   // X11 : For keyboard on SUN
2464   XWMHints wmhints;
2465   wmhints.flags = InputHint;
2466   wmhints.input = 1;
2467
2468   XSetWMHints( aDisplay, window, &wmhints);
2469
2470   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2471     ButtonPressMask | ButtonReleaseMask |
2472     StructureNotifyMask |
2473     PointerMotionMask |
2474     Button1MotionMask | Button2MotionMask |
2475     Button3MotionMask | FocusChangeMask
2476     );
2477   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2478   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2479
2480   XSynchronize(aDisplay, 0);
2481
2482 #else
2483   // _WIN32
2484 #endif
2485
2486 }
2487
2488 //==============================================================================
2489 //function : VFit
2490
2491 //purpose  : Fitall, no DRAW arguments
2492 //Draw arg : No args
2493 //==============================================================================
2494
2495 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgc, const char** theArgv)
2496 {
2497   if (theArgc > 2)
2498   {
2499     std::cout << "Wrong number of arguments! Use: vfit [-selected]" << std::endl;
2500   }
2501
2502   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2503
2504   if (theArgc == 2)
2505   {
2506     TCollection_AsciiString anArg (theArgv[1]);
2507     anArg.LowerCase();
2508     if (anArg == "-selected")
2509     {
2510       ViewerTest::GetAISContext()->FitSelected (aView);
2511       return 0;
2512     }
2513   }
2514   if (aView.IsNull() == Standard_False) {
2515
2516     aView->FitAll();
2517   }
2518   return 0;
2519 }
2520
2521 //=======================================================================
2522 //function : VFitArea
2523 //purpose  : Fit view to show area located between two points
2524 //         : given in world 2D or 3D coordinates.
2525 //=======================================================================
2526 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2527 {
2528   Handle(V3d_View) aView = ViewerTest::CurrentView();
2529   if (aView.IsNull())
2530   {
2531     std::cerr << theArgVec[0] << "Error: No active view.\n";
2532     return 1;
2533   }
2534
2535   // Parse arguments.
2536   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2537   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2538
2539   if (theArgNb == 5)
2540   {
2541     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2542     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2543     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2544     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2545   }
2546   else if (theArgNb == 7)
2547   {
2548     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2549     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2550     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2551     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2552     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2553     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2554   }
2555   else
2556   {
2557     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2558     theDI.PrintHelp(theArgVec[0]);
2559     return 1;
2560   }
2561
2562   // Convert model coordinates to view space
2563   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2564   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2565   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2566
2567   // Determine fit area
2568   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2569   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2570
2571   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2572
2573   if (aDiagonal < Precision::Confusion())
2574   {
2575     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2576     return 1;
2577   }
2578
2579   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2580   return 0;
2581 }
2582
2583 //==============================================================================
2584 //function : VZFit
2585 //purpose  : ZFitall, no DRAW arguments
2586 //Draw arg : No args
2587 //==============================================================================
2588 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2589 {
2590   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2591
2592   if (aCurrentView.IsNull())
2593   {
2594     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2595     return 1;
2596   }
2597
2598   if (theArgsNb == 1)
2599   {
2600     aCurrentView->ZFitAll();
2601     aCurrentView->Redraw();
2602     return 0;
2603   }
2604
2605   Standard_Real aScale = 1.0;
2606
2607   if (theArgsNb >= 2)
2608   {
2609     aScale = Draw::Atoi (theArgVec[1]);
2610   }
2611
2612   aCurrentView->ZFitAll (aScale);
2613   aCurrentView->Redraw();
2614
2615   return 0;
2616 }
2617
2618 //==============================================================================
2619 //function : VRepaint
2620 //purpose  :
2621 //==============================================================================
2622 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2623 {
2624   Handle(V3d_View) V = ViewerTest::CurrentView();
2625   if ( !V.IsNull() ) V->Redraw(); return 0;
2626 }
2627
2628 //==============================================================================
2629 //function : VClear
2630 //purpose  : Remove all the object from the viewer
2631 //Draw arg : No args
2632 //==============================================================================
2633
2634 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2635 {
2636   Handle(V3d_View) V = ViewerTest::CurrentView();
2637   if(!V.IsNull())
2638     ViewerTest::Clear();
2639   return 0;
2640 }
2641
2642 //==============================================================================
2643 //function : VPick
2644 //purpose  :
2645 //==============================================================================
2646
2647 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2648 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2649
2650 if ( argc < 4 ) {
2651   di << argv[0] << "Invalid number of arguments\n";
2652   return 1;
2653 }
2654
2655 while (ViewerMainLoop( argc, argv)) {
2656 }
2657
2658 return 0;
2659 }
2660
2661 //==============================================================================
2662 //function : VSetBg
2663 //purpose  : Load image as background
2664 //==============================================================================
2665
2666 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2667 {
2668   if (argc < 2 || argc > 3)
2669   {
2670     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2671     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2672     return 1;
2673   }
2674
2675   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2676   if(AISContext.IsNull())
2677   {
2678     di << "use 'vinit' command before " << argv[0] << "\n";
2679     return 1;
2680   }
2681
2682   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2683   if (argc == 3)
2684   {
2685     const char* szType = argv[2];
2686     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2687     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2688     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2689     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2690     else
2691     {
2692       di << "Wrong fill type : " << szType << "\n";
2693       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2694       return 1;
2695     }
2696   }
2697
2698   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2699   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2700
2701   return 0;
2702 }
2703
2704 //==============================================================================
2705 //function : VSetBgMode
2706 //purpose  : Change background image fill type
2707 //==============================================================================
2708
2709 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2710 {
2711   if (argc != 2)
2712   {
2713     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2714     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2715     return 1;
2716   }
2717
2718   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2719   if(AISContext.IsNull())
2720   {
2721     di << "use 'vinit' command before " << argv[0] << "\n";
2722     return 1;
2723   }
2724   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2725   const char* szType = argv[1];
2726   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2727   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2728   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2729   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2730   else
2731   {
2732     di << "Wrong fill type : " << szType << "\n";
2733     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2734     return 1;
2735   }
2736   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2737   V3dView->SetBgImageStyle(aFillType, Standard_True);
2738   return 0;
2739 }
2740
2741 //==============================================================================
2742 //function : VSetGradientBg
2743 //purpose  : Mount gradient background
2744 //==============================================================================
2745 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2746 {
2747   if (argc != 8 )
2748   {
2749     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2750     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2751     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2752     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2753     return 1;
2754   }
2755
2756   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2757   if(AISContext.IsNull())
2758   {
2759     di << "use 'vinit' command before " << argv[0] << "\n";
2760     return 1;
2761   }
2762   if (argc == 8)
2763   {
2764
2765     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2766     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2767     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2768     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2769
2770     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2771     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2772     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2773
2774     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2775     int aType = Draw::Atoi(argv[7]);
2776     if( aType < 0 || aType > 8 )
2777     {
2778       di << "Wrong fill type \n";
2779       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2780       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2781       return 1;
2782     }
2783
2784     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2785
2786     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2787     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2788   }
2789
2790   return 0;
2791 }
2792
2793 //==============================================================================
2794 //function : VSetGradientBgMode
2795 //purpose  : Change gradient background fill style
2796 //==============================================================================
2797 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2798 {
2799   if (argc != 2 )
2800   {
2801     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2802     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2803     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2804     return 1;
2805   }
2806
2807   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2808   if(AISContext.IsNull())
2809   {
2810     di << "use 'vinit' command before " << argv[0] << "\n";
2811     return 1;
2812   }
2813   if (argc == 2)
2814   {
2815     int aType = Draw::Atoi(argv[1]);
2816     if( aType < 0 || aType > 8 )
2817     {
2818       di << "Wrong fill type \n";
2819       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2820       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2821       return 1;
2822     }
2823
2824     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2825
2826     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2827     V3dView->SetBgGradientStyle( aMethod, 1 );
2828   }
2829
2830   return 0;
2831 }
2832
2833 //==============================================================================
2834 //function : VSetColorBg
2835 //purpose  : Set color background
2836 //==============================================================================
2837 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2838 {
2839   if (argc != 4 )
2840   {
2841     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2842     di << "R,G,B = [0..255]\n";
2843     return 1;
2844   }
2845
2846   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2847   if(AISContext.IsNull())
2848   {
2849     di << "use 'vinit' command before " << argv[0] << "\n";
2850     return 1;
2851   }
2852   if (argc == 4)
2853   {
2854
2855     Standard_Real R = Draw::Atof(argv[1])/255.;
2856     Standard_Real G = Draw::Atof(argv[2])/255.;
2857     Standard_Real B = Draw::Atof(argv[3])/255.;
2858     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2859
2860     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2861     V3dView->SetBackgroundColor( aColor );
2862     V3dView->Update();
2863   }
2864
2865   return 0;
2866 }
2867
2868 //==============================================================================
2869 //function : VSetDefaultBg
2870 //purpose  : Set default viewer background fill color
2871 //==============================================================================
2872 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2873 {
2874   if (theArgNb != 4
2875    && theArgNb != 8)
2876   {
2877     std::cout << "Error: wrong syntax! See usage:\n";
2878     theDI.PrintHelp (theArgVec[0]);
2879     return 1;
2880   }
2881
2882   ViewerTest_DefaultBackground.FillMethod =
2883     theArgNb == 4 ? Aspect_GFM_NONE
2884                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2885
2886   if (theArgNb == 4)
2887   {
2888     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2889     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2890     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2891     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2892   }
2893   else
2894   {
2895     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2896     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2897     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2898     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2899
2900     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2901     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2902     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2903     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2904   }
2905
2906   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2907        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2908   {
2909     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2910     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2911     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2912                                          ViewerTest_DefaultBackground.GradientColor2,
2913                                          ViewerTest_DefaultBackground.FillMethod);
2914   }
2915
2916   return 0;
2917 }
2918
2919 //==============================================================================
2920 //function : VScale
2921 //purpose  : View Scaling
2922 //==============================================================================
2923
2924 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2925 {
2926   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2927   if ( V3dView.IsNull() ) return 1;
2928
2929   if ( argc != 4 ) {
2930     di << argv[0] << "Invalid number of arguments\n";
2931     return 1;
2932   }
2933   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2934   return 0;
2935 }
2936 //==============================================================================
2937 //function : VZBuffTrihedron
2938 //purpose  :
2939 //==============================================================================
2940
2941 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2942                             Standard_Integer  theArgNb,
2943                             const char**      theArgVec)
2944 {
2945   Handle(V3d_View) aView = ViewerTest::CurrentView();
2946   if (aView.IsNull())
2947   {
2948     std::cout << "Error: no active viewer!\n";
2949     return 1;
2950   }
2951
2952   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2953
2954   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2955   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2956   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2957   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2958   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2959   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2960   Standard_Real                 aScale        = 0.1;
2961   Standard_Real                 aSizeRatio    = 0.8;
2962   Standard_Real                 anArrowDiam   = 0.05;
2963   Standard_Integer              aNbFacets     = 12;
2964   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2965   {
2966     Standard_CString        anArg = theArgVec[anArgIter];
2967     TCollection_AsciiString aFlag (anArg);
2968     aFlag.LowerCase();
2969     if (anUpdateTool.parseRedrawMode (aFlag))
2970     {
2971       continue;
2972     }
2973     else if (aFlag == "-on")
2974     {
2975       continue;
2976     }
2977     else if (aFlag == "-off")
2978     {
2979       aView->TriedronErase();
2980       return 0;
2981     }
2982     else if (aFlag == "-pos"
2983           || aFlag == "-position"
2984           || aFlag == "-corner")
2985     {
2986       if (++anArgIter >= theArgNb)
2987       {
2988         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
2989         return 1;
2990       }
2991
2992       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
2993       aPosName.LowerCase();
2994       if (aPosName == "center")
2995       {
2996         aPosition = Aspect_TOTP_CENTER;
2997       }
2998       else if (aPosName == "left_lower"
2999             || aPosName == "lower_left"
3000             || aPosName == "leftlower"
3001             || aPosName == "lowerleft")
3002       {
3003         aPosition = Aspect_TOTP_LEFT_LOWER;
3004       }
3005       else if (aPosName == "left_upper"
3006             || aPosName == "upper_left"
3007             || aPosName == "leftupper"
3008             || aPosName == "upperleft")
3009       {
3010         aPosition = Aspect_TOTP_LEFT_UPPER;
3011       }
3012       else if (aPosName == "right_lower"
3013             || aPosName == "lower_right"
3014             || aPosName == "rightlower"
3015             || aPosName == "lowerright")
3016       {
3017         aPosition = Aspect_TOTP_RIGHT_LOWER;
3018       }
3019       else if (aPosName == "right_upper"
3020             || aPosName == "upper_right"
3021             || aPosName == "rightupper"
3022             || aPosName == "upperright")
3023       {
3024         aPosition = Aspect_TOTP_RIGHT_UPPER;
3025       }
3026       else
3027       {
3028         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3029         return 1;
3030       }
3031     }
3032     else if (aFlag == "-type")
3033     {
3034       if (++anArgIter >= theArgNb)
3035       {
3036         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3037         return 1;
3038       }
3039
3040       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3041       aTypeName.LowerCase();
3042       if (aTypeName == "wireframe"
3043        || aTypeName == "wire")
3044       {
3045         aVisType = V3d_WIREFRAME;
3046       }
3047       else if (aTypeName == "zbuffer"
3048             || aTypeName == "shaded")
3049       {
3050         aVisType = V3d_ZBUFFER;
3051       }
3052       else
3053       {
3054         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3055       }
3056     }
3057     else if (aFlag == "-scale")
3058     {
3059       if (++anArgIter >= theArgNb)
3060       {
3061         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3062         return 1;
3063       }
3064
3065       aScale = Draw::Atof (theArgVec[anArgIter]);
3066     }
3067     else if (aFlag == "-size"
3068           || aFlag == "-sizeratio")
3069     {
3070       if (++anArgIter >= theArgNb)
3071       {
3072         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3073         return 1;
3074       }
3075
3076       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3077     }
3078     else if (aFlag == "-arrowdiam"
3079           || aFlag == "-arrowdiameter")
3080     {
3081       if (++anArgIter >= theArgNb)
3082       {
3083         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3084         return 1;
3085       }
3086
3087       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3088     }
3089     else if (aFlag == "-nbfacets")
3090     {
3091       if (++anArgIter >= theArgNb)
3092       {
3093         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3094         return 1;
3095       }
3096
3097       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3098     }
3099     else if (aFlag == "-colorlabel"
3100           || aFlag == "-colorlabels")
3101     {
3102       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3103                                                            theArgVec + anArgIter + 1,
3104                                                            aLabelsColor);
3105       if (aNbParsed == 0)
3106       {
3107         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3108         return 1;
3109       }
3110       anArgIter += aNbParsed;
3111     }
3112     else if (aFlag == "-colorarrowx")
3113     {
3114       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3115                                                            theArgVec + anArgIter + 1,
3116                                                            anArrowColorX);
3117       if (aNbParsed == 0)
3118       {
3119         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3120         return 1;
3121       }
3122       anArgIter += aNbParsed;
3123     }
3124     else if (aFlag == "-colorarrowy")
3125     {
3126       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3127                                                            theArgVec + anArgIter + 1,
3128                                                            anArrowColorY);
3129       if (aNbParsed == 0)
3130       {
3131         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3132         return 1;
3133       }
3134       anArgIter += aNbParsed;
3135     }
3136     else if (aFlag == "-colorarrowz")
3137     {
3138       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3139                                                            theArgVec + anArgIter + 1,
3140                                                            anArrowColorZ);
3141       if (aNbParsed == 0)
3142       {
3143         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3144         return 1;
3145       }
3146       anArgIter += aNbParsed;
3147     }
3148     else
3149     {
3150       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3151       return 1;
3152     }
3153   }
3154
3155   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3156                                aSizeRatio, anArrowDiam, aNbFacets);
3157   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3158   aView->ZFitAll();
3159   return 0;
3160 }
3161
3162 //==============================================================================
3163 //function : VRotate
3164 //purpose  : Camera Rotating
3165 //==============================================================================
3166
3167 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3168 {
3169   Handle(V3d_View) aView = ViewerTest::CurrentView();
3170   if (aView.IsNull())
3171   {
3172     std::cout << "No active view!\n";
3173     return 1;
3174   }
3175
3176   Standard_Boolean hasFlags = Standard_False;
3177   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3178   {
3179     Standard_CString        anArg (theArgVec[anArgIter]);
3180     TCollection_AsciiString aFlag (anArg);
3181     aFlag.LowerCase();
3182     if (aFlag == "-mousestart"
3183      || aFlag == "-mousefrom")
3184     {
3185       hasFlags = Standard_True;
3186       if (anArgIter + 2 >= theArgNb)
3187       {
3188         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3189         return 1;
3190       }
3191
3192       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3193       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3194       aView->StartRotation (anX, anY);
3195     }
3196     else if (aFlag == "-mousemove")
3197     {
3198       hasFlags = Standard_True;
3199       if (anArgIter + 2 >= theArgNb)
3200       {
3201         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3202         return 1;
3203       }
3204
3205       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3206       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3207       aView->Rotation (anX, anY);
3208     }
3209     else if (theArgNb != 4
3210           && theArgNb != 7)
3211     {
3212       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3213       return 1;
3214     }
3215   }
3216
3217   if (hasFlags)
3218   {
3219     return 0;
3220   }
3221   else if (theArgNb == 4)
3222   {
3223     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3224     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3225     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3226     aView->Rotate (anAX, anAY, anAZ);
3227     return 0;
3228   }
3229   else if (theArgNb == 7)
3230   {
3231     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3232     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3233     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3234
3235     Standard_Real anX = Draw::Atof (theArgVec[4]);
3236     Standard_Real anY = Draw::Atof (theArgVec[5]);
3237     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3238
3239     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3240     return 0;
3241   }
3242
3243   std::cout << "Error: Invalid number of arguments\n";
3244   return 1;
3245 }
3246
3247 //==============================================================================
3248 //function : VZoom
3249 //purpose  : View zoom in / out (relative to current zoom)
3250 //==============================================================================
3251
3252 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3253   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3254   if ( V3dView.IsNull() ) {
3255     return 1;
3256   }
3257
3258   if ( argc == 2 ) {
3259     Standard_Real coef = Draw::Atof(argv[1]);
3260     if ( coef <= 0.0 ) {
3261       di << argv[1] << "Invalid value\n";
3262       return 1;
3263     }
3264     V3dView->SetZoom( Draw::Atof(argv[1]) );
3265     return 0;
3266   } else {
3267     di << argv[0] << " Invalid number of arguments\n";
3268     return 1;
3269   }
3270 }
3271
3272 //==============================================================================
3273 //function : VPan
3274 //purpose  : View panning (in pixels)
3275 //==============================================================================
3276
3277 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3278   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3279   if ( V3dView.IsNull() ) return 1;
3280
3281   if ( argc == 3 ) {
3282     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3283     return 0;
3284   } else {
3285     di << argv[0] << " Invalid number of arguments\n";
3286     return 1;
3287   }
3288 }
3289
3290 //==============================================================================
3291 //function : VPlace
3292 //purpose  : Place the point (in pixels) at the center of the window
3293 //==============================================================================
3294 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3295 {
3296   Handle(V3d_View) aView = ViewerTest::CurrentView();
3297   if (aView.IsNull())
3298   {
3299     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3300     return 1;
3301   }
3302
3303   if (theArgNb != 3)
3304   {
3305     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3306     return 1;
3307   }
3308
3309   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3310
3311   return 0;
3312 }
3313
3314 //==============================================================================
3315 //function : VExport
3316 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3317 //==============================================================================
3318
3319 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3320 {
3321   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3322   if (V3dView.IsNull())
3323     return 1;
3324
3325   if (argc == 1)
3326   {
3327     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3328     return 1;
3329   }
3330
3331   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3332   TCollection_AsciiString aFormatStr;
3333
3334   TCollection_AsciiString aFileName (argv[1]);
3335   Standard_Integer aLen = aFileName.Length();
3336
3337   if (argc > 2)
3338   {
3339     aFormatStr = TCollection_AsciiString (argv[2]);
3340   }
3341   else if (aLen >= 4)
3342   {
3343     if (aFileName.Value (aLen - 2) == '.')
3344     {
3345       aFormatStr = aFileName.ToCString() + aLen - 2;
3346     }
3347     else if (aFileName.Value (aLen - 3) == '.')
3348     {
3349       aFormatStr = aFileName.ToCString() + aLen - 3;
3350     }
3351     else
3352     {
3353       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3354       return 1;
3355     }
3356   }
3357   else
3358   {
3359     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3360     return 1;
3361   }
3362
3363   aFormatStr.UpperCase();
3364   if (aFormatStr == "PS")
3365     anExpFormat = Graphic3d_EF_PostScript;
3366   else if (aFormatStr == "EPS")
3367     anExpFormat = Graphic3d_EF_EnhPostScript;
3368   else if (aFormatStr == "TEX")
3369     anExpFormat = Graphic3d_EF_TEX;
3370   else if (aFormatStr == "PDF")
3371     anExpFormat = Graphic3d_EF_PDF;
3372   else if (aFormatStr == "SVG")
3373     anExpFormat = Graphic3d_EF_SVG;
3374   else if (aFormatStr == "PGF")
3375     anExpFormat = Graphic3d_EF_PGF;
3376   else if (aFormatStr == "EMF")
3377     anExpFormat = Graphic3d_EF_EMF;
3378   else
3379   {
3380     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3381     return 1;
3382   }
3383
3384   try
3385   {
3386   Standard_DISABLE_DEPRECATION_WARNINGS
3387     if (!V3dView->Export (argv[1], anExpFormat))
3388   Standard_ENABLE_DEPRECATION_WARNINGS
3389     {
3390       di << "Error: export of image to " << aFormatStr << " failed!\n";
3391     }
3392   }
3393   catch (Standard_Failure)
3394   {
3395     di << "Error: export of image to " << aFormatStr << " failed";
3396     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
3397   }
3398   return 0;
3399 }
3400
3401 //==============================================================================
3402 //function : VColorScale
3403 //purpose  : representation color scale
3404 //==============================================================================
3405
3406 static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
3407                                     const TCollection_AsciiString& theGreen,
3408                                     const TCollection_AsciiString& theBlue,
3409                                                     Standard_Real& theRedValue,
3410                                                     Standard_Real& theGreenValue,
3411                                                     Standard_Real& theBlueValue)
3412 {
3413   if (!theRed.IsRealValue()
3414    || !theGreen.IsRealValue()
3415    || !theBlue.IsRealValue())
3416   {
3417     std::cout << "Error: RGB color values should be real!\n";
3418     return Standard_True;
3419   }
3420   theRedValue = theRed    .RealValue();
3421   theGreenValue = theGreen.RealValue();
3422   theBlueValue = theBlue  .RealValue();
3423   if (theRedValue < 0.0 || theRedValue > 1.0
3424    || theGreenValue < 0.0 || theGreenValue > 1.0
3425    || theBlueValue < 0.0 || theBlueValue > 1.0)
3426   {
3427     std::cout << "Error: RGB color values should be within range 0..1!\n";
3428     return Standard_True;
3429   }
3430   return Standard_False;
3431 }
3432
3433 static int VColorScale (Draw_Interpretor& theDI,
3434                         Standard_Integer  theArgNb,
3435                         const char**      theArgVec)
3436 {
3437   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3438   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3439   if (aContext.IsNull())
3440   {
3441     std::cout << "Error: no active view!\n";
3442     return 1;
3443   }
3444   if (theArgNb <= 1)
3445   {
3446     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3447     return 1;
3448   }
3449
3450   Handle(AIS_ColorScale) aCS;
3451   // find object
3452   Handle(AIS_InteractiveObject) anIObj;
3453   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3454   {
3455     aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3456     if (aCS.IsNull())
3457     {
3458       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3459       return 1;
3460     }
3461   }
3462   else
3463   {
3464     aCS = new AIS_ColorScale();
3465     GetMapOfAIS().Bind (aCS,theArgVec[1]);
3466   }
3467
3468   if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD)
3469   {
3470     aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3471   }
3472   if (aCS->GetTransformPersistenceMode() != Graphic3d_TMF_2d)
3473   {
3474     aContext->SetTransformPersistence (aCS, Graphic3d_TMF_2d, gp_Pnt (-1.0, -1.0, 0.0));
3475   }
3476
3477   Standard_Real                   aMinRange    = aCS->GetMin();
3478   Standard_Real                   aMaxRange    = aCS->GetMax();
3479   Standard_Integer                aBreadth     = aCS->GetBreadth();
3480   Standard_Integer                aHeight      = aCS->GetHeight();
3481   Standard_Integer                aNbIntervals = aCS->GetNumberOfIntervals();
3482   Standard_Integer                aTextHeight  = aCS->GetTextHeight();
3483   Aspect_TypeOfColorScalePosition aLabPosition = aCS->GetLabelPosition();
3484   Standard_Integer                aPosX = aCS->GetXPosition();
3485   Standard_Integer                aPosY = aCS->GetYPosition();
3486
3487   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3488
3489   if (theArgNb <= 2)
3490   {
3491     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3492           << "Min range: " << aMinRange << "\n"
3493           << "Max range: " << aMaxRange << "\n"
3494           << "Number of intervals: " << aNbIntervals << "\n"
3495           << "Text height: " << aTextHeight << "\n"
3496           << "Color scale position: " << aPosX <<" "<< aPosY<< "\n"
3497           << "Color scale title: " << aCS->GetTitle() << "\n"
3498           << "Label position: ";
3499     switch (aLabPosition)
3500     {
3501       case Aspect_TOCSP_NONE:
3502         theDI << "None\n";
3503         break;
3504       case Aspect_TOCSP_LEFT:
3505         theDI << "Left\n";
3506         break;
3507       case Aspect_TOCSP_RIGHT:
3508         theDI << "Right\n";
3509         break;
3510       case Aspect_TOCSP_CENTER:
3511         theDI << "Center\n";
3512         break;
3513     }
3514     return 0;
3515   }
3516
3517   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3518   {
3519     Standard_CString        anArg = theArgVec[anArgIter];
3520     TCollection_AsciiString aFlag (anArg);
3521     aFlag.LowerCase();
3522     if (anUpdateTool.parseRedrawMode (aFlag))
3523     {
3524       continue;
3525     }
3526     else if (aFlag == "-range")
3527     {
3528       if (anArgIter + 3 >= theArgNb)
3529       {
3530         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3531         return 1;
3532       }
3533
3534       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3535       TCollection_AsciiString anArg2 (theArgVec[++anArgIter]);
3536       TCollection_AsciiString anArg3 (theArgVec[++anArgIter]);
3537       if (!anArg1.IsRealValue())
3538       {
3539         std::cout << "Error: the minRange value should be real!\n";
3540         return 1;
3541       }
3542       else if (!anArg2.IsRealValue())
3543       {
3544         std::cout << "Error: the maxRange value should be real!\n";
3545         return 1;
3546       }
3547       else if (!anArg3.IsIntegerValue())
3548       {
3549         std::cout << "Error: the number of intervals should be integer!\n";
3550         return 1;
3551       }
3552
3553       aMinRange    = anArg1.RealValue();
3554       aMaxRange    = anArg2.RealValue();
3555       aNbIntervals = anArg3.IntegerValue();
3556     }
3557     else if (aFlag == "-font")
3558     {
3559       if (anArgIter + 1 >= theArgNb)
3560       {
3561         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3562         return 1;
3563       }
3564       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3565       if (!aFontArg.IsIntegerValue())
3566       {
3567         std::cout << "Error: HeightFont value should be integer!\n";
3568         return 1;
3569       }
3570
3571       aTextHeight = aFontArg.IntegerValue();
3572       anArgIter += 1;
3573     }
3574     else if (aFlag == "-textpos")
3575     {
3576       if (anArgIter + 1 >= theArgNb)
3577       {
3578         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3579         return 1;
3580       }
3581       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3582       aTextPosArg.LowerCase();
3583       if (aTextPosArg == "none")
3584       {
3585         aLabPosition = Aspect_TOCSP_NONE;
3586       }
3587       else if (aTextPosArg == "left")
3588       {
3589         aLabPosition = Aspect_TOCSP_LEFT;
3590       }
3591       else if (aTextPosArg == "right")
3592       {
3593         aLabPosition = Aspect_TOCSP_RIGHT;
3594       }
3595       else if (aTextPosArg == "center")
3596       {
3597         aLabPosition = Aspect_TOCSP_CENTER;
3598       }
3599       else
3600       {
3601         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3602         return 1;
3603       }
3604     }
3605     else if (aFlag == "-logarithmic"
3606           || aFlag == "-log")
3607     {
3608       if (anArgIter + 1 >= theArgNb)
3609       {
3610         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3611         return 1;
3612       }
3613       Standard_Boolean IsLog;
3614       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3615       {
3616         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3617         return 1;
3618       }
3619       aCS->SetLogarithmic (IsLog);
3620     }
3621     else if (aFlag == "-xy")
3622     {
3623       if (anArgIter + 2 >= theArgNb)
3624       {
3625         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3626         return 1;
3627       }
3628
3629       TCollection_AsciiString aX (theArgVec[++anArgIter]);
3630       TCollection_AsciiString aY (theArgVec[++anArgIter]);
3631       if (!aX.IsIntegerValue()
3632        || !aY.IsIntegerValue())
3633       {
3634         std::cout << "Error: coordinates should be integer values!\n";
3635         return 1;
3636       }
3637
3638       aPosX = aX.IntegerValue();
3639       aPosY = aY.IntegerValue();
3640     }
3641     else if (aFlag == "-width"
3642           || aFlag == "-w")
3643     {
3644       if (anArgIter + 1 >= theArgNb)
3645       {
3646         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3647         return 1;
3648       }
3649
3650       TCollection_AsciiString aW (theArgVec[++anArgIter]);
3651       if (!aW.IsIntegerValue())
3652       {
3653         std::cout << "Error: a width should be an integer value!\n";
3654         return 1;
3655       }
3656
3657       aBreadth = aW.IntegerValue();
3658     }
3659     else if (aFlag == "-height"
3660           || aFlag == "-h")
3661     {
3662       if (anArgIter + 1 >= theArgNb)
3663       {
3664         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3665         return 1;
3666       }
3667
3668       TCollection_AsciiString aH (theArgVec[++anArgIter]);
3669       if (!aH.IsIntegerValue())
3670       {
3671         std::cout << "Error: a width should be an integer value!\n";
3672         return 1;
3673       }
3674
3675       aHeight = aH.IntegerValue();
3676     }
3677     else if (aFlag == "-color")
3678     {
3679       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3680       {
3681         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3682         return 1;
3683       }
3684
3685       Quantity_NameOfColor aColorName;
3686       if (anArgIter + 4 >= theArgNb)
3687       {
3688         if (anArgIter + 2 >= theArgNb)
3689         {
3690           std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3691           return 1;
3692         }
3693         else if (!Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3694         {
3695           std::cout << "Error: wrong color name: '" << theArgVec[anArgIter + 2] << "' !\n";
3696           return 1;
3697         }
3698       }
3699
3700       TCollection_AsciiString anInd (theArgVec[anArgIter + 1]);
3701       if (!anInd.IsIntegerValue())
3702       {
3703         std::cout << "Error: Index value should be integer!\n";
3704         return 1;
3705       }
3706
3707       Standard_Integer anIndex = anInd.IntegerValue();
3708       if (anIndex <= 0 || anIndex > aNbIntervals)
3709       {
3710         std::cout << "Error: Index value should be within range 1.." << aNbIntervals <<"!\n";
3711         return 1;
3712       }
3713
3714       if (Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3715       {
3716         aCS->SetIntervalColor (Quantity_Color (aColorName), anIndex);
3717         aCS->SetColorType (Aspect_TOCSD_USER);
3718         anArgIter += 2;
3719         continue;
3720       }
3721
3722       TCollection_AsciiString aRed   (theArgVec[anArgIter + 2]);
3723       TCollection_AsciiString aGreen (theArgVec[anArgIter + 3]);
3724       TCollection_AsciiString aBlue  (theArgVec[anArgIter + 4]);
3725       Standard_Real aRedValue,aGreenValue, aBlueValue;
3726       if(checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3727       {
3728         return 1;
3729       }
3730       aCS->SetIntervalColor (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB), anIndex);
3731       aCS->SetColorType (Aspect_TOCSD_USER);
3732       anArgIter += 4;
3733     }
3734     else if (aFlag == "-label")
3735     {
3736       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3737       {
3738         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3739         return 1;
3740       }
3741       else if (anArgIter + 2 >= theArgNb)
3742       {
3743         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3744         return 1;
3745       }
3746
3747       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3748       if (anIndex <= 0 || anIndex > aNbIntervals+1)
3749       {
3750         std::cout << "Error: Index value should be within range 1.." << aNbIntervals+1 <<"!\n";
3751         return 1;
3752       }
3753
3754       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3755       aCS->SetLabel     (aText, anIndex);
3756       aCS->SetLabelType (Aspect_TOCSD_USER);
3757       anArgIter += 2;
3758     }
3759     else if (aFlag == "-colors")
3760     {
3761       Aspect_SequenceOfColor aSeq;
3762       if (anArgIter + aNbIntervals + 1 > theArgNb)
3763       {
3764         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3765                   << aNbIntervals << " intervals\n";
3766         return 1;
3767       }
3768
3769       Standard_Integer aColorIter = anArgIter + 1;
3770       while (aColorIter < theArgNb)
3771       {
3772         if (theArgVec[aColorIter][0] == '-')
3773         {
3774           break;
3775         }
3776
3777         else if (theArgVec[aColorIter][0] >= 97
3778               && theArgVec[aColorIter][0] <= 122)
3779         {
3780           Quantity_NameOfColor aColorName;
3781           if (!Quantity_Color::ColorFromName (theArgVec[aColorIter], aColorName))
3782           {
3783             std::cout << "Error: wrong color name: " << theArgVec[aColorIter] << " !\n";
3784             return 1;
3785           }
3786           aSeq.Append (Quantity_Color (aColorName));
3787           aColorIter++;
3788           anArgIter++;
3789         }
3790         else
3791         {
3792           TCollection_AsciiString aRed   (theArgVec[aColorIter]);
3793           TCollection_AsciiString aGreen (theArgVec[aColorIter + 1]);
3794           TCollection_AsciiString aBlue  (theArgVec[aColorIter + 2]);
3795           Standard_Real aRedValue,aGreenValue, aBlueValue;
3796           if (checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3797           {
3798             return 1;
3799           }
3800           aSeq.Append (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB));
3801           aColorIter += 3;
3802           anArgIter += 3;
3803         }
3804       }
3805       if (aSeq.Length() < aNbIntervals)
3806       {
3807         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3808                   << aNbIntervals << " intervals\n";
3809         return 1;
3810       }
3811
3812       aCS->SetColors    (aSeq);
3813       aCS->SetColorType (Aspect_TOCSD_USER);
3814     }
3815     else if (aFlag == "-labels")
3816     {
3817       if (anArgIter + aNbIntervals + 1 >= theArgNb)
3818       {
3819         std::cout << "Error: not enough arguments! You should provide " << (aNbIntervals + 1)
3820                   << " text labels for " << aNbIntervals << " intervals.\n";
3821         return 1;
3822       }
3823
3824       TColStd_SequenceOfExtendedString aSeq;
3825       for (int aLabelIter = anArgIter + 1; aLabelIter <= anArgIter + aNbIntervals + 1; aLabelIter += 1)
3826       {
3827         aSeq.Append (TCollection_ExtendedString (theArgVec[aLabelIter]));
3828       }
3829       aCS->SetLabels (aSeq);
3830       aCS->SetLabelType (Aspect_TOCSD_USER);
3831       anArgIter += aSeq.Length();
3832     }
3833     else if (aFlag == "-title")
3834     {
3835       if (anArgIter + 1 >= theArgNb)
3836       {
3837         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3838         return 1;
3839       }
3840
3841       Standard_Boolean isTwoArgs = Standard_False;
3842       if (anArgIter + 2 < theArgNb)
3843       {
3844         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3845         aSecondArg.LowerCase();
3846         if (aSecondArg == "none")
3847         {
3848           aCS->SetTitlePosition (Aspect_TOCSP_NONE);
3849           isTwoArgs = Standard_True;
3850         }
3851         else if (aSecondArg == "left")
3852         {
3853           aCS->SetTitlePosition (Aspect_TOCSP_LEFT);
3854           isTwoArgs = Standard_True;
3855         }
3856         else if (aSecondArg == "right")
3857         {
3858           aCS->SetTitlePosition (Aspect_TOCSP_RIGHT);
3859           isTwoArgs = Standard_True;
3860         }
3861         else if (aSecondArg == "center")
3862         {
3863           aCS->SetTitlePosition (Aspect_TOCSP_CENTER);
3864           isTwoArgs = Standard_True;
3865         }
3866       }
3867
3868       aCS->SetTitle (theArgVec[anArgIter + 1]);
3869       if (isTwoArgs)
3870       {
3871         anArgIter += 1;
3872       }
3873       anArgIter += 1;
3874     }
3875     else if (aFlag == "-demoversion"
3876           || aFlag == "-demo")
3877     {
3878       aPosX        = 0;
3879       aPosY        = 0;
3880       aTextHeight  = 16;
3881       aMinRange    = 0.0;
3882       aMaxRange    = 100;
3883       aNbIntervals = 10;
3884       aBreadth     = 0;
3885       aHeight      = 0;
3886       aLabPosition = Aspect_TOCSP_RIGHT;
3887       aCS->SetColorType (Aspect_TOCSD_AUTO);
3888       aCS->SetLabelType (Aspect_TOCSD_AUTO);
3889     }
3890     else if (aFlag == "-findcolor")
3891     {
3892       if (anArgIter + 1 >= theArgNb)
3893       {
3894         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3895         return 1;
3896       }
3897
3898       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3899
3900       if (!anArg1.IsRealValue())
3901       {
3902         std::cout << "Error: the value should be real!\n";
3903         return 1;
3904       }
3905
3906       Quantity_Color aColor;
3907       aCS->FindColor (anArg1.RealValue(), aColor);
3908       theDI << Quantity_Color::StringName (aColor.Name());
3909       return 0;
3910     }
3911     else
3912     {
3913       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3914       return 1;
3915     }
3916   }
3917   if (!aBreadth || !aHeight)
3918   {
3919     Standard_Integer aWinWidth, aWinHeight;
3920     aView->Window()->Size (aWinWidth, aWinHeight);
3921     if (!aBreadth)
3922     {
3923       aBreadth = aWinWidth;
3924     }
3925     if (!aHeight)
3926     {
3927       aHeight = aWinHeight;
3928     }
3929   }
3930   aCS->SetSize              (aBreadth, aHeight);
3931   aCS->SetPosition          (aPosX, aPosY);
3932   aCS->SetTextHeight        (aTextHeight);
3933   aCS->SetRange             (aMinRange, aMaxRange);
3934   aCS->SetNumberOfIntervals (aNbIntervals);
3935   aCS->SetLabelPosition     (aLabPosition);
3936 //  aCS->SetColor             (aView->BackgroundColor().Invert());
3937   aCS->SetToUpdate();
3938   aContext->Display (aCS);
3939
3940   return 0;
3941 }
3942
3943 //==============================================================================
3944 //function : VGraduatedTrihedron
3945 //purpose  : Displays or hides a graduated trihedron
3946 //==============================================================================
3947 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
3948                                   Quantity_Color& theColor)
3949 {
3950   Quantity_NameOfColor aColorName;
3951   TCollection_AsciiString aVal = theValue;
3952   aVal.UpperCase();
3953   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
3954   {
3955     return Standard_False;
3956   }
3957   theColor = Quantity_Color (aColorName);
3958   return Standard_True;
3959 }
3960
3961 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
3962 {
3963   if (theArgNum < 2)
3964   {
3965     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
3966               << theArgs[0] <<"' for more information.\n";
3967     return 1;  //TCL_ERROR
3968   }
3969
3970   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
3971   TCollection_AsciiString aParseKey;
3972   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
3973   {
3974     TCollection_AsciiString anArg (theArgs [anArgIt]);
3975
3976     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
3977     {
3978       aParseKey = anArg;
3979       aParseKey.Remove (1);
3980       aParseKey.LowerCase();
3981       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
3982       continue;
3983     }
3984
3985     if (aParseKey.IsEmpty())
3986     {
3987       continue;
3988     }
3989
3990     aMapOfArgs(aParseKey)->Append (anArg);
3991   }
3992
3993   // Check parameters
3994   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
3995        aMapIt.More(); aMapIt.Next())
3996   {
3997     const TCollection_AsciiString& aKey = aMapIt.Key();
3998     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
3999
4000     // Bool key, without arguments
4001     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4002         && anArgs->IsEmpty())
4003     {
4004       continue;
4005     }
4006
4007     // One argument
4008     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4009           && anArgs->Length() == 1)
4010     {
4011       continue;
4012     }
4013
4014     // On/off arguments
4015     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4016         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4017         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4018         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4019         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4020     {
4021       continue;
4022     }
4023
4024     // One string argument
4025     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4026           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4027           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4028     {
4029       continue;
4030     }
4031
4032     // One integer argument
4033     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4034           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4035           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4036           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4037          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4038     {
4039       continue;
4040     }
4041
4042     // One real argument
4043     if ( aKey.IsEqual ("arrowlength")
4044          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4045     {
4046       continue;
4047     }
4048
4049     // Two string arguments
4050     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4051          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4052     {
4053       continue;
4054     }
4055
4056     TCollection_AsciiString aLowerKey;
4057     aLowerKey  = "-";
4058     aLowerKey += aKey;
4059     aLowerKey.LowerCase();
4060     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4061     std::cout << "Type help for more information.\n";
4062     return 1;
4063   }
4064
4065   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4066   if (anAISContext.IsNull())
4067   {
4068     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4069     return 1;
4070   }
4071
4072   Standard_Boolean toDisplay = Standard_True;
4073   Quantity_Color aColor;
4074   Graphic3d_GraduatedTrihedron aTrihedronData;
4075   // Process parameters
4076   Handle(TColStd_HSequenceOfAsciiString) aValues;
4077   if (aMapOfArgs.Find ("off", aValues))
4078   {
4079     toDisplay = Standard_False;
4080   }
4081
4082   // AXES NAMES
4083   if (aMapOfArgs.Find ("xname", aValues))
4084   {
4085     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4086   }
4087   if (aMapOfArgs.Find ("yname", aValues))
4088   {
4089     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4090   }
4091   if (aMapOfArgs.Find ("zname", aValues))
4092   {
4093     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4094   }
4095   if (aMapOfArgs.Find ("xdrawname", aValues))
4096   {
4097     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4098   }
4099   if (aMapOfArgs.Find ("ydrawname", aValues))
4100   {
4101     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4102   }
4103   if (aMapOfArgs.Find ("zdrawname", aValues))
4104   {
4105     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4106   }
4107   if (aMapOfArgs.Find ("xnameoffset", aValues))
4108   {
4109     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4110   }
4111   if (aMapOfArgs.Find ("ynameoffset", aValues))
4112   {
4113     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4114   }
4115   if (aMapOfArgs.Find ("znameoffset", aValues))
4116   {
4117     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4118   }
4119
4120   // COLORS
4121   if (aMapOfArgs.Find ("xnamecolor", aValues))
4122   {
4123     if (!GetColor (aValues->Value(1), aColor))
4124     {
4125       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4126       return 1;
4127     }
4128     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4129   }
4130   if (aMapOfArgs.Find ("ynamecolor", aValues))
4131   {
4132     if (!GetColor (aValues->Value(1), aColor))
4133     {
4134       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4135       return 1;
4136     }
4137     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4138   }
4139   if (aMapOfArgs.Find ("znamecolor", aValues))
4140   {
4141     if (!GetColor (aValues->Value(1), aColor))
4142     {
4143       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4144       return 1;
4145     }
4146     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4147   }
4148   if (aMapOfArgs.Find ("xcolor", aValues))
4149   {
4150     if (!GetColor (aValues->Value(1), aColor))
4151     {
4152       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4153       return 1;
4154     }
4155     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4156   }
4157   if (aMapOfArgs.Find ("ycolor", aValues))
4158   {
4159     if (!GetColor (aValues->Value(1), aColor))
4160     {
4161       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4162       return 1;
4163     }
4164     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4165   }
4166   if (aMapOfArgs.Find ("zcolor", aValues))
4167   {
4168     if (!GetColor (aValues->Value(1), aColor))
4169     {
4170       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4171       return 1;
4172     }
4173     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4174   }
4175
4176   // TICKMARKS
4177   if (aMapOfArgs.Find ("xticks", aValues))
4178   {
4179     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4180   }
4181   if (aMapOfArgs.Find ("yticks", aValues))
4182   {
4183     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4184   }
4185   if (aMapOfArgs.Find ("zticks", aValues))
4186   {
4187     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4188   }
4189   if (aMapOfArgs.Find ("xticklength", aValues))
4190   {
4191     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4192   }
4193   if (aMapOfArgs.Find ("yticklength", aValues))
4194   {
4195     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4196   }
4197   if (aMapOfArgs.Find ("zticklength", aValues))
4198   {
4199     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4200   }
4201   if (aMapOfArgs.Find ("xdrawticks", aValues))
4202   {
4203     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4204   }
4205   if (aMapOfArgs.Find ("ydrawticks", aValues))
4206   {
4207     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4208   }
4209   if (aMapOfArgs.Find ("zdrawticks", aValues))
4210   {
4211     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4212   }
4213
4214   // VALUES
4215   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4216   {
4217     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4218   }
4219   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4220   {
4221     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4222   }
4223   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4224   {
4225     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4226   }
4227   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4228   {
4229     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4230   }
4231   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4232   {
4233     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4234   }
4235   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4236   {
4237     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4238   }
4239
4240   // ARROWS
4241   if (aMapOfArgs.Find ("arrowlength", aValues))
4242   {
4243     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4244   }
4245
4246   // FONTS
4247   if (aMapOfArgs.Find ("namefont", aValues))
4248   {
4249     aTrihedronData.SetNamesFont (aValues->Value(1));
4250   }
4251   if (aMapOfArgs.Find ("valuesfont", aValues))
4252   {
4253     aTrihedronData.SetValuesFont (aValues->Value(1));
4254   }
4255
4256   if (aMapOfArgs.Find ("drawgrid", aValues))
4257   {
4258     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4259   }
4260   if (aMapOfArgs.Find ("drawaxes", aValues))
4261   {
4262     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4263   }
4264
4265   // The final step: display of erase trihedron
4266   if (toDisplay)
4267   {
4268     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4269   }
4270   else
4271   {
4272     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4273   }
4274
4275   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4276   ViewerTest::CurrentView()->Redraw();
4277
4278   return 0;
4279 }
4280
4281 //==============================================================================
4282 //function : VTile
4283 //purpose  :
4284 //==============================================================================
4285 static int VTile (Draw_Interpretor& theDI,
4286                   Standard_Integer  theArgNb,
4287                   const char**      theArgVec)
4288 {
4289   Handle(V3d_View) aView = ViewerTest::CurrentView();
4290   if (aView.IsNull())
4291   {
4292     std::cerr << "Error: no active viewer.\n";
4293     return 1;
4294   }
4295
4296   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4297   if (theArgNb < 2)
4298   {
4299     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4300           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4301           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4302     return 0;
4303   }
4304
4305   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4306   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4307   {
4308     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4309     anArg.LowerCase();
4310     if (anArg == "-lowerleft"
4311      || anArg == "-upperleft")
4312     {
4313       if (anArgIter + 3 < theArgNb)
4314       {
4315         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4316         return 1;
4317       }
4318       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4319       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4320       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4321     }
4322     else if (anArg == "-total"
4323           || anArg == "-totalsize"
4324           || anArg == "-viewsize")
4325     {
4326       if (anArgIter + 3 < theArgNb)
4327       {
4328         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4329         return 1;
4330       }
4331       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4332       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4333       if (aTile.TotalSize.x() < 1
4334        || aTile.TotalSize.y() < 1)
4335       {
4336         std::cerr << "Error: total size is incorrect.\n";
4337         return 1;
4338       }
4339     }
4340     else if (anArg == "-tilesize")
4341     {
4342       if (anArgIter + 3 < theArgNb)
4343       {
4344         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4345         return 1;
4346       }
4347
4348       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4349       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4350       if (aTile.TileSize.x() < 1
4351        || aTile.TileSize.y() < 1)
4352       {
4353         std::cerr << "Error: tile size is incorrect.\n";
4354         return 1;
4355       }
4356     }
4357     else if (anArg == "-unset")
4358     {
4359       aView->Camera()->SetTile (Graphic3d_CameraTile());
4360       aView->Redraw();
4361       return 0;
4362     }
4363   }
4364
4365   if (aTile.TileSize.x() < 1
4366    || aTile.TileSize.y() < 1)
4367   {
4368     std::cerr << "Error: tile size is undefined.\n";
4369     return 1;
4370   }
4371   else if (aTile.TotalSize.x() < 1
4372         || aTile.TotalSize.y() < 1)
4373   {
4374     std::cerr << "Error: total size is undefined.\n";
4375     return 1;
4376   }
4377
4378   aView->Camera()->SetTile (aTile);
4379   aView->Redraw();
4380   return 0;
4381 }
4382
4383 //==============================================================================
4384 //function : VZLayer
4385 //purpose  : Test z layer operations for v3d viewer
4386 //==============================================================================
4387 static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4388 {
4389   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext ();
4390   if (aContextAIS.IsNull())
4391   {
4392     di << "Call vinit before!\n";
4393     return 1;
4394   }
4395   else if (argc < 2)
4396   {
4397     di << di.PrintHelp (argv[0]);
4398     return 1;
4399   }
4400
4401   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4402   if (aViewer.IsNull())
4403   {
4404     di << "No active viewer!\n";
4405     return 1;
4406   }
4407
4408   // perform operation
4409   TCollection_AsciiString anOp = TCollection_AsciiString (argv[1]);
4410   if (anOp == "add")
4411   {
4412     Standard_Integer aNewId;
4413     if (!aViewer->AddZLayer (aNewId))
4414     {
4415       di << "Impossible to add new z layer!\n";
4416       return 1;
4417     }
4418
4419     di << "New z layer added with index: " << aNewId << "\n";
4420   }
4421   else if (anOp == "del")
4422   {
4423     if (argc < 3)
4424     {
4425       di << "Please also provide as argument id of z layer to remove\n";
4426       return 1;
4427     }
4428
4429     Standard_Integer aDelId = Draw::Atoi (argv[2]);
4430     if (!aViewer->RemoveZLayer (aDelId))
4431     {
4432       di << "Impossible to remove the z layer or invalid id!\n";
4433       return 1;
4434     }
4435
4436     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4437          anObjIter.More(); anObjIter.Next())
4438     {
4439       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4440       if (aPrs.IsNull()
4441        || aPrs->ZLayer() != aDelId)
4442       {
4443         continue;
4444       }
4445       aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4446     }
4447
4448     di << "Z layer " << aDelId << " has been removed\n";
4449   }
4450   else if (anOp == "get")
4451   {
4452     TColStd_SequenceOfInteger anIds;
4453     aViewer->GetAllZLayers (anIds);
4454     for (Standard_Integer aSeqIdx = 1; aSeqIdx <= anIds.Length(); aSeqIdx++)
4455     {
4456       di << anIds.Value (aSeqIdx) << " ";
4457     }
4458
4459     di << "\n";
4460   }
4461   else if (anOp == "settings")
4462   {
4463     if (argc < 3)
4464     {
4465       di << "Please also provide an id\n";
4466       return 1;
4467     }
4468
4469     Standard_Integer anId = Draw::Atoi (argv[2]);
4470     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4471
4472     di << "Depth test - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthTest) ? "enabled" : "disabled") << "\n";
4473     di << "Depth write - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? "enabled" : "disabled") << "\n";
4474     di << "Depth buffer clearing - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthClear) ? "enabled" : "disabled") << "\n";
4475     di << "Depth offset - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthOffset) ? "enabled" : "disabled") << "\n";
4476
4477   }
4478   else if (anOp == "enable")
4479   {
4480     if (argc < 3)
4481     {
4482       di << "Please also provide an option to enable\n";
4483       return 1;
4484     }
4485
4486     if (argc < 4)
4487     {
4488       di << "Please also provide a layer id\n";
4489       return 1;
4490     }
4491
4492     TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
4493     Standard_Integer anId = Draw::Atoi (argv[3]);
4494     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4495
4496     if (aSubOp == "depthtest" || aSubOp == "test")
4497     {
4498       aSettings.EnableSetting (Graphic3d_ZLayerDepthTest);
4499     }
4500     else if (aSubOp == "depthwrite" || aSubOp == "write")
4501     {
4502       aSettings.EnableSetting (Graphic3d_ZLayerDepthWrite);
4503     }
4504     else if (aSubOp == "depthclear" || aSubOp == "clear")
4505     {
4506       aSettings.EnableSetting (Graphic3d_ZLayerDepthClear);
4507     }
4508     else if (aSubOp == "depthoffset" || aSubOp == "offset")
4509     {
4510       if (argc < 6)
4511       {
4512         di << "Please also provide a factor and units values for depth offset\n";
4513         di << "Format is: vzlayer enable offset [factor] [units] [layerId]\n";
4514         return 1;
4515       }
4516
4517       Standard_ShortReal aFactor = static_cast<Standard_ShortReal> (Draw::Atof (argv[3]));
4518       Standard_ShortReal aUnits  = static_cast<Standard_ShortReal> (Draw::Atof (argv[4]));
4519       anId = Draw::Atoi (argv[5]);
4520       aSettings = aViewer->ZLayerSettings (anId);
4521
4522       aSettings.DepthOffsetFactor = aFactor;
4523       aSettings.DepthOffsetUnits  = aUnits;
4524
4525       aSettings.EnableSetting (Graphic3d_ZLayerDepthOffset);
4526     }
4527     else if (aSubOp == "positiveoffset" || aSubOp == "poffset")
4528     {
4529       aSettings.SetDepthOffsetPositive();
4530     }
4531     else if (aSubOp == "negativeoffset" || aSubOp == "noffset")
4532     {
4533       aSettings.SetDepthOffsetNegative();
4534     }
4535     else if (aSubOp == "textureenv")
4536     {
4537       aSettings.UseEnvironmentTexture = true;
4538     }
4539
4540     aViewer->SetZLayerSettings (anId, aSettings);
4541   }
4542   else if (anOp == "disable")
4543   {
4544     if (argc < 3)
4545     {
4546       di << "Please also provide an option to disable\n";
4547       return 1;
4548     }
4549
4550     if (argc < 4)
4551     {
4552       di << "Please also provide a layer id\n";
4553       return 1;
4554     }
4555
4556     TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
4557     Standard_Integer anId = Draw::Atoi (argv[3]);
4558     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4559
4560     if (aSubOp == "depthtest" || aSubOp == "test")
4561     {
4562       aSettings.DisableSetting (Graphic3d_ZLayerDepthTest);
4563     }
4564     else if (aSubOp == "depthwrite" || aSubOp == "write")
4565     {
4566       aSettings.DisableSetting (Graphic3d_ZLayerDepthWrite);
4567     }
4568     else if (aSubOp == "depthclear" || aSubOp == "clear")
4569     {
4570       aSettings.DisableSetting (Graphic3d_ZLayerDepthClear);
4571     }
4572     else if (aSubOp == "depthoffset" || aSubOp == "offset")
4573     {
4574       aSettings.DisableSetting (Graphic3d_ZLayerDepthOffset);
4575     }
4576     else if (aSubOp == "textureenv")
4577     {
4578       aSettings.UseEnvironmentTexture = false;
4579     }
4580
4581     aViewer->SetZLayerSettings (anId, aSettings);
4582   }
4583   else
4584   {
4585     di << "Invalid operation, please use { add / del / get / settings / enable / disable}\n";
4586     return 1;
4587   }
4588
4589   return 0;
4590 }
4591
4592 // The interactive presentation of 2d layer item
4593 // for "vlayerline" command it provides a presentation of
4594 // line with user-defined linewidth, linetype and transparency.
4595 class V3d_LineItem : public AIS_InteractiveObject
4596 {
4597 public:
4598   // CASCADE RTTI
4599   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4600
4601   // constructor
4602   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4603                                Standard_Real X2, Standard_Real Y2,
4604                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4605                                Standard_Real theWidth    = 0.5,
4606                                Standard_Real theTransp   = 1.0);
4607
4608   private:
4609
4610   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4611                 const Handle(Prs3d_Presentation)& thePresentation,
4612                 const Standard_Integer theMode) Standard_OVERRIDE;
4613
4614   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4615                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4616   {}
4617
4618 private:
4619
4620   Standard_Real       myX1, myY1, myX2, myY2;
4621   Aspect_TypeOfLine   myType;
4622   Standard_Real       myWidth;
4623 };
4624
4625 // default constructor for line item
4626 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4627                            Standard_Real X2, Standard_Real Y2,
4628                            Aspect_TypeOfLine theType,
4629                            Standard_Real theWidth,
4630                            Standard_Real theTransp) :
4631   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4632   myType(theType), myWidth(theWidth)
4633 {
4634   SetTransparency (1-theTransp);
4635 }
4636
4637 // render line
4638 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4639                             const Handle(Prs3d_Presentation)& thePresentation,
4640                             const Standard_Integer /*theMode*/)
4641 {
4642   thePresentation->Clear();
4643   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4644   Standard_Integer aWidth, aHeight;
4645   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4646   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4647   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4648   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4649   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4650   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4651   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4652   aGroup->AddPrimitiveArray (aPrim);
4653 }
4654
4655 //=============================================================================
4656 //function : VLayerLine
4657 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4658 //         : linewidth, transparency coefficient
4659 //============================================================================
4660 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4661 {
4662   // get the active view
4663   Handle(V3d_View) aView = ViewerTest::CurrentView();
4664   if (aView.IsNull())
4665   {
4666     di << "Call vinit before!\n";
4667     return 1;
4668   }
4669   else if (argc < 5)
4670   {
4671     di << "Use: " << argv[0];
4672     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4673     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4674     di << "              0 - solid  \n";
4675     di << "              1 - dashed \n";
4676     di << "              2 - dot    \n";
4677     di << "              3 - dashdot\n";
4678     di << " transparency : { 0.0 - 1.0 } \n";
4679     di << "                  0.0 - transparent\n";
4680     di << "                  1.0 - visible    \n";
4681     return 1;
4682   }
4683
4684   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4685   // get the input params
4686   Standard_Real X1 = Draw::Atof(argv[1]);
4687   Standard_Real Y1 = Draw::Atof(argv[2]);
4688   Standard_Real X2 = Draw::Atof(argv[3]);
4689   Standard_Real Y2 = Draw::Atof(argv[4]);
4690
4691   Standard_Real    aWidth = 0.5;
4692   Standard_Integer aType  = 0;
4693   Standard_Real    aTransparency = 1.0;
4694
4695   // has width
4696   if (argc > 5)
4697     aWidth = Draw::Atof(argv[5]);
4698
4699   // has type
4700   if (argc > 6)
4701      aType = (Standard_Integer) Draw::Atoi(argv[6]);
4702
4703   // has transparency
4704   if (argc > 7)
4705   {
4706     aTransparency = Draw::Atof(argv[7]);
4707     if (aTransparency < 0 || aTransparency > 1.0)
4708       aTransparency = 1.0;
4709   }
4710
4711   // select appropriate line type
4712   Aspect_TypeOfLine aLineType;
4713   switch (aType)
4714   {
4715     case 1:
4716       aLineType = Aspect_TOL_DASH;
4717     break;
4718
4719     case 2:
4720       aLineType = Aspect_TOL_DOT;
4721     break;
4722
4723     case 3:
4724       aLineType = Aspect_TOL_DOTDASH;
4725     break;
4726
4727     default:
4728       aLineType = Aspect_TOL_SOLID;
4729   }
4730
4731   static Handle (V3d_LineItem) aLine;
4732   if (!aLine.IsNull())
4733   {
4734     aContext->Erase (aLine);
4735   }
4736   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4737                             aLineType, aWidth,
4738                             aTransparency);
4739
4740   aContext->SetTransformPersistence (aLine, Graphic3d_TMF_2d, gp_Pnt (-1.0, -1.0, 0.0));
4741   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4742   aLine->SetToUpdate();
4743   aContext->Display (aLine, Standard_True);
4744
4745   return 0;
4746 }
4747
4748
4749 //==============================================================================
4750 //function : VGrid
4751 //purpose  :
4752 //==============================================================================
4753
4754 static int VGrid (Draw_Interpretor& /*theDI*/,
4755                   Standard_Integer  theArgNb,
4756                   const char**      theArgVec)
4757 {
4758   // get the active view
4759   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4760   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4761   if (aView.IsNull() || aViewer.IsNull())
4762   {
4763     std::cerr << "No active view. Please call vinit.\n";
4764     return 1;
4765   }
4766
4767   Aspect_GridType     aType = aViewer->GridType();
4768   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4769
4770   Standard_Integer anIter = 1;
4771   for (; anIter < theArgNb; ++anIter)
4772   {
4773     const char* aValue = theArgVec[anIter];
4774     if (*aValue == 'r')
4775     {
4776       aType = Aspect_GT_Rectangular;
4777     }
4778     else if (*aValue == 'c')
4779     {
4780       aType = Aspect_GT_Circular;
4781     }
4782     else if (*aValue == 'l')
4783     {
4784       aMode = Aspect_GDM_Lines;
4785     }
4786     else if (*aValue == 'p')
4787     {
4788       aMode = Aspect_GDM_Points;
4789     }
4790     else if (strcmp (aValue, "off" ) == 0)
4791     {
4792       aViewer->DeactivateGrid();
4793       return 0;
4794     }
4795     else
4796     {
4797       break;
4798     }
4799   }
4800
4801   Standard_Integer aTail = (theArgNb - anIter);
4802   if (aTail == 0)
4803   {
4804     aViewer->ActivateGrid (aType, aMode);
4805     return 0;
4806   }
4807   else if (aTail != 2 && aTail != 5)
4808   {
4809     std::cerr << "Incorrect arguments number! Usage:\n"
4810               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
4811     return 1;
4812   }
4813
4814   Quantity_Length anOriginX, anOriginY;
4815   Quantity_PlaneAngle aRotAngle;
4816   if (aType == Aspect_GT_Rectangular)
4817   {
4818     Quantity_Length aRStepX, aRStepY;
4819     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
4820
4821     anOriginX = Draw::Atof (theArgVec[anIter++]);
4822     anOriginY = Draw::Atof (theArgVec[anIter++]);
4823     if (aTail == 5)
4824     {
4825       aRStepX   = Draw::Atof (theArgVec[anIter++]);
4826       aRStepY   = Draw::Atof (theArgVec[anIter++]);
4827       aRotAngle = Draw::Atof (theArgVec[anIter++]);
4828     }
4829     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
4830     aViewer->ActivateGrid (aType, aMode);
4831   }
4832   else if (aType == Aspect_GT_Circular)
4833   {
4834     Quantity_Length aRadiusStep;
4835     Standard_Integer aDivisionNumber;
4836     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
4837
4838     anOriginX = Draw::Atof (theArgVec[anIter++]);
4839     anOriginY = Draw::Atof (theArgVec[anIter++]);
4840     if (aTail == 5)
4841     {
4842       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
4843       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
4844       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
4845     }
4846
4847     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
4848     aViewer->ActivateGrid (aType, aMode);
4849   }
4850
4851   return 0;
4852 }
4853
4854 //==============================================================================
4855 //function : VPriviledgedPlane
4856 //purpose  :
4857 //==============================================================================
4858
4859 static int VPriviledgedPlane (Draw_Interpretor& theDI,
4860                               Standard_Integer  theArgNb,
4861                               const char**      theArgVec)
4862 {
4863   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
4864   {
4865     std::cerr << "Error: wrong number of arguments! See usage:\n";
4866     theDI.PrintHelp (theArgVec[0]);
4867     return 1;
4868   }
4869
4870   // get the active viewer
4871   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4872   if (aViewer.IsNull())
4873   {
4874     std::cerr << "Error: no active viewer. Please call vinit.\n";
4875     return 1;
4876   }
4877
4878   if (theArgNb == 1)
4879   {
4880     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
4881     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
4882     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
4883     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
4884     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
4885           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
4886           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
4887     return 0;
4888   }
4889
4890   Standard_Integer anArgIdx = 1;
4891   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
4892   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
4893   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
4894   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
4895   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
4896   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
4897
4898   gp_Ax3 aPriviledgedPlane;
4899   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
4900   gp_Dir aNorm (aNormX, aNormY, aNormZ);
4901   if (theArgNb > 7)
4902   {
4903     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
4904     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
4905     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
4906     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
4907     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
4908   }
4909   else
4910   {
4911     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
4912   }
4913
4914   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
4915
4916   return 0;
4917 }
4918
4919 //==============================================================================
4920 //function : VConvert
4921 //purpose  :
4922 //==============================================================================
4923
4924 static int VConvert (Draw_Interpretor& theDI,
4925                      Standard_Integer  theArgNb,
4926                      const char**      theArgVec)
4927 {
4928   // get the active view
4929   Handle(V3d_View) aView = ViewerTest::CurrentView();
4930   if (aView.IsNull())
4931   {
4932     std::cerr << "Error: no active view. Please call vinit.\n";
4933     return 1;
4934   }
4935
4936   enum { Model, Ray, View, Window, Grid } aMode = Model;
4937
4938   // access coordinate arguments
4939   TColStd_SequenceOfReal aCoord;
4940   Standard_Integer anArgIdx = 1;
4941   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
4942   {
4943     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
4944     if (!anArg.IsRealValue())
4945     {
4946       break;
4947     }
4948     aCoord.Append (anArg.RealValue());
4949   }
4950
4951   // non-numeric argument too early
4952   if (aCoord.IsEmpty())
4953   {
4954     std::cerr << "Error: wrong number of arguments! See usage:\n";
4955     theDI.PrintHelp (theArgVec[0]);
4956     return 1;
4957   }
4958
4959   // collect all other arguments and options
4960   for (; anArgIdx < theArgNb; ++anArgIdx)
4961   {
4962     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
4963     anArg.LowerCase();
4964     if      (anArg == "window") aMode = Window;
4965     else if (anArg == "view")   aMode = View;
4966     else if (anArg == "grid")   aMode = Grid;
4967     else if (anArg == "ray")    aMode = Ray;
4968     else
4969     {
4970       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
4971       theDI.PrintHelp (theArgVec[0]);
4972       return 1;
4973     }
4974   }
4975
4976   // complete input checks
4977   if ((aCoord.Length() == 1 && theArgNb > 3) ||
4978       (aCoord.Length() == 2 && theArgNb > 4) ||
4979       (aCoord.Length() == 3 && theArgNb > 5))
4980   {
4981     std::cerr << "Error: wrong number of arguments! See usage:\n";
4982     theDI.PrintHelp (theArgVec[0]);
4983     return 1;
4984   }
4985
4986   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4987   Standard_Integer aXYp[2] = {0, 0};
4988
4989   // convert one-dimensional coordinate
4990   if (aCoord.Length() == 1)
4991   {
4992     switch (aMode)
4993     {
4994       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
4995       case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
4996       default:
4997         std::cerr << "Error: wrong arguments! See usage:\n";
4998         theDI.PrintHelp (theArgVec[0]);
4999         return 1;
5000     }
5001   }
5002
5003   // convert 2D coordinates from projection or view reference space
5004   if (aCoord.Length() == 2)
5005   {
5006     switch (aMode)
5007     {
5008       case Model :
5009         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5010         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5011         return 0;
5012
5013       case View :
5014         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5015         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5016         return 0;
5017
5018       case Window :
5019         aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
5020         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5021         return 0;
5022
5023       case Grid :
5024         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5025         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5026         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5027         return 0;
5028
5029       case Ray :
5030         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5031                                 (Standard_Integer) aCoord (2),
5032                                 aXYZ[0], aXYZ[1], aXYZ[2],
5033                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5034         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5035         return 0;
5036
5037       default:
5038         std::cerr << "Error: wrong arguments! See usage:\n";
5039         theDI.PrintHelp (theArgVec[0]);
5040         return 1;
5041     }
5042   }
5043
5044   // convert 3D coordinates from view reference space
5045   else if (aCoord.Length() == 3)
5046   {
5047     switch (aMode)
5048     {
5049       case Window :
5050         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5051         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5052         return 0;
5053
5054       case Grid :
5055         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5056         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5057         return 0;
5058
5059       default:
5060         std::cerr << "Error: wrong arguments! See usage:\n";
5061         theDI.PrintHelp (theArgVec[0]);
5062         return 1;
5063     }
5064   }
5065
5066   return 0;
5067 }
5068
5069 //==============================================================================
5070 //function : VFps
5071 //purpose  :
5072 //==============================================================================
5073
5074 static int VFps (Draw_Interpretor& theDI,
5075                  Standard_Integer  theArgNb,
5076                  const char**      theArgVec)
5077 {
5078   // get the active view
5079   Handle(V3d_View) aView = ViewerTest::CurrentView();
5080   if (aView.IsNull())
5081   {
5082     std::cerr << "No active view. Please call vinit.\n";
5083     return 1;
5084   }
5085
5086   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5087   if (aFramesNb <= 0)
5088   {
5089     std::cerr << "Incorrect arguments!\n";
5090     return 1;
5091   }
5092
5093   // the time is meaningless for first call
5094   // due to async OpenGl rendering
5095   aView->Redraw();
5096
5097   // redraw view in loop to estimate average values
5098   OSD_Timer aTimer;
5099   aTimer.Start();
5100   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5101   {
5102     aView->Redraw();
5103   }
5104   aTimer.Stop();
5105   Standard_Real aCpu;
5106   const Standard_Real aTime = aTimer.ElapsedTime();
5107   aTimer.OSD_Chronometer::Show (aCpu);
5108
5109   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5110   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5111
5112   // return statistics
5113   theDI << "FPS: " << aFpsAver << "\n"
5114         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5115
5116   // compute additional statistics in ray-tracing mode
5117   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5118
5119   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5120   {
5121     Standard_Integer aSizeX;
5122     Standard_Integer aSizeY;
5123
5124     aView->Window()->Size (aSizeX, aSizeY);
5125
5126     // 1 shadow ray and 1 secondary ray pew each bounce
5127     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5128
5129     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5130   }
5131
5132   return 0;
5133 }
5134
5135 //==============================================================================
5136 //function : VGlDebug
5137 //purpose  :
5138 //==============================================================================
5139
5140 static int VGlDebug (Draw_Interpretor& theDI,
5141                      Standard_Integer  theArgNb,
5142                      const char**      theArgVec)
5143 {
5144   Handle(OpenGl_GraphicDriver) aDriver;
5145   Handle(V3d_View) aView = ViewerTest::CurrentView();
5146   if (!aView.IsNull())
5147   {
5148     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5149   }
5150   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5151   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5152
5153   if (theArgNb < 2)
5154   {
5155     TCollection_AsciiString aDebActive, aSyncActive;
5156     if (aCaps == NULL)
5157     {
5158       aCaps = aDefCaps;
5159     }
5160     else
5161     {
5162       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5163                                                                   "GL_ARB_debug_output");
5164       aDebActive = isActive ? " (active)" : " (inactive)";
5165       if (isActive)
5166       {
5167         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5168         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5169       }
5170     }
5171
5172     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5173           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5174           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5175           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5176     return 0;
5177   }
5178
5179   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5180   {
5181     Standard_CString        anArg     = theArgVec[anArgIter];
5182     TCollection_AsciiString anArgCase (anArg);
5183     anArgCase.LowerCase();
5184     Standard_Boolean toEnableDebug = Standard_True;
5185     if (anArgCase == "-glsl"
5186      || anArgCase == "-glslwarn"
5187      || anArgCase == "-glslwarns"
5188      || anArgCase == "-glslwarnings")
5189     {
5190       Standard_Boolean toShowWarns = Standard_True;
5191       if (++anArgIter < theArgNb
5192       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5193       {
5194         --anArgIter;
5195       }
5196       aDefCaps->glslWarnings = toShowWarns;
5197       if (aCaps != NULL)
5198       {
5199         aCaps->glslWarnings = toShowWarns;
5200       }
5201     }
5202     else if (anArgCase == "-extra"
5203           || anArgCase == "-extramsg"
5204           || anArgCase == "-extramessages")
5205     {
5206       Standard_Boolean toShow = Standard_True;
5207       if (++anArgIter < theArgNb
5208       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5209       {
5210         --anArgIter;
5211       }
5212       aDefCaps->suppressExtraMsg = !toShow;
5213       if (aCaps != NULL)
5214       {
5215         aCaps->suppressExtraMsg = !toShow;
5216       }
5217     }
5218     else if (anArgCase == "-noextra"
5219           || anArgCase == "-noextramsg"
5220           || anArgCase == "-noextramessages")
5221     {
5222       Standard_Boolean toSuppress = Standard_True;
5223       if (++anArgIter < theArgNb
5224       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5225       {
5226         --anArgIter;
5227       }
5228       aDefCaps->suppressExtraMsg = toSuppress;
5229       if (aCaps != NULL)
5230       {
5231         aCaps->suppressExtraMsg = toSuppress;
5232       }
5233     }
5234     else if (anArgCase == "-sync")
5235     {
5236       Standard_Boolean toSync = Standard_True;
5237       if (++anArgIter < theArgNb
5238       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5239       {
5240         --anArgIter;
5241       }
5242       aDefCaps->contextSyncDebug = toSync;
5243       if (toSync)
5244       {
5245         aDefCaps->contextDebug = Standard_True;
5246       }
5247     }
5248     else if (anArgCase == "-debug")
5249     {
5250       if (++anArgIter < theArgNb
5251       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5252       {
5253         --anArgIter;
5254       }
5255       aDefCaps->contextDebug = toEnableDebug;
5256     }
5257     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5258           && (anArgIter + 1 == theArgNb))
5259     {
5260       // simple alias to turn on almost everything
5261       aDefCaps->contextDebug     = toEnableDebug;
5262       aDefCaps->contextSyncDebug = toEnableDebug;
5263       aDefCaps->glslWarnings     = toEnableDebug;
5264     }
5265     else
5266     {
5267       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5268       return 1;
5269     }
5270   }
5271
5272   return 0;
5273 }
5274
5275 //==============================================================================
5276 //function : VVbo
5277 //purpose  :
5278 //==============================================================================
5279
5280 static int VVbo (Draw_Interpretor& theDI,
5281                  Standard_Integer  theArgNb,
5282                  const char**      theArgVec)
5283 {
5284   const Standard_Boolean toSet    = (theArgNb > 1);
5285   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5286   if (toSet)
5287   {
5288     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5289   }
5290
5291   // get the context
5292   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5293   if (aContextAIS.IsNull())
5294   {
5295     if (!toSet)
5296     {
5297       std::cerr << "No active view!\n";
5298     }
5299     return 1;
5300   }
5301   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5302   if (!aDriver.IsNull())
5303   {
5304     if (!toSet)
5305     {
5306       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5307     }
5308     else
5309     {
5310       aDriver->ChangeOptions().vboDisable = toUseVbo;
5311     }
5312   }
5313
5314   return 0;
5315 }
5316
5317 //==============================================================================
5318 //function : VCaps
5319 //purpose  :
5320 //==============================================================================
5321
5322 static int VCaps (Draw_Interpretor& theDI,
5323                   Standard_Integer  theArgNb,
5324                   const char**      theArgVec)
5325 {
5326   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5327   Handle(OpenGl_GraphicDriver)   aDriver;
5328   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5329   if (!aContext.IsNull())
5330   {
5331     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5332     aCaps   = &aDriver->ChangeOptions();
5333   }
5334
5335   if (theArgNb < 2)
5336   {
5337     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5338     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5339     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5340     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5341     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5342     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5343     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5344     return 0;
5345   }
5346
5347   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5348   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5349   {
5350     Standard_CString        anArg     = theArgVec[anArgIter];
5351     TCollection_AsciiString anArgCase (anArg);
5352     anArgCase.LowerCase();
5353     if (anUpdateTool.parseRedrawMode (anArg))
5354     {
5355       continue;
5356     }
5357     else if (anArgCase == "-vsync"
5358           || anArgCase == "-swapinterval")
5359     {
5360       Standard_Boolean toEnable = Standard_True;
5361       if (++anArgIter < theArgNb
5362       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5363       {
5364         --anArgIter;
5365       }
5366       aCaps->swapInterval = toEnable;
5367     }
5368     else if (anArgCase == "-ffp")
5369     {
5370       Standard_Boolean toEnable = Standard_True;
5371       if (++anArgIter < theArgNb
5372       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5373       {
5374         --anArgIter;
5375       }
5376       aCaps->ffpEnable = toEnable;
5377     }
5378     else if (anArgCase == "-vbo")
5379     {
5380       Standard_Boolean toEnable = Standard_True;
5381       if (++anArgIter < theArgNb
5382       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5383       {
5384         --anArgIter;
5385       }
5386       aCaps->vboDisable = !toEnable;
5387     }
5388     else if (anArgCase == "-sprite"
5389           || anArgCase == "-sprites")
5390     {
5391       Standard_Boolean toEnable = Standard_True;
5392       if (++anArgIter < theArgNb
5393       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5394       {
5395         --anArgIter;
5396       }
5397       aCaps->pntSpritesDisable = !toEnable;
5398     }
5399     else if (anArgCase == "-softmode")
5400     {
5401       Standard_Boolean toEnable = Standard_True;
5402       if (++anArgIter < theArgNb
5403       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5404       {
5405         --anArgIter;
5406       }
5407       aCaps->contextNoAccel = toEnable;
5408     }
5409     else if (anArgCase == "-accel"
5410           || anArgCase == "-acceleration")
5411     {
5412       Standard_Boolean toEnable = Standard_True;
5413       if (++anArgIter < theArgNb
5414       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5415       {
5416         --anArgIter;
5417       }
5418       aCaps->contextNoAccel = !toEnable;
5419     }
5420     else if (anArgCase == "-compat"
5421           || anArgCase == "-compatprofile"
5422           || anArgCase == "-compatible"
5423           || anArgCase == "-compatibleprofile")
5424     {
5425       Standard_Boolean toEnable = Standard_True;
5426       if (++anArgIter < theArgNb
5427       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5428       {
5429         --anArgIter;
5430       }
5431       aCaps->contextCompatible = toEnable;
5432       if (!aCaps->contextCompatible)
5433       {
5434         aCaps->ffpEnable = Standard_False;
5435       }
5436     }
5437     else if (anArgCase == "-core"
5438           || anArgCase == "-coreprofile")
5439     {
5440       Standard_Boolean toEnable = Standard_True;
5441       if (++anArgIter < theArgNb
5442       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5443       {
5444         --anArgIter;
5445       }
5446       aCaps->contextCompatible = !toEnable;
5447       if (!aCaps->contextCompatible)
5448       {
5449         aCaps->ffpEnable = Standard_False;
5450       }
5451     }
5452     else if (anArgCase == "-stereo"
5453           || anArgCase == "-quadbuffer")
5454     {
5455       Standard_Boolean toEnable = Standard_True;
5456       if (++anArgIter < theArgNb
5457       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5458       {
5459         --anArgIter;
5460       }
5461       aCaps->contextStereo = toEnable;
5462     }
5463     else
5464     {
5465       std::cout << "Error: unknown argument '" << anArg << "'\n";
5466       return 1;
5467     }
5468   }
5469   if (aCaps != &ViewerTest_myDefaultCaps)
5470   {
5471     ViewerTest_myDefaultCaps = *aCaps;
5472   }
5473   return 0;
5474 }
5475
5476 //==============================================================================
5477 //function : VMemGpu
5478 //purpose  :
5479 //==============================================================================
5480
5481 static int VMemGpu (Draw_Interpretor& theDI,
5482                     Standard_Integer  theArgNb,
5483                     const char**      theArgVec)
5484 {
5485   // get the context
5486   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5487   if (aContextAIS.IsNull())
5488   {
5489     std::cerr << "No active view. Please call vinit.\n";
5490     return 1;
5491   }
5492
5493   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5494   if (aDriver.IsNull())
5495   {
5496     std::cerr << "Graphic driver not available.\n";
5497     return 1;
5498   }
5499
5500   Standard_Size aFreeBytes = 0;
5501   TCollection_AsciiString anInfo;
5502   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5503   {
5504     std::cerr << "Information not available.\n";
5505     return 1;
5506   }
5507
5508   if (theArgNb > 1 && *theArgVec[1] == 'f')
5509   {
5510     theDI << Standard_Real (aFreeBytes);
5511   }
5512   else
5513   {
5514     theDI << anInfo;
5515   }
5516
5517   return 0;
5518 }
5519
5520 // ==============================================================================
5521 // function : VReadPixel
5522 // purpose  :
5523 // ==============================================================================
5524 static int VReadPixel (Draw_Interpretor& theDI,
5525                        Standard_Integer  theArgNb,
5526                        const char**      theArgVec)
5527 {
5528   // get the active view
5529   Handle(V3d_View) aView = ViewerTest::CurrentView();
5530   if (aView.IsNull())
5531   {
5532     std::cerr << "No active view. Please call vinit.\n";
5533     return 1;
5534   }
5535   else if (theArgNb < 3)
5536   {
5537     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5538     return 1;
5539   }
5540
5541   Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
5542   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
5543
5544   Standard_Integer aWidth, aHeight;
5545   aView->Window()->Size (aWidth, aHeight);
5546   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5547   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5548   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5549   {
5550     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5551     return 1;
5552   }
5553
5554   Standard_Boolean toShowName = Standard_False;
5555   Standard_Boolean toShowHls  = Standard_False;
5556   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5557   {
5558     const char* aParam = theArgVec[anIter];
5559     if ( strcasecmp( aParam, "rgb" ) == 0 )
5560     {
5561       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
5562       aBufferType = Graphic3d_BT_RGB;
5563     }
5564     else if ( strcasecmp( aParam, "hls" ) == 0 )
5565     {
5566       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
5567       aBufferType = Graphic3d_BT_RGB;
5568       toShowHls   = Standard_True;
5569     }
5570     else if ( strcasecmp( aParam, "rgbf" ) == 0 )
5571     {
5572       aFormat     = Image_PixMap::ImgRGBF;
5573       aBufferType = Graphic3d_BT_RGB;
5574     }
5575     else if ( strcasecmp( aParam, "rgba" ) == 0 )
5576     {
5577       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
5578       aBufferType = Graphic3d_BT_RGBA;
5579     }
5580     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
5581     {
5582       aFormat     = Image_PixMap::ImgRGBAF;
5583       aBufferType = Graphic3d_BT_RGBA;
5584     }
5585     else if ( strcasecmp( aParam, "depth" ) == 0 )
5586     {
5587       aFormat     = Image_PixMap::ImgGrayF;
5588       aBufferType = Graphic3d_BT_Depth;
5589     }
5590     else if ( strcasecmp( aParam, "name" ) == 0 )
5591     {
5592       toShowName = Standard_True;
5593     }
5594   }
5595
5596   Image_PixMap anImage;
5597   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5598   {
5599     std::cerr << "Image allocation failed\n";
5600     return 1;
5601   }
5602   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5603   {
5604     std::cerr << "Image dump failed\n";
5605     return 1;
5606   }
5607
5608   Quantity_Parameter anAlpha;
5609   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5610   if (toShowName)
5611   {
5612     if (aBufferType == Graphic3d_BT_RGBA)
5613     {
5614       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5615     }
5616     else
5617     {
5618       theDI << Quantity_Color::StringName (aColor.Name());
5619     }
5620   }
5621   else
5622   {
5623     switch (aBufferType)
5624     {
5625       default:
5626       case Graphic3d_BT_RGB:
5627       {
5628         if (toShowHls)
5629         {
5630           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5631         }
5632         else
5633         {
5634           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5635         }
5636         break;
5637       }
5638       case Graphic3d_BT_RGBA:
5639       {
5640         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5641         break;
5642       }
5643       case Graphic3d_BT_Depth:
5644       {
5645         theDI << aColor.Red();
5646         break;
5647       }
5648     }
5649   }
5650
5651   return 0;
5652 }
5653
5654 //==============================================================================
5655 //function : VDiffImage
5656 //purpose  : The draw-command compares two images.
5657 //==============================================================================
5658
5659 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5660 {
5661   if (theArgNb < 6)
5662   {
5663     theDI << "Not enough arguments.\n";
5664     return 1;
5665   }
5666
5667   // image file names
5668   const char* anImgPathRef = theArgVec[1];
5669   const char* anImgPathNew = theArgVec[2];
5670
5671   // get string tolerance and check its validity
5672   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5673   if (aTolColor < 0.0)
5674     aTolColor = 0.0;
5675   if (aTolColor > 1.0)
5676     aTolColor = 1.0;
5677
5678   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5679   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5680
5681   // image file of difference
5682   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5683
5684   // compare the images
5685   Image_Diff aComparer;
5686   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5687   {
5688     return 1;
5689   }
5690
5691   aComparer.SetColorTolerance (aTolColor);
5692   aComparer.SetBorderFilterOn (isBorderFilterOn);
5693   Standard_Integer aDiffColorsNb = aComparer.Compare();
5694   theDI << aDiffColorsNb << "\n";
5695
5696   // save image of difference
5697   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5698   {
5699     aComparer.SaveDiffImage (aDiffImagePath);
5700   }
5701
5702   return 0;
5703 }
5704
5705 //=======================================================================
5706 //function : VSelect
5707 //purpose  : Emulates different types of selection by mouse:
5708 //           1) single click selection
5709 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5710 //           3) selection with polygon having corners at
5711 //           pixel positions (x1,y1),...,(xn,yn)
5712 //           4) any of these selections with shift button pressed
5713 //=======================================================================
5714 static Standard_Integer VSelect (Draw_Interpretor& di,
5715                                  Standard_Integer argc,
5716                                  const char ** argv)
5717 {
5718   if(argc < 3)
5719   {
5720     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5721     return 1;
5722   }
5723
5724   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5725   if(myAIScontext.IsNull())
5726   {
5727     di << "use 'vinit' command before " << argv[0] << "\n";
5728     return 1;
5729   }
5730
5731   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5732   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5733   TCollection_AsciiString anArg;
5734   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5735   anArg.LowerCase();
5736   if (anArg == "-allowoverlap")
5737   {
5738     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5739       : argc == 7;
5740     if (!isValidated)
5741     {
5742       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5743       return 1;
5744     }
5745
5746     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5747     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5748     aCoordsNb -= 2;
5749   }
5750
5751   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5752   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5753   if(aCoordsNb == 2)
5754   {
5755     if(isShiftSelection)
5756       aCurrentEventManager->ShiftSelect();
5757     else
5758       aCurrentEventManager->Select();
5759   }
5760   else if(aCoordsNb == 4)
5761   {
5762     if(isShiftSelection)
5763       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5764     else
5765       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5766   }
5767   else
5768   {
5769     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
5770
5771     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
5772       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
5773
5774     if(isShiftSelection)
5775       aCurrentEventManager->ShiftSelect(aPolyline);
5776     else
5777       aCurrentEventManager->Select(aPolyline);
5778   }
5779   return 0;
5780 }
5781
5782 //=======================================================================
5783 //function : VMoveTo
5784 //purpose  : Emulates cursor movement to defined pixel position
5785 //=======================================================================
5786 static Standard_Integer VMoveTo (Draw_Interpretor& di,
5787                                 Standard_Integer argc,
5788                                 const char ** argv)
5789 {
5790   if(argc != 3)
5791   {
5792     di << "Usage : " << argv[0] << " x y\n";
5793     return 1;
5794   }
5795
5796   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5797   if(aContext.IsNull())
5798   {
5799     di << "use 'vinit' command before " << argv[0] << "\n";
5800     return 1;
5801   }
5802   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
5803   return 0;
5804 }
5805
5806 //=================================================================================================
5807 //function : VViewParams
5808 //purpose  : Gets or sets AIS View characteristics
5809 //=================================================================================================
5810 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
5811 {
5812   Handle(V3d_View) anAISView = ViewerTest::CurrentView();
5813   if (anAISView.IsNull())
5814   {
5815     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
5816     return 1;
5817   }
5818
5819   if (theArgsNb == 1)
5820   {
5821     // print all of the available view parameters
5822     Quantity_Factor anAISViewScale = anAISView->Scale();
5823
5824     Standard_Real anAISViewProjX = 0.0;
5825     Standard_Real anAISViewProjY = 0.0;
5826     Standard_Real anAISViewProjZ = 0.0;
5827     anAISView->Proj (anAISViewProjX, anAISViewProjY, anAISViewProjZ);
5828
5829     Standard_Real anAISViewUpX = 0.0;
5830     Standard_Real anAISViewUpY = 0.0;
5831     Standard_Real anAISViewUpZ = 0.0;
5832     anAISView->Up (anAISViewUpX, anAISViewUpY, anAISViewUpZ);
5833
5834     Standard_Real anAISViewAtX = 0.0;
5835     Standard_Real anAISViewAtY = 0.0;
5836     Standard_Real anAISViewAtZ = 0.0;
5837     anAISView->At (anAISViewAtX, anAISViewAtY, anAISViewAtZ);
5838
5839     Standard_Real anAISViewEyeX = 0.0;
5840     Standard_Real anAISViewEyeY = 0.0;
5841     Standard_Real anAISViewEyeZ = 0.0;
5842     anAISView->Eye (anAISViewEyeX, anAISViewEyeY, anAISViewEyeZ);
5843
5844     theDi << "Scale of current view: " << anAISViewScale << "\n";
5845     theDi << "Proj on X : " << anAISViewProjX << "; on Y: " << anAISViewProjY << "; on Z: " << anAISViewProjZ << "\n";
5846     theDi << "Up on X : " << anAISViewUpX << "; on Y: " << anAISViewUpY << "; on Z: " << anAISViewUpZ << "\n";
5847     theDi << "At on X : " << anAISViewAtX << "; on Y: " << anAISViewAtY << "; on Z: " << anAISViewAtZ << "\n";
5848     theDi << "Eye on X : " << anAISViewEyeX << "; on Y: " << anAISViewEyeY << "; on Z: " << anAISViewEyeZ << "\n";
5849     return 0;
5850   }
5851
5852   // -------------------------
5853   //  Parse options and values
5854   // -------------------------
5855
5856   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfKeysByValues;
5857   TCollection_AsciiString aParseKey;
5858   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
5859   {
5860     TCollection_AsciiString anArg (theArgVec [anArgIt]);
5861
5862     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
5863     {
5864       aParseKey = anArg;
5865       aParseKey.Remove (1);
5866       aParseKey.UpperCase();
5867       aMapOfKeysByValues.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
5868       continue;
5869     }
5870
5871     if (aParseKey.IsEmpty())
5872     {
5873       std::cout << theArgVec[0] << ": values should be passed with key.\n";
5874       std::cout << "Type help for more information.\n";
5875       return 1;
5876     }
5877
5878     aMapOfKeysByValues(aParseKey)->Append (anArg);
5879   }
5880
5881   // ---------------------------------------------
5882   //  Change or print parameters, order plays role
5883   // ---------------------------------------------
5884
5885   // Check arguments for validity
5886   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfKeysByValues);
5887   for (; aMapIt.More(); aMapIt.Next())
5888   {
5889     const TCollection_AsciiString& aKey = aMapIt.Key();
5890     const Handle(TColStd_HSequenceOfAsciiString)& aValues = aMapIt.Value();
5891
5892     if (!(aKey.IsEqual ("SCALE")  && (aValues->Length() == 1 || aValues->IsEmpty()))
5893      && !(aKey.IsEqual ("SIZE")   && (aValues->Length() == 1 || aValues->IsEmpty()))
5894      && !(aKey.IsEqual ("EYE")    && (aValues->Length() == 3 || aValues->IsEmpty()))
5895      && !(aKey.IsEqual ("AT")     && (aValues->Length() == 3 || aValues->IsEmpty()))
5896      && !(aKey.IsEqual ("UP")     && (aValues->Length() == 3 || aValues->IsEmpty()))
5897      && !(aKey.IsEqual ("PROJ")   && (aValues->Length() == 3 || aValues->IsEmpty()))
5898      && !(aKey.IsEqual ("CENTER") &&  aValues->Length() == 2))
5899     {
5900       TCollection_AsciiString aLowerKey;
5901       aLowerKey  = "-";
5902       aLowerKey += aKey;
5903       aLowerKey.LowerCase();
5904       std::cout << theArgVec[0] << ": " << aLowerKey << " is unknown option, or number of arguments is invalid.\n";
5905       std::cout << "Type help for more information.\n";
5906       return 1;
5907     }
5908   }
5909
5910   Handle(TColStd_HSequenceOfAsciiString) aValues;
5911
5912   // Change view parameters in proper order
5913   if (aMapOfKeysByValues.Find ("SCALE", aValues))
5914   {
5915     if (aValues->IsEmpty())
5916     {
5917       theDi << "Scale: " << anAISView->Scale() << "\n";
5918     }
5919     else
5920     {
5921       anAISView->SetScale (aValues->Value(1).RealValue());
5922     }
5923   }
5924   if (aMapOfKeysByValues.Find ("SIZE", aValues))
5925   {
5926     if (aValues->IsEmpty())
5927     {
5928       Standard_Real aSizeX = 0.0;
5929       Standard_Real aSizeY = 0.0;
5930       anAISView->Size (aSizeX, aSizeY);
5931       theDi << "Size X: " << aSizeX << " Y: " << aSizeY << "\n";
5932     }
5933     else
5934     {
5935       anAISView->SetSize (aValues->Value(1).RealValue());
5936     }
5937   }
5938   if (aMapOfKeysByValues.Find ("EYE", aValues))
5939   {
5940     if (aValues->IsEmpty())
5941     {
5942       Standard_Real anEyeX = 0.0;
5943       Standard_Real anEyeY = 0.0;
5944       Standard_Real anEyeZ = 0.0;
5945       anAISView->Eye (anEyeX, anEyeY, anEyeZ);
5946       theDi << "Eye X: " << anEyeX << " Y: " << anEyeY << " Z: " << anEyeZ << "\n";
5947     }
5948     else
5949     {
5950       anAISView->SetEye (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
5951     }
5952   }
5953   if (aMapOfKeysByValues.Find ("AT", aValues))
5954   {
5955     if (aValues->IsEmpty())
5956     {
5957       Standard_Real anAtX = 0.0;
5958       Standard_Real anAtY = 0.0;
5959       Standard_Real anAtZ = 0.0;
5960       anAISView->At (anAtX, anAtY, anAtZ);
5961       theDi << "At X: " << anAtX << " Y: " << anAtY << " Z: " << anAtZ << "\n";
5962     }
5963     else
5964     {
5965       anAISView->SetAt (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
5966     }
5967   }
5968   if (aMapOfKeysByValues.Find ("PROJ", aValues))
5969   {
5970     if (aValues->IsEmpty())
5971     {
5972       Standard_Real aProjX = 0.0;
5973       Standard_Real aProjY = 0.0;
5974       Standard_Real aProjZ = 0.0;
5975       anAISView->Proj (aProjX, aProjY, aProjZ);
5976       theDi << "Proj X: " << aProjX << " Y: " << aProjY << " Z: " << aProjZ << "\n";
5977     }
5978     else
5979     {
5980       anAISView->SetProj (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
5981     }
5982   }
5983   if (aMapOfKeysByValues.Find ("UP", aValues))
5984   {
5985     if (aValues->IsEmpty())
5986     {
5987       Standard_Real anUpX = 0.0;
5988       Standard_Real anUpY = 0.0;
5989       Standard_Real anUpZ = 0.0;
5990       anAISView->Up (anUpX, anUpY, anUpZ);
5991       theDi << "Up X: " << anUpX << " Y: " << anUpY << " Z: " << anUpZ << "\n";
5992     }
5993     else
5994     {
5995       anAISView->SetUp (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
5996     }
5997   }
5998   if (aMapOfKeysByValues.Find ("CENTER", aValues))
5999   {
6000     anAISView->SetCenter (aValues->Value(1).IntegerValue(), aValues->Value(2).IntegerValue());
6001   }
6002
6003   return 0;
6004 }
6005
6006 //=======================================================================
6007 //function : VChangeSelected
6008 //purpose  : Adds the shape to selection or remove one from it
6009 //=======================================================================
6010 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6011                                 Standard_Integer argc,
6012                                 const char ** argv)
6013 {
6014   if(argc != 2)
6015   {
6016     di<<"Usage : " << argv[0] << " shape \n";
6017     return 1;
6018   }
6019   //get AIS_Shape:
6020   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6021   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6022   TCollection_AsciiString aName(argv[1]);
6023   Handle(AIS_InteractiveObject) anAISObject;
6024
6025   if(!aMap.IsBound2(aName))
6026   {
6027     di<<"Use 'vdisplay' before";
6028     return 1;
6029   }
6030   else
6031   {
6032     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6033     if(anAISObject.IsNull()){
6034       di<<"No interactive object \n";
6035       return 1;
6036     }
6037
6038     aContext->AddOrRemoveSelected(anAISObject);
6039   }
6040   return 0;
6041 }
6042
6043 //=======================================================================
6044 //function : VNbSelected
6045 //purpose  : Returns number of selected objects
6046 //=======================================================================
6047 static Standard_Integer VNbSelected (Draw_Interpretor& di,
6048                                 Standard_Integer argc,
6049                                 const char ** argv)
6050 {
6051   if(argc != 1)
6052   {
6053     di << "Usage : " << argv[0] << "\n";
6054     return 1;
6055   }
6056   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6057   if(aContext.IsNull())
6058   {
6059     di << "use 'vinit' command before " << argv[0] << "\n";
6060     return 1;
6061   }
6062   di << aContext->NbSelected() << "\n";
6063   return 0;
6064 }
6065
6066 //=======================================================================
6067 //function : VPurgeDisplay
6068 //purpose  : Switches altialiasing on or off
6069 //=======================================================================
6070 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
6071                                 Standard_Integer argc,
6072                                 const char ** argv)
6073 {
6074   if (argc > 1)
6075   {
6076     di << "Usage : " << argv[0] << "\n";
6077     return 1;
6078   }
6079   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6080   if (aContext.IsNull())
6081   {
6082     di << "use 'vinit' command before " << argv[0] << "\n";
6083     return 1;
6084   }
6085   aContext->CloseAllContexts(Standard_False);
6086   di << aContext->PurgeDisplay() << "\n";
6087   return 0;
6088 }
6089
6090 //=======================================================================
6091 //function : VSetViewSize
6092 //purpose  :
6093 //=======================================================================
6094 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
6095                                 Standard_Integer argc,
6096                                 const char ** argv)
6097 {
6098   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6099   if(aContext.IsNull())
6100   {
6101     di << "use 'vinit' command before " << argv[0] << "\n";
6102     return 1;
6103   }
6104   if(argc != 2)
6105   {
6106     di<<"Usage : " << argv[0] << " Size\n";
6107     return 1;
6108   }
6109   Standard_Real aSize = Draw::Atof (argv[1]);
6110   if (aSize <= 0.)
6111   {
6112     di<<"Bad Size value  : " << aSize << "\n";
6113     return 1;
6114   }
6115
6116   Handle(V3d_View) aView = ViewerTest::CurrentView();
6117   aView->SetSize(aSize);
6118   return 0;
6119 }
6120
6121 //=======================================================================
6122 //function : VMoveView
6123 //purpose  :
6124 //=======================================================================
6125 static Standard_Integer VMoveView (Draw_Interpretor& di,
6126                                 Standard_Integer argc,
6127                                 const char ** argv)
6128 {
6129   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6130   if(aContext.IsNull())
6131   {
6132     di << "use 'vinit' command before " << argv[0] << "\n";
6133     return 1;
6134   }
6135   if(argc < 4 || argc > 5)
6136   {
6137     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
6138     return 1;
6139   }
6140   Standard_Real Dx = Draw::Atof (argv[1]);
6141   Standard_Real Dy = Draw::Atof (argv[2]);
6142   Standard_Real Dz = Draw::Atof (argv[3]);
6143   Standard_Boolean aStart = Standard_True;
6144   if (argc == 5)
6145   {
6146       aStart = (Draw::Atoi (argv[4]) > 0);
6147   }
6148
6149   Handle(V3d_View) aView = ViewerTest::CurrentView();
6150   aView->Move(Dx,Dy,Dz,aStart);
6151   return 0;
6152 }
6153
6154 //=======================================================================
6155 //function : VTranslateView
6156 //purpose  :
6157 //=======================================================================
6158 static Standard_Integer VTranslateView (Draw_Interpretor& di,
6159                                 Standard_Integer argc,
6160                                 const char ** argv)
6161 {
6162   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6163   if(aContext.IsNull())
6164   {
6165     di << "use 'vinit' command before " << argv[0] << "\n";
6166     return 1;
6167   }
6168   if(argc < 4 || argc > 5)
6169   {
6170     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
6171     return 1;
6172   }
6173   Standard_Real Dx = Draw::Atof (argv[1]);
6174   Standard_Real Dy = Draw::Atof (argv[2]);
6175   Standard_Real Dz = Draw::Atof (argv[3]);
6176   Standard_Boolean aStart = Standard_True;
6177   if (argc == 5)
6178   {
6179       aStart = (Draw::Atoi (argv[4]) > 0);
6180   }
6181
6182   Handle(V3d_View) aView = ViewerTest::CurrentView();
6183   aView->Translate(Dx,Dy,Dz,aStart);
6184   return 0;
6185 }
6186
6187 //=======================================================================
6188 //function : VTurnView
6189 //purpose  :
6190 //=======================================================================
6191 static Standard_Integer VTurnView (Draw_Interpretor& di,
6192                                 Standard_Integer argc,
6193                                 const char ** argv)
6194 {
6195   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6196   if(aContext.IsNull()) {
6197     di << "use 'vinit' command before " << argv[0] << "\n";
6198     return 1;
6199   }
6200   if(argc < 4 || argc > 5){
6201     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
6202     return 1;
6203   }
6204   Standard_Real Ax = Draw::Atof (argv[1]);
6205   Standard_Real Ay = Draw::Atof (argv[2]);
6206   Standard_Real Az = Draw::Atof (argv[3]);
6207   Standard_Boolean aStart = Standard_True;
6208   if (argc == 5)
6209   {
6210       aStart = (Draw::Atoi (argv[4]) > 0);
6211   }
6212
6213   Handle(V3d_View) aView = ViewerTest::CurrentView();
6214   aView->Turn(Ax,Ay,Az,aStart);
6215   return 0;
6216 }
6217
6218 //==============================================================================
6219 //function : VTextureEnv
6220 //purpose  : ENables or disables environment mapping
6221 //==============================================================================
6222 class OCC_TextureEnv : public Graphic3d_TextureEnv
6223 {
6224 public:
6225   OCC_TextureEnv(const Standard_CString FileName);
6226   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
6227   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
6228                             const Standard_Boolean theModulateFlag,
6229                             const Graphic3d_TypeOfTextureFilter theFilter,
6230                             const Standard_ShortReal theXScale,
6231                             const Standard_ShortReal theYScale,
6232                             const Standard_ShortReal theXShift,
6233                             const Standard_ShortReal theYShift,
6234                             const Standard_ShortReal theAngle);
6235   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
6236 };
6237 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
6238
6239 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
6240   : Graphic3d_TextureEnv(theFileName)
6241 {
6242 }
6243
6244 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
6245   : Graphic3d_TextureEnv(theTexId)
6246 {
6247 }
6248
6249 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
6250                                           const Standard_Boolean theModulateFlag,
6251                                           const Graphic3d_TypeOfTextureFilter theFilter,
6252                                           const Standard_ShortReal theXScale,
6253                                           const Standard_ShortReal theYScale,
6254                                           const Standard_ShortReal theXShift,
6255                                           const Standard_ShortReal theYShift,
6256                                           const Standard_ShortReal theAngle)
6257 {
6258   myParams->SetRepeat     (theRepeatFlag);
6259   myParams->SetModulate   (theModulateFlag);
6260   myParams->SetFilter     (theFilter);
6261   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
6262   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
6263   myParams->SetRotation   (theAngle);
6264 }
6265
6266 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
6267 {
6268   // get the active view
6269   Handle(V3d_View) aView = ViewerTest::CurrentView();
6270   if (aView.IsNull())
6271   {
6272     std::cerr << "No active view. Please call vinit.\n";
6273     return 1;
6274   }
6275
6276   // Checking the input arguments
6277   Standard_Boolean anEnableFlag = Standard_False;
6278   Standard_Boolean isOk         = theArgNb >= 2;
6279   if (isOk)
6280   {
6281     TCollection_AsciiString anEnableOpt(theArgVec[1]);
6282     anEnableFlag = anEnableOpt.IsEqual("on");
6283     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
6284   }
6285   if (anEnableFlag)
6286   {
6287     isOk = (theArgNb == 3 || theArgNb == 11);
6288     if (isOk)
6289     {
6290       TCollection_AsciiString aTextureOpt(theArgVec[2]);
6291       isOk = (!aTextureOpt.IsIntegerValue() ||
6292              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
6293
6294       if (isOk && theArgNb == 11)
6295       {
6296         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
6297                                 aModulateOpt(theArgVec[4]),
6298                                 aFilterOpt  (theArgVec[5]),
6299                                 aSScaleOpt  (theArgVec[6]),
6300                                 aTScaleOpt  (theArgVec[7]),
6301                                 aSTransOpt  (theArgVec[8]),
6302                                 aTTransOpt  (theArgVec[9]),
6303                                 anAngleOpt  (theArgVec[10]);
6304         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
6305                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
6306                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
6307                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
6308                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
6309                 anAngleOpt.IsRealValue());
6310       }
6311     }
6312   }
6313
6314   if (!isOk)
6315   {
6316     std::cerr << "Usage :" << std::endl;
6317     std::cerr << theArgVec[0] << " off" << std::endl;
6318     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;
6319     return 1;
6320   }
6321
6322   if (anEnableFlag)
6323   {
6324     TCollection_AsciiString aTextureOpt(theArgVec[2]);
6325     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
6326                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
6327                                      new OCC_TextureEnv(theArgVec[2]);
6328
6329     if (theArgNb == 11)
6330     {
6331       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
6332       aTexEnv->SetTextureParameters(
6333         aRepeatOpt.  IsEqual("repeat"),
6334         aModulateOpt.IsEqual("modulate"),
6335         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
6336                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
6337                                                                            Graphic3d_TOTF_TRILINEAR,
6338         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
6339         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
6340         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
6341         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
6342         (Standard_ShortReal)Draw::Atof(theArgVec[10])
6343         );
6344     }
6345     aView->SetTextureEnv(aTexEnv);
6346   }
6347   else // Disabling environment mapping
6348   {
6349     Handle(Graphic3d_TextureEnv) aTexture;
6350     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
6351   }
6352
6353   aView->Redraw();
6354   return 0;
6355 }
6356
6357 namespace
6358 {
6359   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
6360
6361   //! Remove registered clipping plane from all views and objects.
6362   static void removePlane (MapOfPlanes& theRegPlanes,
6363                            const TCollection_AsciiString& theName)
6364   {
6365     Handle(Graphic3d_ClipPlane) aClipPlane;
6366     if (!theRegPlanes.Find (theName, aClipPlane))
6367     {
6368       std::cout << "Warning: no such plane.\n";
6369       return;
6370     }
6371
6372     theRegPlanes.UnBind (theName);
6373     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
6374          anIObjIt.More(); anIObjIt.Next())
6375     {
6376       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
6377       aPrs->RemoveClipPlane (aClipPlane);
6378     }
6379
6380     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
6381          aViewIt.More(); aViewIt.Next())
6382     {
6383       const Handle(V3d_View)& aView = aViewIt.Key2();
6384       aView->RemoveClipPlane(aClipPlane);
6385     }
6386
6387     ViewerTest::RedrawAllViews();
6388   }
6389 }
6390
6391 //===============================================================================================
6392 //function : VClipPlane
6393 //purpose  :
6394 //===============================================================================================
6395 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6396 {
6397   // use short-cut for created clip planes map of created (or "registered by name") clip planes
6398   static MapOfPlanes aRegPlanes;
6399
6400   if (theArgsNb < 2)
6401   {
6402     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
6403     {
6404       theDi << aPlaneIter.Key() << " ";
6405     }
6406     return 0;
6407   }
6408
6409   TCollection_AsciiString aCommand (theArgVec[1]);
6410   aCommand.LowerCase();
6411   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
6412   if (anActiveView.IsNull())
6413   {
6414     std::cout << "Error: no active view.\n";
6415     return 1;
6416   }
6417
6418   // print maximum number of planes for current viewer
6419   if (aCommand == "-maxplanes"
6420    || aCommand == "maxplanes")
6421   {
6422     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
6423           << " plane slots provided by driver.\n";
6424     return 0;
6425   }
6426
6427   // create / delete plane instance
6428   if (aCommand == "-create"
6429    || aCommand == "create"
6430    || aCommand == "-delete"
6431    || aCommand == "delete"
6432    || aCommand == "-clone"
6433    || aCommand == "clone")
6434   {
6435     if (theArgsNb < 3)
6436     {
6437       std::cout << "Syntax error: plane name is required.\n";
6438       return 1;
6439     }
6440
6441     Standard_Boolean toCreate = aCommand == "-create"
6442                              || aCommand == "create";
6443     Standard_Boolean toClone  = aCommand == "-clone"
6444                              || aCommand == "clone";
6445     Standard_Boolean toDelete = aCommand == "-delete"
6446                              || aCommand == "delete";
6447     TCollection_AsciiString aPlane (theArgVec[2]);
6448
6449     if (toCreate)
6450     {
6451       if (aRegPlanes.IsBound (aPlane))
6452       {
6453         std::cout << "Warning: existing plane has been overridden.\n";
6454         toDelete = true;
6455       }
6456       else
6457       {
6458         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
6459         return 0;
6460       }
6461     }
6462     else if (toClone) // toClone
6463     {
6464       if (!aRegPlanes.IsBound (aPlane))
6465       {
6466         std::cout << "Error: no such plane.\n";
6467         return 1;
6468       }
6469       else if (theArgsNb < 4)
6470       {
6471         std::cout << "Syntax error: enter name for new plane.\n";
6472         return 1;
6473       }
6474
6475       TCollection_AsciiString aClone (theArgVec[3]);
6476       if (aRegPlanes.IsBound (aClone))
6477       {
6478         std::cout << "Error: plane name is in use.\n";
6479         return 1;
6480       }
6481
6482       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
6483
6484       aRegPlanes.Bind (aClone, aClipPlane->Clone());
6485       return 0;
6486     }
6487
6488     if (toDelete)
6489     {
6490       if (aPlane == "ALL"
6491        || aPlane == "all"
6492        || aPlane == "*")
6493       {
6494         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
6495         {
6496           aPlane = aPlaneIter.Key();
6497           removePlane (aRegPlanes, aPlane);
6498           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
6499         }
6500       }
6501       else
6502       {
6503         removePlane (aRegPlanes, aPlane);
6504       }
6505     }
6506
6507     if (toCreate)
6508     {
6509       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
6510     }
6511     return 0;
6512   }
6513
6514   // set / unset plane command
6515   if (aCommand == "set"
6516    || aCommand == "unset")
6517   {
6518     if (theArgsNb < 5)
6519     {
6520       std::cout << "Syntax error: need more arguments.\n";
6521       return 1;
6522     }
6523
6524     // redirect to new syntax
6525     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
6526     anArgVec.SetValue (1, theArgVec[0]);
6527     anArgVec.SetValue (2, theArgVec[2]);
6528     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
6529     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
6530     {
6531       anArgVec.SetValue (anIt, theArgVec[anIt]);
6532     }
6533
6534     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
6535   }
6536
6537   // change plane command
6538   TCollection_AsciiString aPlaneName;
6539   Handle(Graphic3d_ClipPlane) aClipPlane;
6540   Standard_Integer anArgIter = 0;
6541   if (aCommand == "-change"
6542    || aCommand == "change")
6543   {
6544     // old syntax support
6545     if (theArgsNb < 3)
6546     {
6547       std::cout << "Syntax error: need more arguments.\n";
6548       return 1;
6549     }
6550
6551     anArgIter  = 3;
6552     aPlaneName = theArgVec[2];
6553     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
6554     {
6555       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
6556       return 1;
6557     }
6558   }
6559   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
6560   {
6561     anArgIter  = 2;
6562     aPlaneName = theArgVec[1];
6563   }
6564   else
6565   {
6566     anArgIter  = 2;
6567     aPlaneName = theArgVec[1];
6568     aClipPlane = new Graphic3d_ClipPlane();
6569     aRegPlanes.Bind (aPlaneName, aClipPlane);
6570     theDi << "Created new plane " << aPlaneName << ".\n";
6571   }
6572
6573   if (theArgsNb - anArgIter < 1)
6574   {
6575     std::cout << "Syntax error: need more arguments.\n";
6576     return 1;
6577   }
6578
6579   for (; anArgIter < theArgsNb; ++anArgIter)
6580   {
6581     const char**     aChangeArgs   = theArgVec + anArgIter;
6582     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
6583     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
6584     aChangeArg.LowerCase();
6585
6586     Standard_Boolean toEnable = Standard_True;
6587     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
6588     {
6589       aClipPlane->SetOn (toEnable);
6590     }
6591     else if (aChangeArg == "-equation"
6592           || aChangeArg == "equation")
6593     {
6594       if (aNbChangeArgs < 5)
6595       {
6596         std::cout << "Syntax error: need more arguments.\n";
6597         return 1;
6598       }
6599
6600       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
6601       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
6602       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
6603       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
6604       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
6605       anArgIter += 4;
6606     }
6607     else if (aChangeArg == "-capping"
6608           || aChangeArg == "capping")
6609     {
6610       if (aNbChangeArgs < 2)
6611       {
6612         std::cout << "Syntax error: need more arguments.\n";
6613         return 1;
6614       }
6615
6616       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6617       {
6618         aClipPlane->SetCapping (toEnable);
6619         anArgIter += 1;
6620       }
6621       else
6622       {
6623         // just skip otherwise (old syntax)
6624       }
6625     }
6626     else if (aChangeArg == "-useobjectmaterial"
6627           || aChangeArg == "-useobjectmat"
6628           || aChangeArg == "-useobjmat"
6629           || aChangeArg == "-useobjmaterial")
6630     {
6631       if (aNbChangeArgs < 2)
6632       {
6633         std::cout << "Syntax error: need more arguments.\n";
6634         return 1;
6635       }
6636
6637       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6638       {
6639         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
6640         anArgIter += 1;
6641       }
6642     }
6643     else if (aChangeArg == "-useobjecttexture"
6644           || aChangeArg == "-useobjecttex"
6645           || aChangeArg == "-useobjtexture"
6646           || aChangeArg == "-useobjtex")
6647     {
6648       if (aNbChangeArgs < 2)
6649       {
6650         std::cout << "Syntax error: need more arguments.\n";
6651         return 1;
6652       }
6653
6654       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6655       {
6656         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
6657         anArgIter += 1;
6658       }
6659     }
6660     else if (aChangeArg == "-useobjectshader"
6661           || aChangeArg == "-useobjshader")
6662     {
6663       if (aNbChangeArgs < 2)
6664       {
6665         std::cout << "Syntax error: need more arguments.\n";
6666         return 1;
6667       }
6668
6669       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6670       {
6671         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
6672         anArgIter += 1;
6673       }
6674     }
6675     else if (aChangeArg == "-color"
6676           || aChangeArg == "color")
6677     {
6678       Quantity_Color aColor;
6679       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
6680                                                            aChangeArgs + 1,
6681                                                            aColor);
6682       if (aNbParsed == 0)
6683       {
6684         std::cout << "Syntax error: need more arguments.\n";
6685         return 1;
6686       }
6687
6688       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
6689       aMat.SetAmbientColor (aColor);
6690       aMat.SetDiffuseColor (aColor);
6691       aClipPlane->SetCappingMaterial (aMat);
6692       anArgIter += aNbParsed;
6693     }
6694     else if (aChangeArg == "-texname"
6695           || aChangeArg == "texname")
6696     {
6697       if (aNbChangeArgs < 2)
6698       {
6699         std::cout << "Syntax error: need more arguments.\n";
6700         return 1;
6701       }
6702
6703       TCollection_AsciiString aTextureName (aChangeArgs[1]);
6704       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
6705       if (!aTexture->IsDone())
6706       {
6707         aClipPlane->SetCappingTexture (NULL);
6708       }
6709       else
6710       {
6711         aTexture->EnableModulate();
6712         aTexture->EnableRepeat();
6713         aClipPlane->SetCappingTexture (aTexture);
6714       }
6715       anArgIter += 1;
6716     }
6717     else if (aChangeArg == "-texscale"
6718           || aChangeArg == "texscale")
6719     {
6720       if (aClipPlane->CappingTexture().IsNull())
6721       {
6722         std::cout << "Error: no texture is set.\n";
6723         return 1;
6724       }
6725
6726       if (aNbChangeArgs < 3)
6727       {
6728         std::cout << "Syntax error: need more arguments.\n";
6729         return 1;
6730       }
6731
6732       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
6733       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
6734       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
6735       anArgIter += 2;
6736     }
6737     else if (aChangeArg == "-texorigin"
6738           || aChangeArg == "texorigin") // texture origin
6739     {
6740       if (aClipPlane->CappingTexture().IsNull())
6741       {
6742         std::cout << "Error: no texture is set.\n";
6743         return 1;
6744       }
6745
6746       if (aNbChangeArgs < 3)
6747       {
6748         std::cout << "Syntax error: need more arguments.\n";
6749         return 1;
6750       }
6751
6752       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
6753       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
6754
6755       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
6756       anArgIter += 2;
6757     }
6758     else if (aChangeArg == "-texrotate"
6759           || aChangeArg == "texrotate") // texture rotation
6760     {
6761       if (aClipPlane->CappingTexture().IsNull())
6762       {
6763         std::cout << "Error: no texture is set.\n";
6764         return 1;
6765       }
6766
6767       if (aNbChangeArgs < 2)
6768       {
6769         std::cout << "Syntax error: need more arguments.\n";
6770         return 1;
6771       }
6772
6773       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
6774       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
6775       anArgIter += 1;
6776     }
6777     else if (aChangeArg == "-hatch"
6778           || aChangeArg == "hatch")
6779     {
6780       if (aNbChangeArgs < 2)
6781       {
6782         std::cout << "Syntax error: need more arguments.\n";
6783         return 1;
6784       }
6785
6786       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
6787       aHatchStr.LowerCase();
6788       if (aHatchStr == "on")
6789       {
6790         aClipPlane->SetCappingHatchOn();
6791       }
6792       else if (aHatchStr == "off")
6793       {
6794         aClipPlane->SetCappingHatchOff();
6795       }
6796       else
6797       {
6798         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
6799       }
6800       anArgIter += 1;
6801     }
6802     else if (aChangeArg == "-delete"
6803           || aChangeArg == "delete")
6804     {
6805       removePlane (aRegPlanes, aPlaneName);
6806       return 0;
6807     }
6808     else if (aChangeArg == "-set"
6809           || aChangeArg == "-unset")
6810     {
6811       // set / unset plane command
6812       Standard_Boolean toSet = aChangeArg == "-set";
6813       Standard_Integer anIt = 1;
6814       for (; anIt < aNbChangeArgs; ++anIt)
6815       {
6816         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
6817         if (anEntityName.IsEmpty()
6818          || anEntityName.Value (1) == '-')
6819         {
6820           break;
6821         }
6822         else if (ViewerTest_myViews.IsBound1 (anEntityName))
6823         {
6824           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
6825           if (toSet)
6826           {
6827             aView->AddClipPlane (aClipPlane);
6828           }
6829           else
6830           {
6831             aView->RemoveClipPlane (aClipPlane);
6832           }
6833           continue;
6834         }
6835         else if (GetMapOfAIS().IsBound2 (anEntityName))
6836         {
6837           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
6838           if (toSet)
6839           {
6840             aIObj->AddClipPlane (aClipPlane);
6841           }
6842           else
6843           {
6844             aIObj->RemoveClipPlane (aClipPlane);
6845           }
6846         }
6847         else
6848         {
6849           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
6850           return 1;
6851         }
6852       }
6853
6854       if (anIt == 1)
6855       {
6856         // apply to active view
6857         if (toSet)
6858         {
6859           anActiveView->AddClipPlane (aClipPlane);
6860         }
6861         else
6862         {
6863           anActiveView->RemoveClipPlane (aClipPlane);
6864         }
6865       }
6866       else
6867       {
6868         anArgIter = anArgIter + anIt - 1;
6869       }
6870     }
6871     else
6872     {
6873       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
6874       return 1;
6875     }
6876   }
6877
6878   ViewerTest::RedrawAllViews();
6879   return 0;
6880 }
6881
6882 //===============================================================================================
6883 //function : VZRange
6884 //purpose  :
6885 //===============================================================================================
6886 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6887 {
6888   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
6889
6890   if (aCurrentView.IsNull())
6891   {
6892     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
6893     return 1;
6894   }
6895
6896   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
6897
6898   if (theArgsNb < 2)
6899   {
6900     theDi << "ZNear: " << aCamera->ZNear() << "\n";
6901     theDi << "ZFar: " << aCamera->ZFar() << "\n";
6902     return 0;
6903   }
6904
6905   if (theArgsNb == 3)
6906   {
6907     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
6908     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
6909
6910     if (aNewZNear >= aNewZFar)
6911     {
6912       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
6913       return 1;
6914     }
6915
6916     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
6917     {
6918       std::cout << theArgVec[0] << ": invalid arguments: ";
6919       std::cout << "znear, zfar should be positive for perspective camera.\n";
6920       return 1;
6921     }
6922
6923     aCamera->SetZRange (aNewZNear, aNewZFar);
6924   }
6925   else
6926   {
6927     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
6928     return 1;
6929   }
6930
6931   aCurrentView->Redraw();
6932
6933   return 0;
6934 }
6935
6936 //===============================================================================================
6937 //function : VAutoZFit
6938 //purpose  :
6939 //===============================================================================================
6940 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6941 {
6942   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
6943
6944   if (aCurrentView.IsNull())
6945   {
6946     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
6947     return 1;
6948   }
6949
6950   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
6951
6952   if (theArgsNb > 3)
6953   {
6954     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
6955     return 1;
6956   }
6957
6958   if (theArgsNb < 2)
6959   {
6960     theDi << "Auto z-fit mode: \n"
6961           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
6962           << "Scale: " << aScale << "\n";
6963     return 0;
6964   }
6965
6966   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
6967
6968   if (theArgsNb >= 3)
6969   {
6970     aScale = Draw::Atoi (theArgVec[2]);
6971   }
6972
6973   aCurrentView->SetAutoZFitMode (isOn, aScale);
6974   aCurrentView->AutoZFit();
6975   aCurrentView->Redraw();
6976
6977   return 0;
6978 }
6979
6980 //! Auxiliary function to print projection type
6981 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
6982 {
6983   switch (theProjType)
6984   {
6985     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
6986     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
6987     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
6988     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
6989     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
6990   }
6991   return "UNKNOWN";
6992 }
6993
6994 //===============================================================================================
6995 //function : VCamera
6996 //purpose  :
6997 //===============================================================================================
6998 static int VCamera (Draw_Interpretor& theDI,
6999                     Standard_Integer  theArgsNb,
7000                     const char**      theArgVec)
7001 {
7002   Handle(V3d_View) aView = ViewerTest::CurrentView();
7003   if (aView.IsNull())
7004   {
7005     std::cout << "Error: no active view.\n";
7006     return 1;
7007   }
7008
7009   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7010   if (theArgsNb < 2)
7011   {
7012     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7013     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7014     theDI << "Distance:   " << aCamera->Distance() << "\n";
7015     theDI << "IOD:        " << aCamera->IOD() << "\n";
7016     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7017     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7018     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7019     return 0;
7020   }
7021
7022   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7023   {
7024     Standard_CString        anArg = theArgVec[anArgIter];
7025     TCollection_AsciiString anArgCase (anArg);
7026     anArgCase.LowerCase();
7027     if (anArgCase == "-proj"
7028      || anArgCase == "-projection"
7029      || anArgCase == "-projtype"
7030      || anArgCase == "-projectiontype")
7031     {
7032       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7033     }
7034     else if (anArgCase == "-ortho"
7035           || anArgCase == "-orthographic")
7036     {
7037       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
7038     }
7039     else if (anArgCase == "-persp"
7040           || anArgCase == "-perspective"
7041           || anArgCase == "-perspmono"
7042           || anArgCase == "-perspectivemono"
7043           || anArgCase == "-mono")
7044     {
7045       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7046     }
7047     else if (anArgCase == "-stereo"
7048           || anArgCase == "-stereoscopic"
7049           || anArgCase == "-perspstereo"
7050           || anArgCase == "-perspectivestereo")
7051     {
7052       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7053     }
7054     else if (anArgCase == "-left"
7055           || anArgCase == "-lefteye"
7056           || anArgCase == "-monoleft"
7057           || anArgCase == "-monolefteye"
7058           || anArgCase == "-perpsleft"
7059           || anArgCase == "-perpslefteye")
7060     {
7061       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
7062     }
7063     else if (anArgCase == "-right"
7064           || anArgCase == "-righteye"
7065           || anArgCase == "-monoright"
7066           || anArgCase == "-monorighteye"
7067           || anArgCase == "-perpsright")
7068     {
7069       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
7070     }
7071     else if (anArgCase == "-dist"
7072           || anArgCase == "-distance")
7073     {
7074       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7075       if (anArgValue != NULL
7076       && *anArgValue != '-')
7077       {
7078         ++anArgIter;
7079         aCamera->SetDistance (Draw::Atof (anArgValue));
7080         continue;
7081       }
7082       theDI << aCamera->Distance() << " ";
7083     }
7084     else if (anArgCase == "-iod")
7085     {
7086       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7087       if (anArgValue != NULL
7088       && *anArgValue != '-')
7089       {
7090         ++anArgIter;
7091         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
7092         continue;
7093       }
7094       theDI << aCamera->IOD() << " ";
7095     }
7096     else if (anArgCase == "-iodtype")
7097     {
7098       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
7099       TCollection_AsciiString anValueCase (anArgValue);
7100       anValueCase.LowerCase();
7101       if (anValueCase == "abs"
7102        || anValueCase == "absolute")
7103       {
7104         ++anArgIter;
7105         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
7106         continue;
7107       }
7108       else if (anValueCase == "rel"
7109             || anValueCase == "relative")
7110       {
7111         ++anArgIter;
7112         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
7113         continue;
7114       }
7115       else if (*anArgValue != '-')
7116       {
7117         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
7118         return 1;
7119       }
7120       switch (aCamera->GetIODType())
7121       {
7122         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
7123         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
7124       }
7125     }
7126     else if (anArgCase == "-zfocus")
7127     {
7128       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7129       if (anArgValue != NULL
7130       && *anArgValue != '-')
7131       {
7132         ++anArgIter;
7133         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
7134         continue;
7135       }
7136       theDI << aCamera->ZFocus() << " ";
7137     }
7138     else if (anArgCase == "-zfocustype")
7139     {
7140       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
7141       TCollection_AsciiString anValueCase (anArgValue);
7142       anValueCase.LowerCase();
7143       if (anValueCase == "abs"
7144        || anValueCase == "absolute")
7145       {
7146         ++anArgIter;
7147         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
7148         continue;
7149       }
7150       else if (anValueCase == "rel"
7151             || anValueCase == "relative")
7152       {
7153         ++anArgIter;
7154         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
7155         continue;
7156       }
7157       else if (*anArgValue != '-')
7158       {
7159         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
7160         return 1;
7161       }
7162       switch (aCamera->ZFocusType())
7163       {
7164         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
7165         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
7166       }
7167     }
7168     else if (anArgCase == "-fov"
7169           || anArgCase == "-fovy")
7170     {
7171       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7172       if (anArgValue != NULL
7173       && *anArgValue != '-')
7174       {
7175         ++anArgIter;
7176         aCamera->SetFOVy (Draw::Atof (anArgValue));
7177         continue;
7178       }
7179       theDI << aCamera->FOVy() << " ";
7180     }
7181     else
7182     {
7183       std::cout << "Error: unknown argument '" << anArg << "'\n";
7184       return 1;
7185     }
7186   }
7187
7188   aView->AutoZFit();
7189   aView->Redraw();
7190
7191   return 0;
7192 }
7193
7194 //! Parse stereo output mode
7195 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
7196                                          Graphic3d_StereoMode& theMode)
7197 {
7198   TCollection_AsciiString aFlag (theArg);
7199   aFlag.LowerCase();
7200   if (aFlag == "quadbuffer")
7201   {
7202     theMode = Graphic3d_StereoMode_QuadBuffer;
7203   }
7204   else if (aFlag == "anaglyph")
7205   {
7206     theMode = Graphic3d_StereoMode_Anaglyph;
7207   }
7208   else if (aFlag == "row"
7209         || aFlag == "rowinterlaced")
7210   {
7211     theMode = Graphic3d_StereoMode_RowInterlaced;
7212   }
7213   else if (aFlag == "col"
7214         || aFlag == "colinterlaced"
7215         || aFlag == "columninterlaced")
7216   {
7217     theMode = Graphic3d_StereoMode_ColumnInterlaced;
7218   }
7219   else if (aFlag == "chess"
7220         || aFlag == "chessboard")
7221   {
7222     theMode = Graphic3d_StereoMode_ChessBoard;
7223   }
7224   else if (aFlag == "sbs"
7225         || aFlag == "sidebyside")
7226   {
7227     theMode = Graphic3d_StereoMode_SideBySide;
7228   }
7229   else if (aFlag == "ou"
7230         || aFlag == "overunder")
7231   {
7232     theMode = Graphic3d_StereoMode_OverUnder;
7233   }
7234   else if (aFlag == "pageflip"
7235         || aFlag == "softpageflip")
7236   {
7237     theMode = Graphic3d_StereoMode_SoftPageFlip;
7238   }
7239   else
7240   {
7241     return Standard_False;
7242   }
7243   return Standard_True;
7244 }
7245
7246 //! Parse anaglyph filter
7247 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
7248                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
7249 {
7250   TCollection_AsciiString aFlag (theArg);
7251   aFlag.LowerCase();
7252   if (aFlag == "redcyansimple")
7253   {
7254     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
7255   }
7256   else if (aFlag == "redcyan"
7257         || aFlag == "redcyanoptimized")
7258   {
7259     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
7260   }
7261   else if (aFlag == "yellowbluesimple")
7262   {
7263     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
7264   }
7265   else if (aFlag == "yellowblue"
7266         || aFlag == "yellowblueoptimized")
7267   {
7268     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
7269   }
7270   else if (aFlag == "greenmagenta"
7271         || aFlag == "greenmagentasimple")
7272   {
7273     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
7274   }
7275   else
7276   {
7277     return Standard_False;
7278   }
7279   return Standard_True;
7280 }
7281
7282 //==============================================================================
7283 //function : VStereo
7284 //purpose  :
7285 //==============================================================================
7286
7287 static int VStereo (Draw_Interpretor& theDI,
7288                     Standard_Integer  theArgNb,
7289                     const char**      theArgVec)
7290 {
7291   Handle(V3d_View) aView = ViewerTest::CurrentView();
7292   if (theArgNb < 2)
7293   {
7294     if (aView.IsNull())
7295     {
7296       std::cout << "Error: no active viewer!\n";
7297       return 0;
7298     }
7299
7300     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
7301     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
7302     if (isActive)
7303     {
7304       TCollection_AsciiString aMode;
7305       switch (aView->RenderingParams().StereoMode)
7306       {
7307         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
7308         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
7309         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
7310         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
7311         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
7312         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
7313         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
7314         case Graphic3d_StereoMode_Anaglyph  :
7315           aMode = "anaglyph";
7316           switch (aView->RenderingParams().AnaglyphFilter)
7317           {
7318             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
7319             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
7320             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
7321             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
7322             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
7323             default: break;
7324           }
7325         default: break;
7326       }
7327       theDI << "Mode " << aMode << "\n";
7328     }
7329     return 0;
7330   }
7331
7332   Handle(Graphic3d_Camera) aCamera;
7333   Graphic3d_RenderingParams*   aParams   = NULL;
7334   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
7335   if (!aView.IsNull())
7336   {
7337     aParams   = &aView->ChangeRenderingParams();
7338     aMode     = aParams->StereoMode;
7339     aCamera   = aView->Camera();
7340   }
7341
7342   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7343   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
7344   {
7345     Standard_CString        anArg = theArgVec[anArgIter];
7346     TCollection_AsciiString aFlag (anArg);
7347     aFlag.LowerCase();
7348     if (anUpdateTool.parseRedrawMode (aFlag))
7349     {
7350       continue;
7351     }
7352     else if (aFlag == "0"
7353           || aFlag == "off")
7354     {
7355       if (++anArgIter < theArgNb)
7356       {
7357         std::cout << "Error: wrong number of arguments!\n";
7358         return 1;
7359       }
7360
7361       if (!aCamera.IsNull()
7362        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
7363       {
7364         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7365       }
7366       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
7367       return 0;
7368     }
7369     else if (aFlag == "1"
7370           || aFlag == "on")
7371     {
7372       if (++anArgIter < theArgNb)
7373       {
7374         std::cout << "Error: wrong number of arguments!\n";
7375         return 1;
7376       }
7377
7378       if (!aCamera.IsNull())
7379       {
7380         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7381       }
7382       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7383       return 0;
7384     }
7385     else if (aFlag == "-reverse"
7386           || aFlag == "-reversed"
7387           || aFlag == "-swap")
7388     {
7389       Standard_Boolean toEnable = Standard_True;
7390       if (++anArgIter < theArgNb
7391       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7392       {
7393         --anArgIter;
7394       }
7395       aParams->ToReverseStereo = toEnable;
7396     }
7397     else if (aFlag == "-noreverse"
7398           || aFlag == "-noswap")
7399     {
7400       Standard_Boolean toDisable = Standard_True;
7401       if (++anArgIter < theArgNb
7402       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
7403       {
7404         --anArgIter;
7405       }
7406       aParams->ToReverseStereo = !toDisable;
7407     }
7408     else if (aFlag == "-mode"
7409           || aFlag == "-stereomode")
7410     {
7411       if (++anArgIter >= theArgNb
7412       || !parseStereoMode (theArgVec[anArgIter], aMode))
7413       {
7414         std::cout << "Error: syntax error at '" << anArg << "'\n";
7415         return 1;
7416       }
7417
7418       if (aMode == Graphic3d_StereoMode_QuadBuffer)
7419       {
7420         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7421       }
7422     }
7423     else if (aFlag == "-anaglyph"
7424           || aFlag == "-anaglyphfilter")
7425     {
7426       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
7427       if (++anArgIter >= theArgNb
7428       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
7429       {
7430         std::cout << "Error: syntax error at '" << anArg << "'\n";
7431         return 1;
7432       }
7433
7434       aMode = Graphic3d_StereoMode_Anaglyph;
7435       aParams->AnaglyphFilter = aFilter;
7436     }
7437     else if (parseStereoMode (anArg, aMode)) // short syntax
7438     {
7439       if (aMode == Graphic3d_StereoMode_QuadBuffer)
7440       {
7441         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7442       }
7443     }
7444     else
7445     {
7446       std::cout << "Error: syntax error at '" << anArg << "'\n";
7447       return 1;
7448     }
7449   }
7450
7451   if (!aView.IsNull())
7452   {
7453     aParams->StereoMode = aMode;
7454     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7455   }
7456   return 0;
7457 }
7458
7459 //===============================================================================================
7460 //function : VDefaults
7461 //purpose  :
7462 //===============================================================================================
7463 static int VDefaults (Draw_Interpretor& theDi,
7464                       Standard_Integer  theArgsNb,
7465                       const char**      theArgVec)
7466 {
7467   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7468   if (aCtx.IsNull())
7469   {
7470     std::cerr << "No active viewer!\n";
7471     return 1;
7472   }
7473
7474   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
7475   if (theArgsNb < 2)
7476   {
7477     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
7478     {
7479       theDi << "DeflType:           relative\n"
7480             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
7481     }
7482     else
7483     {
7484       theDi << "DeflType:           absolute\n"
7485             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
7486     }
7487     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
7488     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
7489     return 0;
7490   }
7491
7492   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7493   {
7494     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7495     anArg.UpperCase();
7496     if (anArg == "-ABSDEFL"
7497      || anArg == "-ABSOLUTEDEFLECTION"
7498      || anArg == "-DEFL"
7499      || anArg == "-DEFLECTION")
7500     {
7501       if (++anArgIter >= theArgsNb)
7502       {
7503         std::cout << "Error: wrong syntax at " << anArg << "\n";
7504         return 1;
7505       }
7506       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
7507       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
7508     }
7509     else if (anArg == "-RELDEFL"
7510           || anArg == "-RELATIVEDEFLECTION"
7511           || anArg == "-DEVCOEFF"
7512           || anArg == "-DEVIATIONCOEFF"
7513           || anArg == "-DEVIATIONCOEFFICIENT")
7514     {
7515       if (++anArgIter >= theArgsNb)
7516       {
7517         std::cout << "Error: wrong syntax at " << anArg << "\n";
7518         return 1;
7519       }
7520       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
7521       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
7522     }
7523     else if (anArg == "-ANGDEFL"
7524           || anArg == "-ANGULARDEFL"
7525           || anArg == "-ANGULARDEFLECTION")
7526     {
7527       if (++anArgIter >= theArgsNb)
7528       {
7529         std::cout << "Error: wrong syntax at " << anArg << "\n";
7530         return 1;
7531       }
7532       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
7533       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
7534     }
7535     else if (anArg == "-AUTOTR"
7536           || anArg == "-AUTOTRIANG"
7537           || anArg == "-AUTOTRIANGULATION")
7538     {
7539       if (++anArgIter >= theArgsNb)
7540       {
7541         std::cout << "Error: wrong syntax at " << anArg << "\n";
7542         return 1;
7543       }
7544       TCollection_AsciiString aValue (theArgVec[anArgIter]);
7545       aValue.LowerCase();
7546       if (aValue == "on"
7547        || aValue == "1")
7548       {
7549         aDefParams->SetAutoTriangulation (Standard_True);
7550       }
7551       else if (aValue == "off"
7552             || aValue == "0")
7553       {
7554         aDefParams->SetAutoTriangulation (Standard_False);
7555       }
7556     }
7557     else
7558     {
7559       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
7560     }
7561   }
7562
7563   return 0;
7564 }
7565
7566 //! Auxiliary method
7567 inline void addLight (const Handle(V3d_Light)& theLightNew,
7568                       const Standard_Boolean   theIsGlobal)
7569 {
7570   if (theLightNew.IsNull())
7571   {
7572     return;
7573   }
7574
7575   if (theIsGlobal)
7576   {
7577     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
7578   }
7579   else
7580   {
7581     ViewerTest::CurrentView()->SetLightOn (theLightNew);
7582   }
7583 }
7584
7585 //! Auxiliary method
7586 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
7587 {
7588   TCollection_AsciiString anArgNextCase (theArgNext);
7589   anArgNextCase.UpperCase();
7590   if (anArgNextCase.Length() > 5
7591    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
7592   {
7593     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
7594   }
7595   else
7596   {
7597     return theArgNext.IntegerValue();
7598   }
7599 }
7600
7601 //===============================================================================================
7602 //function : VLight
7603 //purpose  :
7604 //===============================================================================================
7605 static int VLight (Draw_Interpretor& theDi,
7606                    Standard_Integer  theArgsNb,
7607                    const char**      theArgVec)
7608 {
7609   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
7610   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
7611   if (aView.IsNull()
7612    || aViewer.IsNull())
7613   {
7614     std::cerr << "No active viewer!\n";
7615     return 1;
7616   }
7617
7618   Standard_Real        anXYZ[3];
7619   Quantity_Coefficient anAtten[2];
7620   if (theArgsNb < 2)
7621   {
7622     // print lights info
7623     Standard_Integer aLightId = 0;
7624     for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightId)
7625     {
7626       Handle(V3d_Light) aLight = aView->ActiveLight();
7627       const Quantity_Color aColor = aLight->Color();
7628       theDi << "Light" << aLightId << "\n";
7629       switch (aLight->Type())
7630       {
7631         case V3d_AMBIENT:
7632         {
7633           theDi << "  Type:       Ambient\n";
7634           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7635           break;
7636         }
7637         case V3d_DIRECTIONAL:
7638         {
7639           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
7640           theDi << "  Type:       Directional\n";
7641           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7642           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7643           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
7644           if (!aLightDir.IsNull())
7645           {
7646             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7647             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7648             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
7649             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7650           }
7651           break;
7652         }
7653         case V3d_POSITIONAL:
7654         {
7655           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
7656           theDi << "  Type:       Positional\n";
7657           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7658           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7659           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
7660           if (!aLightPos.IsNull())
7661           {
7662             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7663             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7664             aLightPos->Attenuation (anAtten[0], anAtten[1]);
7665             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
7666           }
7667           break;
7668         }
7669         case V3d_SPOT:
7670         {
7671           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
7672           theDi << "  Type:       Spot\n";
7673           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7674           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7675           if (!aLightSpot.IsNull())
7676           {
7677             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7678             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7679             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
7680             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7681             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
7682             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
7683             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
7684             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
7685           }
7686           break;
7687         }
7688         default:
7689         {
7690           theDi << "  Type:       UNKNOWN\n";
7691           break;
7692         }
7693       }
7694       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
7695     }
7696   }
7697
7698   Handle(V3d_Light) aLightNew;
7699   Handle(V3d_Light) aLightOld;
7700   Standard_Boolean  isGlobal = Standard_True;
7701   Standard_Boolean  toCreate = Standard_False;
7702   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7703   {
7704     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
7705     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
7706     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
7707     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
7708     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
7709
7710     TCollection_AsciiString aName, aValue;
7711     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
7712     TCollection_AsciiString anArgCase (anArg);
7713     anArgCase.UpperCase();
7714     if (anArgCase.IsEqual ("NEW")
7715      || anArgCase.IsEqual ("ADD")
7716      || anArgCase.IsEqual ("CREATE"))
7717     {
7718       toCreate = Standard_True;
7719     }
7720     else if (anArgCase.IsEqual ("GLOB")
7721           || anArgCase.IsEqual ("GLOBAL"))
7722     {
7723       isGlobal = Standard_True;
7724     }
7725     else if (anArgCase.IsEqual ("LOC")
7726           || anArgCase.IsEqual ("LOCAL"))
7727     {
7728       isGlobal = Standard_False;
7729     }
7730     else if (anArgCase.IsEqual ("DEF")
7731           || anArgCase.IsEqual ("DEFAULTS"))
7732     {
7733       toCreate = Standard_False;
7734       aViewer->SetDefaultLights();
7735     }
7736     else if (anArgCase.IsEqual ("CLR")
7737           || anArgCase.IsEqual ("CLEAR"))
7738     {
7739       toCreate = Standard_False;
7740       aView->InitActiveLights();
7741       while (aView->MoreActiveLights())
7742       {
7743         aViewer->DelLight (aView->ActiveLight());
7744         aView->InitActiveLights();
7745       }
7746     }
7747     else if (anArgCase.IsEqual ("AMB")
7748           || anArgCase.IsEqual ("AMBIENT")
7749           || anArgCase.IsEqual ("AMBLIGHT"))
7750     {
7751       addLight (aLightNew, isGlobal);
7752       if (!toCreate)
7753       {
7754         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7755         return 1;
7756       }
7757       toCreate  = Standard_False;
7758       aLightNew = new V3d_AmbientLight (aViewer);
7759     }
7760     else if (anArgCase.IsEqual ("DIRECTIONAL")
7761           || anArgCase.IsEqual ("DIRLIGHT"))
7762     {
7763       addLight (aLightNew, isGlobal);
7764       if (!toCreate)
7765       {
7766         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7767         return 1;
7768       }
7769       toCreate  = Standard_False;
7770       aLightNew = new V3d_DirectionalLight (aViewer);
7771     }
7772     else if (anArgCase.IsEqual ("SPOT")
7773           || anArgCase.IsEqual ("SPOTLIGHT"))
7774     {
7775       addLight (aLightNew, isGlobal);
7776       if (!toCreate)
7777       {
7778         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7779         return 1;
7780       }
7781       toCreate  = Standard_False;
7782       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
7783     }
7784     else if (anArgCase.IsEqual ("POSLIGHT")
7785           || anArgCase.IsEqual ("POSITIONAL"))
7786     {
7787       addLight (aLightNew, isGlobal);
7788       if (!toCreate)
7789       {
7790         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7791         return 1;
7792       }
7793       toCreate  = Standard_False;
7794       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
7795     }
7796     else if (anArgCase.IsEqual ("CHANGE"))
7797     {
7798       addLight (aLightNew, isGlobal);
7799       aLightNew.Nullify();
7800       if (++anArgIt >= theArgsNb)
7801       {
7802         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7803         return 1;
7804       }
7805
7806       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
7807       Standard_Integer aLightIt = 0;
7808       for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
7809       {
7810         if (aLightIt == aLightId)
7811         {
7812           aLightOld = aView->ActiveLight();
7813           break;
7814         }
7815       }
7816
7817       if (aLightOld.IsNull())
7818       {
7819         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
7820         return 1;
7821       }
7822     }
7823     else if (anArgCase.IsEqual ("DEL")
7824           || anArgCase.IsEqual ("DELETE"))
7825     {
7826       Handle(V3d_Light) aLightDel;
7827       if (++anArgIt >= theArgsNb)
7828       {
7829         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7830         return 1;
7831       }
7832
7833       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
7834       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
7835       Standard_Integer aLightIt = 0;
7836       for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
7837       {
7838         aLightDel = aView->ActiveLight();
7839         if (aLightIt == aLightDelId)
7840         {
7841           break;
7842         }
7843       }
7844       if (!aLightDel.IsNull())
7845       {
7846         aViewer->DelLight (aLightDel);
7847       }
7848     }
7849     else if (anArgCase.IsEqual ("COLOR")
7850           || anArgCase.IsEqual ("COLOUR"))
7851     {
7852       if (++anArgIt >= theArgsNb)
7853       {
7854         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7855         return 1;
7856       }
7857
7858       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
7859       anArgNext.UpperCase();
7860       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
7861       if (!aLightCurr.IsNull())
7862       {
7863         aLightCurr->SetColor (aColor);
7864       }
7865     }
7866     else if (anArgCase.IsEqual ("POS")
7867           || anArgCase.IsEqual ("POSITION"))
7868     {
7869       if ((anArgIt + 3) >= theArgsNb)
7870       {
7871         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7872         return 1;
7873       }
7874
7875       anXYZ[0] = Atof (theArgVec[++anArgIt]);
7876       anXYZ[1] = Atof (theArgVec[++anArgIt]);
7877       anXYZ[2] = Atof (theArgVec[++anArgIt]);
7878       if (!aLightDir.IsNull())
7879       {
7880         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
7881       }
7882       else if (!aLightPos.IsNull())
7883       {
7884         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
7885       }
7886       else if (!aLightSpot.IsNull())
7887       {
7888         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
7889       }
7890       else
7891       {
7892         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7893         return 1;
7894       }
7895     }
7896     else if (anArgCase.IsEqual ("DIR")
7897           || anArgCase.IsEqual ("DIRECTION"))
7898     {
7899       if ((anArgIt + 3) >= theArgsNb)
7900       {
7901         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7902         return 1;
7903       }
7904
7905       anXYZ[0] = Atof (theArgVec[++anArgIt]);
7906       anXYZ[1] = Atof (theArgVec[++anArgIt]);
7907       anXYZ[2] = Atof (theArgVec[++anArgIt]);
7908       if (!aLightDir.IsNull())
7909       {
7910         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
7911       }
7912       else if (!aLightSpot.IsNull())
7913       {
7914         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
7915       }
7916       else
7917       {
7918         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7919         return 1;
7920       }
7921     }
7922     else if (anArgCase.IsEqual ("SM")
7923           || anArgCase.IsEqual ("SMOOTHNESS"))
7924     {
7925       if (++anArgIt >= theArgsNb)
7926       {
7927         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7928         return 1;
7929       }
7930
7931       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
7932
7933       if (fabs (aSmoothness) < Precision::Confusion())
7934       {
7935         aLightCurr->SetIntensity (1.f);
7936       }
7937       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
7938       {
7939         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
7940       }
7941       else
7942       {
7943         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
7944         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
7945       }
7946
7947       if (!aLightPos.IsNull())
7948       {
7949         aLightPos->SetSmoothRadius (aSmoothness);
7950       }
7951       else if (!aLightDir.IsNull())
7952       {
7953         aLightDir->SetSmoothAngle (aSmoothness);
7954       }
7955     }
7956     else if (anArgCase.IsEqual ("INT")
7957           || anArgCase.IsEqual ("INTENSITY"))
7958     {
7959       if (++anArgIt >= theArgsNb)
7960       {
7961         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7962         return 1;
7963       }
7964
7965       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
7966
7967       if (!aLightCurr.IsNull())
7968       {
7969         aLightCurr->SetIntensity (aIntensity);
7970       }
7971     }
7972     else if (anArgCase.IsEqual ("ANG")
7973           || anArgCase.IsEqual ("ANGLE"))
7974     {
7975       if (++anArgIt >= theArgsNb)
7976       {
7977         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7978         return 1;
7979       }
7980
7981       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
7982
7983       if (!aLightSpot.IsNull())
7984       {
7985         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
7986       }
7987     }
7988     else if (anArgCase.IsEqual ("CONSTATTEN")
7989           || anArgCase.IsEqual ("CONSTATTENUATION"))
7990     {
7991       if (++anArgIt >= theArgsNb)
7992       {
7993         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7994         return 1;
7995       }
7996
7997       if (!aLightPos.IsNull())
7998       {
7999         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8000         anAtten[0] = Atof (theArgVec[anArgIt]);
8001         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8002       }
8003       else if (!aLightSpot.IsNull())
8004       {
8005         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8006         anAtten[0] = Atof (theArgVec[anArgIt]);
8007         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8008       }
8009       else
8010       {
8011         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8012         return 1;
8013       }
8014     }
8015     else if (anArgCase.IsEqual ("LINATTEN")
8016           || anArgCase.IsEqual ("LINEARATTEN")
8017           || anArgCase.IsEqual ("LINEARATTENUATION"))
8018     {
8019       if (++anArgIt >= theArgsNb)
8020       {
8021         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8022         return 1;
8023       }
8024
8025       if (!aLightPos.IsNull())
8026       {
8027         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8028         anAtten[1] = Atof (theArgVec[anArgIt]);
8029         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8030       }
8031       else if (!aLightSpot.IsNull())
8032       {
8033         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8034         anAtten[1] = Atof (theArgVec[anArgIt]);
8035         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8036       }
8037       else
8038       {
8039         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8040         return 1;
8041       }
8042     }
8043     else if (anArgCase.IsEqual ("EXP")
8044           || anArgCase.IsEqual ("EXPONENT")
8045           || anArgCase.IsEqual ("SPOTEXP")
8046           || anArgCase.IsEqual ("SPOTEXPONENT"))
8047     {
8048       if (++anArgIt >= theArgsNb)
8049       {
8050         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8051         return 1;
8052       }
8053
8054       if (!aLightSpot.IsNull())
8055       {
8056         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
8057       }
8058       else
8059       {
8060         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8061         return 1;
8062       }
8063     }
8064     else if (anArgCase.IsEqual ("HEAD")
8065           || anArgCase.IsEqual ("HEADLIGHT"))
8066     {
8067       if (++anArgIt >= theArgsNb)
8068       {
8069         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8070         return 1;
8071       }
8072
8073       if (aLightAmb.IsNull()
8074        && !aLightCurr.IsNull())
8075       {
8076         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
8077       }
8078       else
8079       {
8080         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8081         return 1;
8082       }
8083     }
8084     else
8085     {
8086       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
8087     }
8088   }
8089
8090   addLight (aLightNew, isGlobal);
8091   aViewer->UpdateLights();
8092
8093   return 0;
8094 }
8095
8096 //=======================================================================
8097 //function : VRenderParams
8098 //purpose  : Enables/disables rendering features
8099 //=======================================================================
8100
8101 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
8102                                        Standard_Integer  theArgNb,
8103                                        const char**      theArgVec)
8104 {
8105   Handle(V3d_View) aView = ViewerTest::CurrentView();
8106   if (aView.IsNull())
8107   {
8108     std::cerr << "Error: no active viewer!\n";
8109     return 1;
8110   }
8111
8112   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
8113   TCollection_AsciiString aCmdName (theArgVec[0]);
8114   aCmdName.LowerCase();
8115   if (aCmdName == "vraytrace")
8116   {
8117     if (theArgNb == 1)
8118     {
8119       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
8120       return 0;
8121     }
8122     else if (theArgNb == 2)
8123     {
8124       TCollection_AsciiString aValue (theArgVec[1]);
8125       aValue.LowerCase();
8126       if (aValue == "on"
8127        || aValue == "1")
8128       {
8129         aParams.Method = Graphic3d_RM_RAYTRACING;
8130         aView->Redraw();
8131         return 0;
8132       }
8133       else if (aValue == "off"
8134             || aValue == "0")
8135       {
8136         aParams.Method = Graphic3d_RM_RASTERIZATION;
8137         aView->Redraw();
8138         return 0;
8139       }
8140       else
8141       {
8142         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
8143         return 1;
8144       }
8145     }
8146     else
8147     {
8148       std::cout << "Error: wrong number of arguments\n";
8149       return 1;
8150     }
8151   }
8152
8153   if (theArgNb < 2)
8154   {
8155     theDI << "renderMode:  ";
8156     switch (aParams.Method)
8157     {
8158       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
8159       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
8160     }
8161     theDI << "\n";
8162     theDI << "msaa:         " <<  aParams.NbMsaaSamples << "\n";
8163     theDI << "rayDepth:     " <<  aParams.RaytracingDepth                             << "\n";
8164     theDI << "fsaa:         " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
8165     theDI << "shadows:      " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
8166     theDI << "reflections:  " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
8167     theDI << "gleam:        " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
8168     theDI << "GI:           " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
8169     theDI << "blocked RNG:  " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
8170     theDI << "shadingModel: ";
8171     switch (aView->ShadingModel())
8172     {
8173       case V3d_COLOR:   theDI << "color";   break;
8174       case V3d_FLAT:    theDI << "flat";    break;
8175       case V3d_GOURAUD: theDI << "gouraud"; break;
8176       case V3d_PHONG:   theDI << "phong";   break;
8177     }
8178     theDI << "\n";
8179     return 0;
8180   }
8181
8182   Standard_Boolean toPrint = Standard_False;
8183   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8184   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8185   {
8186     Standard_CString        anArg (theArgVec[anArgIter]);
8187     TCollection_AsciiString aFlag (anArg);
8188     aFlag.LowerCase();
8189     if (anUpdateTool.parseRedrawMode (aFlag))
8190     {
8191       continue;
8192     }
8193     else if (aFlag == "-echo"
8194           || aFlag == "-print")
8195     {
8196       toPrint = Standard_True;
8197       anUpdateTool.Invalidate();
8198     }
8199     else if (aFlag == "-mode"
8200           || aFlag == "-rendermode"
8201           || aFlag == "-render_mode")
8202     {
8203       if (toPrint)
8204       {
8205         switch (aParams.Method)
8206         {
8207           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
8208           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
8209         }
8210         continue;
8211       }
8212       else
8213       {
8214         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8215         return 1;
8216       }
8217     }
8218     else if (aFlag == "-ray"
8219           || aFlag == "-raytrace")
8220     {
8221       if (toPrint)
8222       {
8223         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
8224         continue;
8225       }
8226
8227       aParams.Method = Graphic3d_RM_RAYTRACING;
8228     }
8229     else if (aFlag == "-rast"
8230           || aFlag == "-raster"
8231           || aFlag == "-rasterization")
8232     {
8233       if (toPrint)
8234       {
8235         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
8236         continue;
8237       }
8238
8239       aParams.Method = Graphic3d_RM_RASTERIZATION;
8240     }
8241     else if (aFlag == "-msaa")
8242     {
8243       if (toPrint)
8244       {
8245         theDI << aParams.NbMsaaSamples << " ";
8246         continue;
8247       }
8248       else if (++anArgIter >= theArgNb)
8249       {
8250         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8251         return 1;
8252       }
8253
8254       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
8255       if (aNbSamples < 0)
8256       {
8257         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
8258         return 1;
8259       }
8260       else
8261       {
8262         aParams.NbMsaaSamples = aNbSamples;
8263       }
8264     }
8265     else if (aFlag == "-raydepth"
8266           || aFlag == "-ray_depth")
8267     {
8268       if (toPrint)
8269       {
8270         theDI << aParams.RaytracingDepth << " ";
8271         continue;
8272       }
8273       else if (++anArgIter >= theArgNb)
8274       {
8275         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8276         return 1;
8277       }
8278
8279       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
8280
8281       // We allow RaytracingDepth be more than 10 in case of GI enabled
8282       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
8283       {
8284         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
8285         return 1;
8286       }
8287       else
8288       {
8289         aParams.RaytracingDepth = aDepth;
8290       }
8291     }
8292     else if (aFlag == "-shad"
8293           || aFlag == "-shadows")
8294     {
8295       if (toPrint)
8296       {
8297         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
8298         continue;
8299       }
8300
8301       Standard_Boolean toEnable = Standard_True;
8302       if (++anArgIter < theArgNb
8303       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8304       {
8305         --anArgIter;
8306       }
8307       aParams.IsShadowEnabled = toEnable;
8308     }
8309     else if (aFlag == "-refl"
8310           || aFlag == "-reflections")
8311     {
8312       if (toPrint)
8313       {
8314         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
8315         continue;
8316       }
8317
8318       Standard_Boolean toEnable = Standard_True;
8319       if (++anArgIter < theArgNb
8320       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8321       {
8322         --anArgIter;
8323       }
8324       aParams.IsReflectionEnabled = toEnable;
8325     }
8326     else if (aFlag == "-fsaa")
8327     {
8328       if (toPrint)
8329       {
8330         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
8331         continue;
8332       }
8333
8334       Standard_Boolean toEnable = Standard_True;
8335       if (++anArgIter < theArgNb
8336       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8337       {
8338         --anArgIter;
8339       }
8340       aParams.IsAntialiasingEnabled = toEnable;
8341     }
8342     else if (aFlag == "-gleam")
8343     {
8344       if (toPrint)
8345       {
8346         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
8347         continue;
8348       }
8349
8350       Standard_Boolean toEnable = Standard_True;
8351       if (++anArgIter < theArgNb
8352       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8353       {
8354         --anArgIter;
8355       }
8356       aParams.IsTransparentShadowEnabled = toEnable;
8357     }
8358     else if (aFlag == "-gi")
8359     {
8360       if (toPrint)
8361       {
8362         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
8363         continue;
8364       }
8365
8366       Standard_Boolean toEnable = Standard_True;
8367       if (++anArgIter < theArgNb
8368       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8369       {
8370         --anArgIter;
8371       }
8372       aParams.IsGlobalIlluminationEnabled = toEnable;
8373       if (!toEnable)
8374       {
8375         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
8376       }
8377     }
8378     else if (aFlag == "-blockedrng"
8379           || aFlag == "-brng")
8380     {
8381       if (toPrint)
8382       {
8383         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
8384         continue;
8385       }
8386
8387       Standard_Boolean toEnable = Standard_True;
8388       if (++anArgIter < theArgNb
8389         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8390       {
8391         --anArgIter;
8392       }
8393       aParams.CoherentPathTracingMode = toEnable;
8394     }
8395     else if (aFlag == "-env")
8396     {
8397       if (toPrint)
8398       {
8399         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
8400         continue;
8401       }
8402
8403       Standard_Boolean toEnable = Standard_True;
8404       if (++anArgIter < theArgNb
8405         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8406       {
8407         --anArgIter;
8408       }
8409       aParams.UseEnvironmentMapBackground = toEnable;
8410     }
8411     else if (aFlag == "-shademodel"
8412           || aFlag == "-shadingmodel"
8413           || aFlag == "-shading")
8414     {
8415       if (toPrint)
8416       {
8417         switch (aView->ShadingModel())
8418         {
8419           case V3d_COLOR:   theDI << "color ";   break;
8420           case V3d_FLAT:    theDI << "flat ";    break;
8421           case V3d_GOURAUD: theDI << "gouraud "; break;
8422           case V3d_PHONG:   theDI << "phong ";   break;
8423         }
8424         continue;
8425       }
8426
8427       if (++anArgIter >= theArgNb)
8428       {
8429         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8430       }
8431
8432       TCollection_AsciiString aMode (theArgVec[anArgIter]);
8433       aMode.LowerCase();
8434       if (aMode == "color"
8435        || aMode == "none")
8436       {
8437         aView->SetShadingModel (V3d_COLOR);
8438       }
8439       else if (aMode == "flat"
8440             || aMode == "facet")
8441       {
8442         aView->SetShadingModel (V3d_FLAT);
8443       }
8444       else if (aMode == "gouraud"
8445             || aMode == "vertex"
8446             || aMode == "vert")
8447       {
8448         aView->SetShadingModel (V3d_GOURAUD);
8449       }
8450       else if (aMode == "phong"
8451             || aMode == "fragment"
8452             || aMode == "frag"
8453             || aMode == "pixel")
8454       {
8455         aView->SetShadingModel (V3d_PHONG);
8456       }
8457       else
8458       {
8459         std::cout << "Error: unknown shading model '" << aMode << "'\n";
8460         return 1;
8461       }
8462     }
8463     else if (aFlag == "-resolution")
8464     {
8465       if (++anArgIter >= theArgNb)
8466       {
8467         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8468         return 1;
8469       }
8470
8471       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
8472       if (aResolution.IsIntegerValue())
8473       {
8474         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
8475       }
8476       else
8477       {
8478         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
8479         return 1;
8480       }
8481     }
8482     else
8483     {
8484       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
8485       return 1;
8486     }
8487   }
8488
8489   return 0;
8490 }
8491
8492 //=======================================================================
8493 //function : VProgressiveMode
8494 //purpose  :
8495 //=======================================================================
8496 #if defined(_WIN32)
8497 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
8498                                           Standard_Integer  /*theNbArgs*/,
8499                                           const char**      /*theArgs*/)
8500 {
8501   Handle(V3d_View) aView = ViewerTest::CurrentView();
8502   if (aView.IsNull())
8503   {
8504     std::cerr << "Error: no active viewer!\n";
8505     return 1;
8506   }
8507
8508   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
8509
8510   for (;;)
8511   {
8512     aView->Redraw();
8513
8514     Standard_Boolean toExit = Standard_False;
8515
8516     MSG aMsg;
8517     while (PeekMessage (&aMsg, NULL, 0, 0, PM_REMOVE))
8518     {
8519       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
8520       {
8521         toExit = Standard_True;
8522       }
8523
8524       TranslateMessage (&aMsg);
8525       DispatchMessage  (&aMsg);
8526     }
8527
8528     if (toExit)
8529     {
8530       break;
8531     }
8532   }
8533
8534   return 0;
8535 }
8536 #endif
8537
8538 //=======================================================================
8539 //function : VFrustumCulling
8540 //purpose  : enables/disables view volume's culling.
8541 //=======================================================================
8542 static int VFrustumCulling (Draw_Interpretor& theDI,
8543                             Standard_Integer  theArgNb,
8544                             const char**      theArgVec)
8545 {
8546   Handle(V3d_View) aView = ViewerTest::CurrentView();
8547   if (aView.IsNull())
8548   {
8549     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
8550     return 1;
8551   }
8552
8553   if (theArgNb < 2)
8554   {
8555     theDI << (aView->IsCullingEnabled() ? "on" : "off");
8556     return 0;
8557   }
8558   else if (theArgNb != 2)
8559   {
8560     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
8561     return 1;
8562   }
8563
8564   TCollection_AsciiString aModeStr (theArgVec[1]);
8565   aModeStr.LowerCase();
8566   Standard_Boolean toEnable = 0;
8567   if (aModeStr == "on")
8568   {
8569     toEnable = 1;
8570   }
8571   else if (aModeStr == "off")
8572   {
8573     toEnable = 0;
8574   }
8575   else
8576   {
8577     toEnable = Draw::Atoi (theArgVec[1]) != 0;
8578   }
8579
8580   aView->SetFrustumCulling (toEnable);
8581   aView->Redraw();
8582   return 0;
8583 }
8584
8585 //=======================================================================
8586 //function : VHighlightSelected
8587 //purpose  : 
8588 //=======================================================================
8589 static int VHighlightSelected (Draw_Interpretor& theDI,
8590                                Standard_Integer  theArgNb,
8591                                const char**      theArgVec)
8592 {
8593   if (ViewerTest::GetAISContext().IsNull())
8594   {
8595     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
8596     return 1;
8597   }
8598
8599   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8600
8601   if (theArgNb < 2)
8602   {
8603     theDI << (aContext->ToHilightSelected() ? "on" : "off");
8604     return 0;
8605   }
8606
8607   if (theArgNb != 2)
8608   {
8609     std::cout  << theArgVec[0] << " error : wrong number of parameters."
8610           << "Type 'help" << theArgVec[0] << "' for more information.";
8611     return 1;
8612   }
8613
8614   // Parse parameter
8615   TCollection_AsciiString aMode (theArgVec[1]);
8616   aMode.LowerCase();
8617   Standard_Boolean toEnable = Standard_False;
8618   if (aMode.IsEqual ("on"))
8619   {
8620     toEnable = Standard_True;
8621   }
8622   else if (aMode.IsEqual ("off"))
8623   {
8624     toEnable = Standard_False;
8625   }
8626   else
8627   {
8628     toEnable = Draw::Atoi (theArgVec[1]) != 0;
8629   }
8630
8631   if (toEnable != aContext->ToHilightSelected())
8632   {
8633     aContext->SetToHilightSelected (toEnable);
8634
8635     // Move cursor to null position and  back to process updating of detection
8636     // and highlighting of selected object immediatly.
8637     Standard_Integer aPixX = 0;
8638     Standard_Integer aPixY = 0;
8639     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
8640
8641     anEventManager->GetCurrentPosition (aPixX, aPixY);
8642     anEventManager->MoveTo (0, 0);
8643     anEventManager->MoveTo (aPixX, aPixY);
8644   }
8645
8646   return 0;
8647 }
8648
8649 //=======================================================================
8650 //function : VXRotate
8651 //purpose  :
8652 //=======================================================================
8653 static Standard_Integer VXRotate (Draw_Interpretor& di,
8654                                    Standard_Integer argc,
8655                                    const char ** argv)
8656 {
8657   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8658   if (aContext.IsNull())
8659   {
8660     di << argv[0] << "ERROR : use 'vinit' command before \n";
8661     return 1;
8662   }
8663   
8664   if (argc != 3)
8665   {
8666     di << "ERROR : Usage : " << argv[0] << " name angle\n";
8667     return 1;
8668   }
8669
8670   TCollection_AsciiString aName (argv[1]);
8671   Standard_Real anAngle = Draw::Atof (argv[2]);
8672
8673   // find object
8674   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
8675   Handle(AIS_InteractiveObject) anIObj;
8676   if (!aMap.IsBound2 (aName) )
8677   {
8678     di << "Use 'vdisplay' before\n";
8679     return 1;
8680   }
8681   else
8682   {
8683     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
8684
8685     gp_Trsf aTransform;
8686     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
8687     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
8688
8689     aContext->SetLocation (anIObj, aTransform);
8690     aContext->UpdateCurrentViewer();
8691   }
8692
8693   return 0;
8694 }
8695
8696 //===============================================================================================
8697 //class   : ViewerTest_AISManipulator
8698 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
8699 //===============================================================================================
8700 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
8701
8702 class ViewerTest_AISManipulator : public AIS_Manipulator
8703 {
8704 public:
8705
8706   ViewerTest_AISManipulator() : AIS_Manipulator()
8707   {
8708     GetMapOfAISManipulators().Add (this);
8709   }
8710
8711   virtual ~ViewerTest_AISManipulator()
8712   {
8713     GetMapOfAISManipulators().Remove (this);
8714   }
8715
8716   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
8717 };
8718
8719 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
8720 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
8721
8722 //===============================================================================================
8723 //function : VManipulator
8724 //purpose  :
8725 //===============================================================================================
8726 static int VManipulator (Draw_Interpretor& theDi,
8727                          Standard_Integer  theArgsNb,
8728                          const char**      theArgVec)
8729 {
8730   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8731   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8732   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
8733   if (aView.IsNull()
8734    || aViewer.IsNull())
8735   {
8736     std::cerr << "No active viewer!\n";
8737     return 1;
8738   }
8739
8740   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
8741   Standard_Integer anArgIter = 1;
8742   for (; anArgIter < theArgsNb; ++anArgIter)
8743   {
8744     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
8745   }
8746
8747   ViewerTest_CmdParser aCmd;
8748   aCmd.AddDescription ("Manages manipulator for interactive objects:");
8749   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
8750   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
8751   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
8752   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
8753   aCmd.AddOption ("detach",         "...       - detach manipulator");
8754
8755   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
8756   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
8757   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
8758
8759   aCmd.AddOption ("move",   "... x y z - move object");
8760   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
8761   aCmd.AddOption ("scale",  "... factor - scale object");
8762
8763   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
8764   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
8765   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
8766   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
8767   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
8768   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
8769   aCmd.AddOption ("size",              "... size - set size of manipulator");
8770   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
8771
8772   aCmd.Parse (theArgsNb, theArgVec);
8773
8774   if (aCmd.HasOption ("help"))
8775   {
8776     theDi.PrintHelp (theArgVec[0]);
8777     return 0;
8778   }
8779
8780   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
8781
8782   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
8783
8784   if (aName.IsEmpty())
8785   {
8786     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
8787     return 1;
8788   }
8789
8790   // ----------------------------------
8791   // detach existing manipulator object
8792   // ----------------------------------
8793
8794   if (aCmd.HasOption ("detach"))
8795   {
8796     if (!aMapAIS.IsBound2 (aName))
8797     {
8798       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
8799       return 1;
8800     }
8801
8802     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
8803     if (aManipulator.IsNull())
8804     {
8805       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
8806       return 1;
8807     }
8808
8809     aManipulator->Detach();
8810     aMapAIS.UnBind2 (aName);
8811     ViewerTest::GetAISContext()->Remove (aManipulator);
8812
8813     return 0;
8814   }
8815
8816   // -----------------------------------------------
8817   // find or create manipulator if it does not exist
8818   // -----------------------------------------------
8819
8820   Handle(AIS_Manipulator) aManipulator;
8821   if (!aMapAIS.IsBound2 (aName))
8822   {
8823     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
8824
8825     aManipulator = new ViewerTest_AISManipulator();
8826     aMapAIS.Bind (aManipulator, aName);
8827   }
8828   else
8829   {
8830     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
8831     if (aManipulator.IsNull())
8832     {
8833       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
8834       return 1;
8835     }
8836   }
8837
8838   // -----------------------------------------
8839   // change properties of manipulator instance
8840   // -----------------------------------------
8841
8842   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
8843   {
8844     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
8845   }
8846   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
8847   {
8848     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
8849   }
8850   if (aCmd.HasOption ("followRotation", 1, Standard_True))
8851   {
8852     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
8853   }
8854   if (aCmd.HasOption ("gap", 1, Standard_True))
8855   {
8856     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
8857   }
8858   if (aCmd.HasOption ("part", 3, Standard_True))
8859   {
8860     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
8861     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
8862     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
8863     if (aMode < 1 || aMode > 3)
8864     {
8865       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
8866       return 1;
8867     }
8868
8869     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
8870   }
8871   if (aCmd.HasOption ("pos", 3, Standard_True))
8872   {
8873     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
8874     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
8875     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
8876
8877     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
8878   }
8879   if (aCmd.HasOption ("size", 1, Standard_True))
8880   {
8881     aManipulator->SetSize (aCmd.ArgFloat ("size"));
8882   }
8883   if (aCmd.HasOption ("zoomable", 1, Standard_True))
8884   {
8885     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
8886
8887     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
8888     {
8889       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
8890       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
8891     }
8892   }
8893
8894   // ---------------------------------------------------
8895   // attach, detach or access manipulator from an object
8896   // ---------------------------------------------------
8897
8898   if (aCmd.HasOption ("attach"))
8899   {
8900     // Find an object and attach manipulator to it
8901     if (!aCmd.HasOption ("attach", 1, Standard_True))
8902     {
8903       return 1;
8904     }
8905
8906     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
8907     if (!aMapAIS.IsBound2 (anObjName))
8908     {
8909       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
8910       return 1;
8911     }
8912
8913     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
8914     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
8915     for (; anIt.More(); anIt.Next())
8916     {
8917       if (anIt.Value()->IsAttached()
8918        && anIt.Value()->Object() == anObject)
8919       {
8920         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
8921         return 1;
8922       }
8923     }
8924
8925     AIS_Manipulator::OptionsForAttach anOptions;
8926     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
8927     {
8928       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
8929     }
8930     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
8931     {
8932       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
8933     }
8934     if (aCmd.HasOption ("enableModes", 1, Standard_True))
8935     {
8936       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
8937     }
8938
8939     aManipulator->Attach (anObject, anOptions);
8940   }
8941
8942   // --------------------------------------
8943   // apply transformation using manipulator
8944   // --------------------------------------
8945
8946   if (aCmd.HasOption ("startTransform", 2, Standard_True))
8947   {
8948     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
8949   }
8950   if (aCmd.HasOption ("transform", 2, Standard_True))
8951   {
8952     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
8953   }
8954   if (aCmd.HasOption ("stopTransform"))
8955   {
8956     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
8957
8958     aManipulator->StopTransform (toApply);
8959   }
8960
8961   gp_Trsf aT;
8962   if (aCmd.HasOption ("move", 3, Standard_True))
8963   {
8964     aT.SetTranslationPart (aCmd.ArgVec ("move"));
8965   }
8966   if (aCmd.HasOption ("rotate", 7, Standard_True))
8967   {
8968     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
8969   }
8970   if (aCmd.HasOption ("scale", 1))
8971   {
8972     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
8973   }
8974
8975   if (aT.Form() != gp_Identity)
8976   {
8977     aManipulator->Transform (aT);
8978   }
8979
8980   ViewerTest::GetAISContext()->Redisplay (aManipulator);
8981
8982   return 0;
8983 }
8984
8985 //=======================================================================
8986 //function : ViewerCommands
8987 //purpose  :
8988 //=======================================================================
8989
8990 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
8991 {
8992
8993   const char *group = "ZeViewer";
8994   theCommands.Add("vinit",
8995 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
8996     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
8997 #else
8998     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
8999 #endif
9000     " - Creates new View window with specified name view_name.\n"
9001     "By default the new view is created in the viewer and in"
9002     " graphic driver shared with active view.\n"
9003     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
9004     "If driverName isn't specified the driver will be shared with active view.\n"
9005     "If viewerName isn't specified the viewer will be shared with active view.\n"
9006 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
9007     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
9008     "is used in creation of graphic driver\n"
9009 #endif
9010     " - l, t: pixel position of left top corner of the window\n"
9011     " - w,h: width and heigth of window respectively.\n"
9012     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
9013     __FILE__,VInit,group);
9014   theCommands.Add("vclose" ,
9015     "[view_id [keep_context=0|1]]\n"
9016     "or vclose ALL - to remove all created views\n"
9017     " - removes view(viewer window) defined by its view_id.\n"
9018     " - keep_context: by default 0; if 1 and the last view is deleted"
9019     " the current context is not removed.",
9020     __FILE__,VClose,group);
9021   theCommands.Add("vactivate" ,
9022     "view_id"
9023     " - activates view(viewer window) defined by its view_id",
9024     __FILE__,VActivate,group);
9025   theCommands.Add("vviewlist",
9026     "vviewlist [format={tree, long}]"
9027     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
9028     " - format: format of result output, if tree the output is a tree view;"
9029     "otherwise it's a list of full view names. By default format = tree",
9030     __FILE__,VViewList,group);
9031   theCommands.Add("vhelp" ,
9032     "vhelp            : display help on the viewer commands",
9033     __FILE__,VHelp,group);
9034   theCommands.Add("vtop" ,
9035     "vtop or <T>      : Top view. Orientation +X+Y" ,
9036     __FILE__,VTop,group);
9037   theCommands.Add("vbottom" ,
9038     "vbottom          : Bottom view. Orientation +X-Y" ,
9039     __FILE__,VBottom,group);
9040   theCommands.Add("vleft" ,
9041     "vleft            : Left view. Orientation -Y+Z" ,
9042     __FILE__,VLeft,group);
9043   theCommands.Add("vright" ,
9044     "vright           : Right view. Orientation +Y+Z" ,
9045     __FILE__,VRight,group);
9046   theCommands.Add("vaxo" ,
9047     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
9048     __FILE__,VAxo,group);
9049   theCommands.Add("vfront" ,
9050     "vfront           : Front view. Orientation +X+Z" ,
9051     __FILE__,VFront,group);
9052   theCommands.Add("vback" ,
9053     "vback            : Back view. Orientation -X+Z" ,
9054     __FILE__,VBack,group);
9055   theCommands.Add("vpick" ,
9056     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
9057     VPick,group);
9058   theCommands.Add("vfit"    ,
9059     "vfit or <F> [-selected]"
9060     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
9061     __FILE__,VFit,group);
9062   theCommands.Add ("vfitarea",
9063     "vfitarea x1 y1 x2 y2"
9064     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
9065     "\n\t\t: Fit view to show area located between two points"
9066     "\n\t\t: given in world 2D or 3D corrdinates.",
9067     __FILE__, VFitArea, group);
9068   theCommands.Add ("vzfit", "vzfit [scale]\n"
9069     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
9070     "   \"scale\" - specifies factor to scale computed z range.\n",
9071     __FILE__, VZFit, group);
9072   theCommands.Add("vrepaint",
9073     "vrepaint        : vrepaint, force redraw",
9074     __FILE__,VRepaint,group);
9075   theCommands.Add("vclear",
9076     "vclear          : vclear"
9077     "\n\t\t: remove all the object from the viewer",
9078     __FILE__,VClear,group);
9079   theCommands.Add("vsetbg",
9080     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
9081     __FILE__,VSetBg,group);
9082   theCommands.Add("vsetbgmode",
9083     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
9084     __FILE__,VSetBgMode,group);
9085   theCommands.Add("vsetgradientbg",
9086     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
9087     __FILE__,VSetGradientBg,group);
9088   theCommands.Add("vsetgrbgmode",
9089     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
9090     __FILE__,VSetGradientBgMode,group);
9091   theCommands.Add("vsetcolorbg",
9092     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
9093     __FILE__,VSetColorBg,group);
9094   theCommands.Add("vsetdefaultbg",
9095     "vsetdefaultbg r g b\n"
9096     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
9097     "\n\t\t: Set default viewer background fill color (flat/gradient).",
9098     __FILE__,VSetDefaultBg,group);
9099   theCommands.Add("vscale",
9100     "vscale          : vscale X Y Z",
9101     __FILE__,VScale,group);
9102   theCommands.Add("vzbufftrihedron",
9103             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
9104     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
9105     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
9106     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
9107     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
9108     "\n\t\t: Displays a trihedron",
9109     __FILE__,VZBuffTrihedron,group);
9110   theCommands.Add("vrotate",
9111     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
9112     "\n                : Option -mouseStart starts rotation according to the mouse position"
9113     "\n                : Option -mouseMove continues rotation with angle computed"
9114     "\n                : from last and new mouse position."
9115     "\n                : vrotate AX AY AZ [X Y Z]",
9116     __FILE__,VRotate,group);
9117   theCommands.Add("vzoom",
9118     "vzoom           : vzoom coef",
9119     __FILE__,VZoom,group);
9120   theCommands.Add("vpan",
9121     "vpan            : vpan dx dy",
9122     __FILE__,VPan,group);
9123   theCommands.Add("vexport",
9124     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
9125     " : exports the view to a vector file of a given format"
9126     " : notice that EMF format requires patched gl2ps",
9127     __FILE__,VExport,group);
9128   theCommands.Add("vcolorscale",
9129     "vcolorscale     : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16  -textpos "
9130     "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n"
9131     "-demo/-demoversion draw a demoversion of color scale.\n"
9132     "-show/display display color scale.\n"
9133     "-hide/erase erase color scale.\n"
9134     "Please note that -show/-hide option must be the first argument!\n"
9135     "-color Index R G B: set color for indexed interval\n"
9136     "-color Index ColorName: set color for indexed interval\n"
9137     "-colors R G B R G B ...: set colors for all intervals\n"
9138     "-colors ColorName1 ColorName2 ...: set colors for all intervals\n"
9139     "-colors supports both color names and rgb values in one call\n"
9140     "-label Index Text: set label for indexed interval\n"
9141     "-labels Text Text Text ...: set labels for all intervals\n"
9142     "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n"
9143     "Available text positions: left, right, center, none;\n",
9144     __FILE__,VColorScale,group);
9145   theCommands.Add("vgraduatedtrihedron",
9146     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
9147     "\t[-namefont Name] [-valuesfont Name]\n"
9148     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
9149     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
9150     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
9151     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
9152     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
9153     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
9154     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
9155     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
9156     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
9157     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
9158     " - Displays or erases graduated trihedron"
9159     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
9160     " - namefont - font of axes names. Default: Arial\n"
9161     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
9162     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
9163     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
9164     " - valuesfont - font of axes values. Default: Arial\n"
9165     " - xcolor, ycolor, zcolor - color of axis and values\n"
9166     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
9167     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
9168     __FILE__,VGraduatedTrihedron,group);
9169   theCommands.Add("vtile" ,
9170             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
9171     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
9172     "\n\t\t:  -totalSize the size of virtual bigger viewport"
9173     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
9174     "\n\t\t:  -lowerLeft tile offset as lower left corner"
9175     "\n\t\t:  -upperLeft tile offset as upper left corner",
9176     __FILE__, VTile, group);
9177   theCommands.Add("vzlayer",
9178     "vzlayer add/del/get/settings/enable/disable [id]\n"
9179     " add - add new z layer to viewer and print its id\n"
9180     " del - del z layer by its id\n"
9181     " get - print sequence of z layers in increasing order of their overlay level\n"
9182     " settings - print status of z layer settings\n"
9183     " enable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    enables given setting for the z layer\n"
9184     " enable (p[ositive]offset/n[egative]offset) \n    enables given setting for the z layer\n"
9185     " enable textureenv \n    enables environment texture mapping\n"
9186     " disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    disables given setting for the z layer\n"
9187     " disable textureenv \n    disables environment texture mapping\n"
9188     "\nWhere id is the layer identificator\n"
9189     "\nExamples:\n"
9190     "   vzlayer add\n"
9191     "   vzlayer enable poffset 1\n"
9192     "   vzlayer disable depthtest 1\n"
9193     "   vzlayer del 1\n",
9194     __FILE__,VZLayer,group);
9195   theCommands.Add("vlayerline",
9196     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
9197     __FILE__,VLayerLine,group);
9198   theCommands.Add ("vgrid",
9199     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
9200     " : Mode - rectangular or circular"
9201     " : Type - lines or points",
9202     __FILE__, VGrid, group);
9203   theCommands.Add ("vpriviledgedplane",
9204     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
9205     "\n\t\t:   Ox, Oy, Oz - plane origin"
9206     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
9207     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
9208     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
9209     __FILE__, VPriviledgedPlane, group);
9210   theCommands.Add ("vconvert",
9211     "vconvert v [Mode={window|view}]"
9212     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
9213     "\n\t\t: vconvert x y z [Mode={window|grid}]"
9214     "\n\t\t:   window - convert to window coordinates, pixels"
9215     "\n\t\t:   view   - convert to view projection plane"
9216     "\n\t\t:   grid   - convert to model coordinates, given on grid"
9217     "\n\t\t:   ray    - convert projection ray to model coordiantes"
9218     "\n\t\t: - vconvert v window : convert view to window;"
9219     "\n\t\t: - vconvert v view   : convert window to view;"
9220     "\n\t\t: - vconvert x y window : convert view to window;"
9221     "\n\t\t: - vconvert x y view : convert window to view;"
9222     "\n\t\t: - vconvert x y : convert window to model;"
9223     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
9224     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
9225     "\n\t\t: - vconvert x y z window : convert model to window;"
9226     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
9227     "\n\t\t: Converts the given coordinates to window/view/model space.",
9228     __FILE__, VConvert, group);
9229   theCommands.Add ("vfps",
9230     "vfps [framesNb=100] : estimate average frame rate for active view",
9231     __FILE__, VFps, group);
9232   theCommands.Add ("vgldebug",
9233             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
9234     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
9235     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
9236     "\n\t\t: Debug context can be requested only on Windows"
9237     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
9238     "\n\t\t:  -sync     - request synchronized debug GL context"
9239     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
9240     "\n\t\t:              which are suppressed by default,"
9241     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
9242     "\n\t\t:              which are suppressed by default",
9243     __FILE__, VGlDebug, group);
9244   theCommands.Add ("vvbo",
9245     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
9246     __FILE__, VVbo, group);
9247   theCommands.Add ("vstereo",
9248             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
9249     "\n\t\t:         [-anaglyph Filter]"
9250     "\n\t\t: Control stereo output mode. Available modes for -mode:"
9251     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
9252     "\n\t\t:                     requires driver support."
9253     "\n\t\t:                     Should be called BEFORE vinit!"
9254     "\n\t\t:  anaglyph         - Anaglyph glasses"
9255     "\n\t\t:  rowInterlaced    - row-interlaced display"
9256     "\n\t\t:  columnInterlaced - column-interlaced display"
9257     "\n\t\t:  chessBoard       - chess-board output"
9258     "\n\t\t:  sideBySide       - horizontal pair"
9259     "\n\t\t:  overUnder        - vertical   pair"
9260     "\n\t\t: Available Anaglyph filters for -anaglyph:"
9261     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
9262     "\n\t\t:  greenMagentaSimple",
9263     __FILE__, VStereo, group);
9264   theCommands.Add ("vcaps",
9265             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
9266     "\n\t\t:       [-compatibleProfile {0|1}]"
9267     "\n\t\t:       [-vsync {0|1}]"
9268     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
9269     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
9270     "\n\t\t: Modify particular graphic driver options:"
9271     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
9272     "\n\t\t:             built-in GLSL programs"
9273     "\n\t\t:            (requires compatible profile)"
9274     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
9275     "\n\t\t:             arrays to GPU memory)"
9276     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
9277     "\n\t\t:  vsync    - switch VSync on or off"
9278     "\n\t\t: Context creation options:"
9279     "\n\t\t:  softMode          - software OpenGL implementation"
9280     "\n\t\t:  compatibleProfile - backward-compatible profile"
9281     "\n\t\t:  quadbuffer        - QuadBuffer"
9282     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
9283     "\n\t\t: rendering paths producing the same visual result when"
9284     "\n\t\t: possible."
9285     "\n\t\t: Command is intended for testing old hardware compatibility.",
9286     __FILE__, VCaps, group);
9287   theCommands.Add ("vmemgpu",
9288     "vmemgpu [f]: print system-dependent GPU memory information if available;"
9289     " with f option returns free memory in bytes",
9290     __FILE__, VMemGpu, group);
9291   theCommands.Add ("vreadpixel",
9292     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
9293     " : Read pixel value for active view",
9294     __FILE__, VReadPixel, group);
9295   theCommands.Add("diffimage",
9296     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
9297     __FILE__, VDiffImage, group);
9298   theCommands.Add ("vselect",
9299     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
9300     "- emulates different types of selection:\n"
9301     "- 1) single click selection\n"
9302     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
9303     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
9304     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
9305     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
9306     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
9307     " (partial inclusion - overlap - is not allowed by default)\n"
9308     "- 5) any of these selections with shift button pressed",
9309     __FILE__, VSelect, group);
9310   theCommands.Add ("vmoveto",
9311     "vmoveto x y"
9312     "- emulates cursor movement to pixel postion (x,y)",
9313     __FILE__, VMoveTo, group);
9314   theCommands.Add ("vviewparams", "vviewparams usage:\n"
9315     "- vviewparams\n"
9316     "- vviewparams [-scale [s]] [-eye [x y z]] [-at [x y z]] [-up [x y z]]\n"
9317     "              [-proj [x y z]] [-center x y] [-size sx]\n"
9318     "-   Gets or sets current view parameters.\n"
9319     "-   If called without arguments, all view parameters are printed.\n"
9320     "-   The options are:\n"
9321     "      -scale [s]    : prints or sets viewport relative scale.\n"
9322     "      -eye [x y z]  : prints or sets eye location.\n"
9323     "      -at [x y z]   : prints or sets center of look.\n"
9324     "      -up [x y z]   : prints or sets direction of up vector.\n"
9325     "      -proj [x y z] : prints or sets direction of look.\n"
9326     "      -center x y   : sets location of center of the screen in pixels.\n"
9327     "      -size [sx]    : prints viewport projection width and height sizes\n"
9328     "                    : or changes the size of its maximum dimension.\n",
9329     __FILE__, VViewParams, group);
9330   theCommands.Add("vchangeselected",
9331     "vchangeselected shape"
9332     "- adds to shape to selection or remove one from it",
9333                 __FILE__, VChangeSelected, group);
9334   theCommands.Add ("vnbselected",
9335     "vnbselected"
9336     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
9337   theCommands.Add ("vcamera",
9338               "vcamera [-ortho] [-projtype]"
9339       "\n\t\t:         [-persp]"
9340       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
9341       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
9342       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
9343       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
9344       "\n\t\t: Manage camera parameters."
9345       "\n\t\t: Prints current value when option called without argument."
9346       "\n\t\t: Orthographic camera:"
9347       "\n\t\t:   -ortho      activate orthographic projection"
9348       "\n\t\t: Perspective camera:"
9349       "\n\t\t:   -persp      activate perspective  projection (mono)"
9350       "\n\t\t:   -fovy       field of view in y axis, in degrees"
9351       "\n\t\t:   -distance   distance of eye from camera center"
9352       "\n\t\t: Stereoscopic camera:"
9353       "\n\t\t:   -stereo     perspective  projection (stereo)"
9354       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
9355       "\n\t\t:   -rightEye   perspective  projection (right eye)"
9356       "\n\t\t:   -iod        intraocular distance value"
9357       "\n\t\t:   -iodType    distance type, absolute or relative"
9358       "\n\t\t:   -zfocus     stereographic focus value"
9359       "\n\t\t:   -zfocusType focus type, absolute or relative",
9360     __FILE__, VCamera, group);
9361   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
9362     "- vautozfit [on={1|0}] [scale]\n"
9363     "    Prints or changes parameters of automatic z-fit mode:\n"
9364     "   \"on\" - turns automatic z-fit on or off\n"
9365     "   \"scale\" - specifies factor to scale computed z range.\n",
9366     __FILE__, VAutoZFit, group);
9367   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
9368     "   vzrange                - without parameters shows current values\n"
9369     "   vzrange [znear] [zfar] - applies provided values to view",
9370     __FILE__,VZRange, group);
9371   theCommands.Add ("vpurgedisplay",
9372     "vpurgedisplay"
9373     "- removes structures which don't belong to objects displayed in neutral point",
9374     __FILE__, VPurgeDisplay, group);
9375   theCommands.Add("vsetviewsize",
9376     "vsetviewsize size",
9377     __FILE__,VSetViewSize,group);
9378   theCommands.Add("vmoveview",
9379     "vmoveview Dx Dy Dz [Start = 1|0]",
9380     __FILE__,VMoveView,group);
9381   theCommands.Add("vtranslateview",
9382     "vtranslateview Dx Dy Dz [Start = 1|0)]",
9383     __FILE__,VTranslateView,group);
9384   theCommands.Add("vturnview",
9385     "vturnview Ax Ay Az [Start = 1|0]",
9386     __FILE__,VTurnView,group);
9387   theCommands.Add("vtextureenv",
9388     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
9389     "or user-defined file and optionally applying texture mapping parameters\n"
9390     "                  Usage:\n"
9391     "                  vtextureenv off - disables environment mapping\n"
9392     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
9393     "                              std_texture = (0..7)\n"
9394     "                              rep         = {clamp|repeat}\n"
9395     "                              mod         = {decal|modulate}\n"
9396     "                              flt         = {nearest|bilinear|trilinear}\n"
9397     "                              ss, st      - scale factors for s and t texture coordinates\n"
9398     "                              ts, tt      - translation for s and t texture coordinates\n"
9399     "                              rot         - texture rotation angle in degrees",
9400     __FILE__, VTextureEnv, group);
9401   theCommands.Add("vhlr" ,
9402     "is_enabled={on|off} [show_hidden={1|0}]"
9403     " - Hidden line removal algorithm:"
9404     " - is_enabled: if is on HLR algorithm is applied\n"
9405     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
9406     __FILE__,VHLR,group);
9407   theCommands.Add("vhlrtype" ,
9408     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
9409     " - Changes the type of HLR algorithm using for shapes."
9410     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
9411     "   if equals to polyalgo, polygonal HLR algorithm is applied."
9412     "If shapes are not given HLR algoithm of given type is applied"
9413     " to all shapes in the view\n",
9414     __FILE__,VHLRType,group);
9415   theCommands.Add("vclipplane",
9416               "vclipplane planeName [{0|1}]"
9417       "\n\t\t:   [-equation A B C D]"
9418       "\n\t\t:   [-set|-unset [objects|views]]"
9419       "\n\t\t:   [-maxPlanes]"
9420       "\n\t\t:   [-capping {0|1}]"
9421       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
9422       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
9423       "\n\t\t:       [-texRotate Angle]"
9424       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
9425       "\n\t\t:       [-useObjShader {0|1}]"
9426       "\n\t\t: Clipping planes management:"
9427       "\n\t\t:   -maxPlanes   print plane limit for view"
9428       "\n\t\t:   -delete      delete plane with given name"
9429       "\n\t\t:   {off|on|0|1} turn clipping on/off"
9430       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
9431       "\n\t\t:                applied to active View when list is omitted"
9432       "\n\t\t:   -equation A B C D change plane equation"
9433       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
9434       "\n\t\t: Capping options:"
9435       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
9436       "\n\t\t:   -color R G B          set capping color"
9437       "\n\t\t:   -texName Texture      set capping texture"
9438       "\n\t\t:   -texScale SX SY       set capping tex scale"
9439       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
9440       "\n\t\t:   -texRotate Angle      set capping tex rotation"
9441       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
9442       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
9443       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
9444       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
9445       __FILE__, VClipPlane, group);
9446   theCommands.Add("vdefaults",
9447                "vdefaults [-absDefl value]"
9448        "\n\t\t:           [-devCoeff value]"
9449        "\n\t\t:           [-angDefl value]"
9450        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
9451     , __FILE__, VDefaults, group);
9452   theCommands.Add("vlight",
9453     "tool to manage light sources, without arguments shows list of lights."
9454     "\n    Main commands: "
9455     "\n      'clear' to clear lights"
9456     "\n      '{def}aults' to load deafault lights"
9457     "\n      'add' (or 'new') <type> to add any light source"
9458     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
9459     "\n      'change' <lightId> to edit light source with specified lightId"
9460     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
9461     "\n        {pos}ition X Y Z"
9462     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
9463     "\n        color colorName"
9464     "\n        {head}light 0|1"
9465     "\n        {sm}oothness value"
9466     "\n        {int}ensity value"
9467     "\n        {constAtten}uation value"
9468     "\n        {linearAtten}uation value"
9469     "\n        angle angleDeg"
9470     "\n        {spotexp}onent value"
9471     "\n        local|global"
9472     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
9473     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
9474     __FILE__, VLight, group);
9475   theCommands.Add("vraytrace",
9476             "vraytrace [0|1]"
9477     "\n\t\t: Turns on/off ray-tracing renderer."
9478     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
9479     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
9480     __FILE__, VRenderParams, group);
9481   theCommands.Add("vrenderparams",
9482     "\n    Manages rendering parameters: "
9483     "\n      '-raster'               Disables GPU ray-tracing"
9484     "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
9485     "\n      '-rayTrace'             Enables  GPU ray-tracing"
9486     "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
9487     "\n      '-shadows      on|off'  Enables/disables shadows rendering"
9488     "\n      '-reflections  on|off'  Enables/disables specular reflections"
9489     "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
9490     "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
9491     "\n      '-gi           on|off'  Enables/disables global illumination effects"
9492     "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
9493     "\n      '-env          on|off'  Enables/disables environment map background"
9494     "\n      '-shadingModel model'   Controls shading model from enumeration"
9495     "\n                              color, flat, gouraud, phong"
9496     "\n      '-resolution   value'   Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
9497     "\n    Unlike vcaps, these parameters dramatically change visual properties."
9498     "\n    Command is intended to control presentation quality depending on"
9499     "\n    hardware capabilities and performance.",
9500     __FILE__, VRenderParams, group);
9501   theCommands.Add("vfrustumculling",
9502     "vfrustumculling [toEnable]: enables/disables objects clipping",
9503     __FILE__,VFrustumCulling,group);
9504   theCommands.Add("vhighlightselected",
9505     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
9506     "Without arguments it shows if highlighting of selected objects is enabled now.",
9507     __FILE__,VHighlightSelected,group);
9508   theCommands.Add ("vplace",
9509             "vplace dx dy"
9510     "\n\t\t: Places the point (in pixels) at the center of the window",
9511     __FILE__, VPlace, group);
9512   theCommands.Add("vxrotate",
9513     "vxrotate",
9514     __FILE__,VXRotate,group);
9515
9516     theCommands.Add("vmanipulator",
9517       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
9518       "\n    tool to create and manage AIS manipulators."
9519       "\n    Options: "
9520       "\n      '-attach AISObject'                 attach manipulator to AISObject"
9521       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
9522       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
9523       "\n      '-enableModes    {0|1}'             enable modes when attaching"
9524       "\n      '-detach'                           detach manipulator"
9525       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
9526       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
9527       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
9528       "\n      '-move x y z'                     - move attached object"
9529       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
9530       "\n      '-scale factor'                   - scale attached object"
9531       "\n      '-autoActivate      {0|1}'        - set activation on detection"
9532       "\n      '-followTranslation {0|1}'        - set following translation transform"
9533       "\n      '-followRotation    {0|1}'        - set following rotation transform"
9534       "\n      '-gap value'                      - set gap between sub-parts"
9535       "\n      '-part axis mode    {0|1}'        - set visual part"
9536       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
9537       "\n      '-size value'                     - set size of manipulator"
9538       "\n      '-zoomable {0|1}'                 - set zoom persistence",
9539     __FILE__, VManipulator, group);
9540
9541 #if defined(_WIN32)
9542   theCommands.Add("vprogressive",
9543     "vprogressive",
9544     __FILE__, VProgressiveMode, group);
9545 #endif
9546 }