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