0026641: Visualization, TKOpenGl - handle correctly transformation persistence within...
[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
3990     {
3991       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3992       return 1;
3993     }
3994   }
3995   if (!aBreadth || !aHeight)
3996   {
3997     Standard_Integer aWinWidth, aWinHeight;
3998     aView->Window()->Size (aWinWidth, aWinHeight);
3999     if (!aBreadth)
4000     {
4001       aBreadth = aWinWidth;
4002     }
4003     if (!aHeight)
4004     {
4005       aHeight = aWinHeight;
4006     }
4007   }
4008   aCS->SetSize              (aBreadth, aHeight);
4009   aCS->SetPosition          (aPosX, aPosY);
4010   aCS->SetTextHeight        (aTextHeight);
4011   aCS->SetRange             (aMinRange, aMaxRange);
4012   aCS->SetNumberOfIntervals (aNbIntervals);
4013   aCS->SetLabelPosition     (aLabPosition);
4014 //  aCS->SetColor             (aView->BackgroundColor().Invert());
4015   aCS->SetToUpdate();
4016   aContext->Display (aCS);
4017
4018   return 0;
4019 }
4020
4021 //==============================================================================
4022 //function : VGraduatedTrihedron
4023 //purpose  : Displays or hides a graduated trihedron
4024 //==============================================================================
4025 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4026                                   Quantity_Color& theColor)
4027 {
4028   Quantity_NameOfColor aColorName;
4029   TCollection_AsciiString aVal = theValue;
4030   aVal.UpperCase();
4031   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4032   {
4033     return Standard_False;
4034   }
4035   theColor = Quantity_Color (aColorName);
4036   return Standard_True;
4037 }
4038
4039 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4040 {
4041   if (theArgNum < 2)
4042   {
4043     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4044               << theArgs[0] <<"' for more information.\n";
4045     return 1;  //TCL_ERROR
4046   }
4047
4048   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4049   TCollection_AsciiString aParseKey;
4050   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4051   {
4052     TCollection_AsciiString anArg (theArgs [anArgIt]);
4053
4054     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4055     {
4056       aParseKey = anArg;
4057       aParseKey.Remove (1);
4058       aParseKey.LowerCase();
4059       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4060       continue;
4061     }
4062
4063     if (aParseKey.IsEmpty())
4064     {
4065       continue;
4066     }
4067
4068     aMapOfArgs(aParseKey)->Append (anArg);
4069   }
4070
4071   // Check parameters
4072   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4073        aMapIt.More(); aMapIt.Next())
4074   {
4075     const TCollection_AsciiString& aKey = aMapIt.Key();
4076     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4077
4078     // Bool key, without arguments
4079     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4080         && anArgs->IsEmpty())
4081     {
4082       continue;
4083     }
4084
4085     // One argument
4086     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4087           && anArgs->Length() == 1)
4088     {
4089       continue;
4090     }
4091
4092     // On/off arguments
4093     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4094         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4095         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4096         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4097         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4098     {
4099       continue;
4100     }
4101
4102     // One string argument
4103     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4104           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4105           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4106     {
4107       continue;
4108     }
4109
4110     // One integer argument
4111     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4112           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4113           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4114           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4115          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4116     {
4117       continue;
4118     }
4119
4120     // One real argument
4121     if ( aKey.IsEqual ("arrowlength")
4122          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4123     {
4124       continue;
4125     }
4126
4127     // Two string arguments
4128     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4129          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4130     {
4131       continue;
4132     }
4133
4134     TCollection_AsciiString aLowerKey;
4135     aLowerKey  = "-";
4136     aLowerKey += aKey;
4137     aLowerKey.LowerCase();
4138     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4139     std::cout << "Type help for more information.\n";
4140     return 1;
4141   }
4142
4143   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4144   if (anAISContext.IsNull())
4145   {
4146     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4147     return 1;
4148   }
4149
4150   Standard_Boolean toDisplay = Standard_True;
4151   Quantity_Color aColor;
4152   Graphic3d_GraduatedTrihedron aTrihedronData;
4153   // Process parameters
4154   Handle(TColStd_HSequenceOfAsciiString) aValues;
4155   if (aMapOfArgs.Find ("off", aValues))
4156   {
4157     toDisplay = Standard_False;
4158   }
4159
4160   // AXES NAMES
4161   if (aMapOfArgs.Find ("xname", aValues))
4162   {
4163     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4164   }
4165   if (aMapOfArgs.Find ("yname", aValues))
4166   {
4167     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4168   }
4169   if (aMapOfArgs.Find ("zname", aValues))
4170   {
4171     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4172   }
4173   if (aMapOfArgs.Find ("xdrawname", aValues))
4174   {
4175     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4176   }
4177   if (aMapOfArgs.Find ("ydrawname", aValues))
4178   {
4179     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4180   }
4181   if (aMapOfArgs.Find ("zdrawname", aValues))
4182   {
4183     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4184   }
4185   if (aMapOfArgs.Find ("xnameoffset", aValues))
4186   {
4187     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4188   }
4189   if (aMapOfArgs.Find ("ynameoffset", aValues))
4190   {
4191     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4192   }
4193   if (aMapOfArgs.Find ("znameoffset", aValues))
4194   {
4195     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4196   }
4197
4198   // COLORS
4199   if (aMapOfArgs.Find ("xnamecolor", aValues))
4200   {
4201     if (!GetColor (aValues->Value(1), aColor))
4202     {
4203       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4204       return 1;
4205     }
4206     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4207   }
4208   if (aMapOfArgs.Find ("ynamecolor", aValues))
4209   {
4210     if (!GetColor (aValues->Value(1), aColor))
4211     {
4212       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4213       return 1;
4214     }
4215     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4216   }
4217   if (aMapOfArgs.Find ("znamecolor", aValues))
4218   {
4219     if (!GetColor (aValues->Value(1), aColor))
4220     {
4221       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4222       return 1;
4223     }
4224     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4225   }
4226   if (aMapOfArgs.Find ("xcolor", aValues))
4227   {
4228     if (!GetColor (aValues->Value(1), aColor))
4229     {
4230       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4231       return 1;
4232     }
4233     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4234   }
4235   if (aMapOfArgs.Find ("ycolor", aValues))
4236   {
4237     if (!GetColor (aValues->Value(1), aColor))
4238     {
4239       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4240       return 1;
4241     }
4242     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4243   }
4244   if (aMapOfArgs.Find ("zcolor", aValues))
4245   {
4246     if (!GetColor (aValues->Value(1), aColor))
4247     {
4248       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4249       return 1;
4250     }
4251     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4252   }
4253
4254   // TICKMARKS
4255   if (aMapOfArgs.Find ("xticks", aValues))
4256   {
4257     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4258   }
4259   if (aMapOfArgs.Find ("yticks", aValues))
4260   {
4261     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4262   }
4263   if (aMapOfArgs.Find ("zticks", aValues))
4264   {
4265     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4266   }
4267   if (aMapOfArgs.Find ("xticklength", aValues))
4268   {
4269     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4270   }
4271   if (aMapOfArgs.Find ("yticklength", aValues))
4272   {
4273     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4274   }
4275   if (aMapOfArgs.Find ("zticklength", aValues))
4276   {
4277     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4278   }
4279   if (aMapOfArgs.Find ("xdrawticks", aValues))
4280   {
4281     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4282   }
4283   if (aMapOfArgs.Find ("ydrawticks", aValues))
4284   {
4285     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4286   }
4287   if (aMapOfArgs.Find ("zdrawticks", aValues))
4288   {
4289     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4290   }
4291
4292   // VALUES
4293   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4294   {
4295     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4296   }
4297   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4298   {
4299     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4300   }
4301   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4302   {
4303     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4304   }
4305   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4306   {
4307     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4308   }
4309   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4310   {
4311     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4312   }
4313   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4314   {
4315     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4316   }
4317
4318   // ARROWS
4319   if (aMapOfArgs.Find ("arrowlength", aValues))
4320   {
4321     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4322   }
4323
4324   // FONTS
4325   if (aMapOfArgs.Find ("namefont", aValues))
4326   {
4327     aTrihedronData.SetNamesFont (aValues->Value(1));
4328   }
4329   if (aMapOfArgs.Find ("valuesfont", aValues))
4330   {
4331     aTrihedronData.SetValuesFont (aValues->Value(1));
4332   }
4333
4334   if (aMapOfArgs.Find ("drawgrid", aValues))
4335   {
4336     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4337   }
4338   if (aMapOfArgs.Find ("drawaxes", aValues))
4339   {
4340     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4341   }
4342
4343   // The final step: display of erase trihedron
4344   if (toDisplay)
4345   {
4346     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4347   }
4348   else
4349   {
4350     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4351   }
4352
4353   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4354   ViewerTest::CurrentView()->Redraw();
4355
4356   return 0;
4357 }
4358
4359 //==============================================================================
4360 //function : VPrintView
4361 //purpose  : Test printing algorithm, print the view to image file with given
4362 //           width and height. Printing implemented only for WNT.
4363 //==============================================================================
4364 static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
4365                        const char** argv)
4366 {
4367 #ifndef _WIN32
4368   (void )argc;
4369   (void )argv;
4370   di << "Printing implemented only for WNT!\n";
4371   return 0;
4372 #else
4373
4374   Handle(AIS_InteractiveContext) aContextAIS = NULL;
4375   Handle(V3d_View) aView = NULL;
4376   aContextAIS = ViewerTest::GetAISContext();
4377   if (!aContextAIS.IsNull())
4378   {
4379     const Handle(V3d_Viewer)& Vwr = aContextAIS->CurrentViewer();
4380     Vwr->InitActiveViews();
4381     if(Vwr->MoreActiveViews())
4382       aView = Vwr->ActiveView();
4383   }
4384
4385   // check for errors
4386   if (aView.IsNull())
4387   {
4388     di << "Call vinit before!\n";
4389     return 1;
4390   }
4391   else if (argc < 4)
4392   {
4393     di << "Use: " << argv[0];
4394     di << " width height filename [print algo=0] [tile_width tile_height]\n";
4395     di << "width, height of the intermediate buffer for operation\n";
4396     di << "algo : {0|1}\n";
4397     di << "        0 - stretch algorithm\n";
4398     di << "        1 - tile algorithm\n";
4399     di << "test printing algorithms into an intermediate buffer\n";
4400     di << "using specific tile size if provided\n";
4401     di << "with saving output to an image file\n";
4402     return 1;
4403   }
4404
4405   // get the input params
4406   Standard_Integer aWidth  = Draw::Atoi (argv[1]);
4407   Standard_Integer aHeight = Draw::Atoi (argv[2]);
4408   Standard_Integer aMode   = 0;
4409   TCollection_AsciiString aFileName = TCollection_AsciiString (argv[3]);
4410   if (argc >= 5)
4411     aMode = Draw::Atoi (argv[4]);
4412
4413   Standard_Integer aTileWidth  = 0;
4414   Standard_Integer aTileHeight = 0;
4415   Standard_Boolean isTileSizeProvided = Standard_False;
4416   if (argc == 7)
4417   {
4418     isTileSizeProvided = Standard_True;
4419     aTileWidth  = Draw::Atoi (argv[5]);
4420     aTileHeight = Draw::Atoi (argv[6]);
4421   }
4422
4423   // check the input parameters
4424   if (aWidth <= 0 || aHeight <= 0)
4425   {
4426     di << "Width and height must be positive values!\n";
4427     return 1;
4428   }
4429   if (aMode != 0 && aMode != 1)
4430     aMode = 0;
4431
4432   // define compatible bitmap
4433   HDC anDC = CreateCompatibleDC(0);
4434   BITMAPINFO aBitmapData;
4435   memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
4436   aBitmapData.bmiHeader.biSize          = sizeof (BITMAPINFOHEADER);
4437   aBitmapData.bmiHeader.biWidth         = aWidth ;
4438   aBitmapData.bmiHeader.biHeight        = aHeight;
4439   aBitmapData.bmiHeader.biPlanes        = 1;
4440   aBitmapData.bmiHeader.biBitCount      = 24;
4441   aBitmapData.bmiHeader.biXPelsPerMeter = 0;
4442   aBitmapData.bmiHeader.biYPelsPerMeter = 0;
4443   aBitmapData.bmiHeader.biClrUsed       = 0;
4444   aBitmapData.bmiHeader.biClrImportant  = 0;
4445   aBitmapData.bmiHeader.biCompression   = BI_RGB;
4446   aBitmapData.bmiHeader.biSizeImage     = 0;
4447
4448   // Create Device Independent Bitmap
4449   void* aBitsOut = NULL;
4450   HBITMAP aMemoryBitmap = CreateDIBSection (anDC, &aBitmapData, DIB_RGB_COLORS,
4451                                             &aBitsOut, NULL, 0);
4452   HGDIOBJ anOldBitmap   = SelectObject(anDC, aMemoryBitmap);
4453
4454   Standard_Boolean isSaved = Standard_False, isPrinted = Standard_False;
4455   if (aBitsOut != NULL)
4456   {
4457     if (aMode == 0)
4458       isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_STRETCH);
4459     else
4460     {
4461       if (isTileSizeProvided)
4462       {
4463         Handle(Graphic3d_CView)    aGraphicView = ViewerTest::CurrentView()->View();
4464         Handle(Standard_Transient) anOldBuffer  = aGraphicView->FBO();
4465         Handle(Standard_Transient) aNewBuffer   = aGraphicView->FBOCreate (aTileWidth, aTileHeight);
4466         aGraphicView->SetFBO (aNewBuffer);
4467
4468         isPrinted = aView->Print (anDC, 1, 1, 0, Aspect_PA_TILE);
4469
4470         aGraphicView->FBORelease (aNewBuffer);
4471         aGraphicView->SetFBO (anOldBuffer);
4472       }
4473       else
4474       {
4475         isPrinted = aView->Print (anDC, 1, 1, 0, Aspect_PA_TILE);
4476       }
4477     }
4478
4479     // successfully printed into an intermediate buffer
4480     if (isPrinted)
4481     {
4482       Image_PixMap aWrapper;
4483       aWrapper.InitWrapper (Image_PixMap::ImgBGR, (Standard_Byte* )aBitsOut, aWidth, aHeight, aWidth * 3 + aWidth % 4);
4484       aWrapper.SetTopDown (false);
4485
4486       Image_AlienPixMap anImageBitmap;
4487       anImageBitmap.InitCopy (aWrapper);
4488       isSaved = anImageBitmap.Save (aFileName);
4489     }
4490     else
4491     {
4492       di << "Print operation failed due to printing errors or\n";
4493       di << "insufficient memory available\n";
4494       di << "Please, try to use smaller dimensions for this test\n";
4495       di << "command, as it allocates intermediate buffer for storing\n";
4496       di << "the result\n";
4497     }
4498   }
4499   else
4500   {
4501     di << "Can't allocate memory for intermediate buffer\n";
4502     di << "Please use smaller dimensions\n";
4503   }
4504
4505   if (aMemoryBitmap)
4506   {
4507     SelectObject (anDC, anOldBitmap);
4508     DeleteObject (aMemoryBitmap);
4509     DeleteDC(anDC);
4510   }
4511
4512   if (!isSaved)
4513   {
4514     di << "Save to file operation failed. This operation may fail\n";
4515     di << "if you don't have enough available memory, then you can\n";
4516     di << "use smaller dimensions for the output file\n";
4517     return 1;
4518   }
4519
4520   return 0;
4521
4522 #endif
4523 }
4524
4525 //==============================================================================
4526 //function : VZLayer
4527 //purpose  : Test z layer operations for v3d viewer
4528 //==============================================================================
4529 static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4530 {
4531   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext ();
4532   if (aContextAIS.IsNull())
4533   {
4534     di << "Call vinit before!\n";
4535     return 1;
4536   }
4537   else if (argc < 2)
4538   {
4539     di << di.PrintHelp (argv[0]);
4540     return 1;
4541   }
4542
4543   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4544   if (aViewer.IsNull())
4545   {
4546     di << "No active viewer!\n";
4547     return 1;
4548   }
4549
4550   // perform operation
4551   TCollection_AsciiString anOp = TCollection_AsciiString (argv[1]);
4552   if (anOp == "add")
4553   {
4554     Standard_Integer aNewId;
4555     if (!aViewer->AddZLayer (aNewId))
4556     {
4557       di << "Impossible to add new z layer!\n";
4558       return 1;
4559     }
4560
4561     di << "New z layer added with index: " << aNewId << "\n";
4562   }
4563   else if (anOp == "del")
4564   {
4565     if (argc < 3)
4566     {
4567       di << "Please also provide as argument id of z layer to remove\n";
4568       return 1;
4569     }
4570
4571     Standard_Integer aDelId = Draw::Atoi (argv[2]);
4572     if (!aViewer->RemoveZLayer (aDelId))
4573     {
4574       di << "Impossible to remove the z layer or invalid id!\n";
4575       return 1;
4576     }
4577
4578     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4579          anObjIter.More(); anObjIter.Next())
4580     {
4581       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4582       if (aPrs.IsNull()
4583        || aPrs->ZLayer() != aDelId)
4584       {
4585         continue;
4586       }
4587       aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4588     }
4589
4590     di << "Z layer " << aDelId << " has been removed\n";
4591   }
4592   else if (anOp == "get")
4593   {
4594     TColStd_SequenceOfInteger anIds;
4595     aViewer->GetAllZLayers (anIds);
4596     for (Standard_Integer aSeqIdx = 1; aSeqIdx <= anIds.Length(); aSeqIdx++)
4597     {
4598       di << anIds.Value (aSeqIdx) << " ";
4599     }
4600
4601     di << "\n";
4602   }
4603   else if (anOp == "settings")
4604   {
4605     if (argc < 3)
4606     {
4607       di << "Please also provide an id\n";
4608       return 1;
4609     }
4610
4611     Standard_Integer anId = Draw::Atoi (argv[2]);
4612     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4613
4614     di << "Depth test - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthTest) ? "enabled" : "disabled") << "\n";
4615     di << "Depth write - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? "enabled" : "disabled") << "\n";
4616     di << "Depth buffer clearing - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthClear) ? "enabled" : "disabled") << "\n";
4617     di << "Depth offset - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthOffset) ? "enabled" : "disabled") << "\n";
4618
4619   }
4620   else if (anOp == "enable")
4621   {
4622     if (argc < 3)
4623     {
4624       di << "Please also provide an option to enable\n";
4625       return 1;
4626     }
4627
4628     if (argc < 4)
4629     {
4630       di << "Please also provide a layer id\n";
4631       return 1;
4632     }
4633
4634     TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
4635     Standard_Integer anId = Draw::Atoi (argv[3]);
4636     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4637
4638     if (aSubOp == "depthtest" || aSubOp == "test")
4639     {
4640       aSettings.EnableSetting (Graphic3d_ZLayerDepthTest);
4641     }
4642     else if (aSubOp == "depthwrite" || aSubOp == "write")
4643     {
4644       aSettings.EnableSetting (Graphic3d_ZLayerDepthWrite);
4645     }
4646     else if (aSubOp == "depthclear" || aSubOp == "clear")
4647     {
4648       aSettings.EnableSetting (Graphic3d_ZLayerDepthClear);
4649     }
4650     else if (aSubOp == "depthoffset" || aSubOp == "offset")
4651     {
4652       if (argc < 6)
4653       {
4654         di << "Please also provide a factor and units values for depth offset\n";
4655         di << "Format is: vzlayer enable offset [factor] [units] [layerId]\n";
4656         return 1;
4657       }
4658
4659       Standard_ShortReal aFactor = static_cast<Standard_ShortReal> (Draw::Atof (argv[3]));
4660       Standard_ShortReal aUnits  = static_cast<Standard_ShortReal> (Draw::Atof (argv[4]));
4661       anId = Draw::Atoi (argv[5]);
4662       aSettings = aViewer->ZLayerSettings (anId);
4663
4664       aSettings.DepthOffsetFactor = aFactor;
4665       aSettings.DepthOffsetUnits  = aUnits;
4666
4667       aSettings.EnableSetting (Graphic3d_ZLayerDepthOffset);
4668     }
4669     else if (aSubOp == "positiveoffset" || aSubOp == "poffset")
4670     {
4671       aSettings.SetDepthOffsetPositive();
4672     }
4673     else if (aSubOp == "negativeoffset" || aSubOp == "noffset")
4674     {
4675       aSettings.SetDepthOffsetNegative();
4676     }
4677     else if (aSubOp == "textureenv")
4678     {
4679       aSettings.UseEnvironmentTexture = true;
4680     }
4681
4682     aViewer->SetZLayerSettings (anId, aSettings);
4683   }
4684   else if (anOp == "disable")
4685   {
4686     if (argc < 3)
4687     {
4688       di << "Please also provide an option to disable\n";
4689       return 1;
4690     }
4691
4692     if (argc < 4)
4693     {
4694       di << "Please also provide a layer id\n";
4695       return 1;
4696     }
4697
4698     TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
4699     Standard_Integer anId = Draw::Atoi (argv[3]);
4700     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4701
4702     if (aSubOp == "depthtest" || aSubOp == "test")
4703     {
4704       aSettings.DisableSetting (Graphic3d_ZLayerDepthTest);
4705     }
4706     else if (aSubOp == "depthwrite" || aSubOp == "write")
4707     {
4708       aSettings.DisableSetting (Graphic3d_ZLayerDepthWrite);
4709     }
4710     else if (aSubOp == "depthclear" || aSubOp == "clear")
4711     {
4712       aSettings.DisableSetting (Graphic3d_ZLayerDepthClear);
4713     }
4714     else if (aSubOp == "depthoffset" || aSubOp == "offset")
4715     {
4716       aSettings.DisableSetting (Graphic3d_ZLayerDepthOffset);
4717     }
4718     else if (aSubOp == "textureenv")
4719     {
4720       aSettings.UseEnvironmentTexture = false;
4721     }
4722
4723     aViewer->SetZLayerSettings (anId, aSettings);
4724   }
4725   else
4726   {
4727     di << "Invalid operation, please use { add / del / get / settings / enable / disable}\n";
4728     return 1;
4729   }
4730
4731   return 0;
4732 }
4733
4734 // The interactive presentation of 2d layer item
4735 // for "vlayerline" command it provides a presentation of
4736 // line with user-defined linewidth, linetype and transparency.
4737 class V3d_LineItem : public AIS_InteractiveObject
4738 {
4739 public:
4740   // CASCADE RTTI
4741   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4742
4743   // constructor
4744   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4745                                Standard_Real X2, Standard_Real Y2,
4746                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4747                                Standard_Real theWidth    = 0.5,
4748                                Standard_Real theTransp   = 1.0);
4749
4750   private:
4751
4752   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4753                 const Handle(Prs3d_Presentation)& thePresentation,
4754                 const Standard_Integer theMode) Standard_OVERRIDE;
4755
4756   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4757                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4758   {}
4759
4760 private:
4761
4762   Standard_Real       myX1, myY1, myX2, myY2;
4763   Aspect_TypeOfLine   myType;
4764   Standard_Real       myWidth;
4765 };
4766
4767 // default constructor for line item
4768 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4769                            Standard_Real X2, Standard_Real Y2,
4770                            Aspect_TypeOfLine theType,
4771                            Standard_Real theWidth,
4772                            Standard_Real theTransp) :
4773   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4774   myType(theType), myWidth(theWidth)
4775 {
4776   SetTransparency (1-theTransp);
4777 }
4778
4779 // render line
4780 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4781                             const Handle(Prs3d_Presentation)& thePresentation,
4782                             const Standard_Integer /*theMode*/)
4783 {
4784   thePresentation->Clear();
4785   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4786   Standard_Integer aWidth, aHeight;
4787   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4788   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4789   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4790   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4791   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4792   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4793   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4794   aGroup->AddPrimitiveArray (aPrim);
4795 }
4796
4797 //=============================================================================
4798 //function : VLayerLine
4799 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4800 //         : linewidth, transparency coefficient
4801 //============================================================================
4802 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4803 {
4804   // get the active view
4805   Handle(V3d_View) aView = ViewerTest::CurrentView();
4806   if (aView.IsNull())
4807   {
4808     di << "Call vinit before!\n";
4809     return 1;
4810   }
4811   else if (argc < 5)
4812   {
4813     di << "Use: " << argv[0];
4814     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4815     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4816     di << "              0 - solid  \n";
4817     di << "              1 - dashed \n";
4818     di << "              2 - dot    \n";
4819     di << "              3 - dashdot\n";
4820     di << " transparency : { 0.0 - 1.0 } \n";
4821     di << "                  0.0 - transparent\n";
4822     di << "                  1.0 - visible    \n";
4823     return 1;
4824   }
4825
4826   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4827   // get the input params
4828   Standard_Real X1 = Draw::Atof(argv[1]);
4829   Standard_Real Y1 = Draw::Atof(argv[2]);
4830   Standard_Real X2 = Draw::Atof(argv[3]);
4831   Standard_Real Y2 = Draw::Atof(argv[4]);
4832
4833   Standard_Real    aWidth = 0.5;
4834   Standard_Integer aType  = 0;
4835   Standard_Real    aTransparency = 1.0;
4836
4837   // has width
4838   if (argc > 5)
4839     aWidth = Draw::Atof(argv[5]);
4840
4841   // has type
4842   if (argc > 6)
4843      aType = (Standard_Integer) Draw::Atoi(argv[6]);
4844
4845   // has transparency
4846   if (argc > 7)
4847   {
4848     aTransparency = Draw::Atof(argv[7]);
4849     if (aTransparency < 0 || aTransparency > 1.0)
4850       aTransparency = 1.0;
4851   }
4852
4853   // select appropriate line type
4854   Aspect_TypeOfLine aLineType;
4855   switch (aType)
4856   {
4857     case 1:
4858       aLineType = Aspect_TOL_DASH;
4859     break;
4860
4861     case 2:
4862       aLineType = Aspect_TOL_DOT;
4863     break;
4864
4865     case 3:
4866       aLineType = Aspect_TOL_DOTDASH;
4867     break;
4868
4869     default:
4870       aLineType = Aspect_TOL_SOLID;
4871   }
4872
4873   static Handle (V3d_LineItem) aLine;
4874   if (!aLine.IsNull())
4875   {
4876     aContext->Erase (aLine);
4877   }
4878   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4879                             aLineType, aWidth,
4880                             aTransparency);
4881
4882   aContext->SetTransformPersistence (aLine, Graphic3d_TMF_2d, gp_Pnt (-1.0, -1.0, 0.0));
4883   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4884   aLine->SetToUpdate();
4885   aContext->Display (aLine, Standard_True);
4886
4887   return 0;
4888 }
4889
4890
4891 //==============================================================================
4892 //function : VGrid
4893 //purpose  :
4894 //==============================================================================
4895
4896 static int VGrid (Draw_Interpretor& /*theDI*/,
4897                   Standard_Integer  theArgNb,
4898                   const char**      theArgVec)
4899 {
4900   // get the active view
4901   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4902   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4903   if (aView.IsNull() || aViewer.IsNull())
4904   {
4905     std::cerr << "No active view. Please call vinit.\n";
4906     return 1;
4907   }
4908
4909   Aspect_GridType     aType = aViewer->GridType();
4910   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4911
4912   Standard_Integer anIter = 1;
4913   for (; anIter < theArgNb; ++anIter)
4914   {
4915     const char* aValue = theArgVec[anIter];
4916     if (*aValue == 'r')
4917     {
4918       aType = Aspect_GT_Rectangular;
4919     }
4920     else if (*aValue == 'c')
4921     {
4922       aType = Aspect_GT_Circular;
4923     }
4924     else if (*aValue == 'l')
4925     {
4926       aMode = Aspect_GDM_Lines;
4927     }
4928     else if (*aValue == 'p')
4929     {
4930       aMode = Aspect_GDM_Points;
4931     }
4932     else if (strcmp (aValue, "off" ) == 0)
4933     {
4934       aViewer->DeactivateGrid();
4935       return 0;
4936     }
4937     else
4938     {
4939       break;
4940     }
4941   }
4942
4943   Standard_Integer aTail = (theArgNb - anIter);
4944   if (aTail == 0)
4945   {
4946     aViewer->ActivateGrid (aType, aMode);
4947     return 0;
4948   }
4949   else if (aTail != 2 && aTail != 5)
4950   {
4951     std::cerr << "Incorrect arguments number! Usage:\n"
4952               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
4953     return 1;
4954   }
4955
4956   Quantity_Length anOriginX, anOriginY;
4957   Quantity_PlaneAngle aRotAngle;
4958   if (aType == Aspect_GT_Rectangular)
4959   {
4960     Quantity_Length aRStepX, aRStepY;
4961     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
4962
4963     anOriginX = Draw::Atof (theArgVec[anIter++]);
4964     anOriginY = Draw::Atof (theArgVec[anIter++]);
4965     if (aTail == 5)
4966     {
4967       aRStepX   = Draw::Atof (theArgVec[anIter++]);
4968       aRStepY   = Draw::Atof (theArgVec[anIter++]);
4969       aRotAngle = Draw::Atof (theArgVec[anIter++]);
4970     }
4971     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
4972     aViewer->ActivateGrid (aType, aMode);
4973   }
4974   else if (aType == Aspect_GT_Circular)
4975   {
4976     Quantity_Length aRadiusStep;
4977     Standard_Integer aDivisionNumber;
4978     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
4979
4980     anOriginX = Draw::Atof (theArgVec[anIter++]);
4981     anOriginY = Draw::Atof (theArgVec[anIter++]);
4982     if (aTail == 5)
4983     {
4984       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
4985       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
4986       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
4987     }
4988
4989     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
4990     aViewer->ActivateGrid (aType, aMode);
4991   }
4992
4993   return 0;
4994 }
4995
4996 //==============================================================================
4997 //function : VPriviledgedPlane
4998 //purpose  :
4999 //==============================================================================
5000
5001 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5002                               Standard_Integer  theArgNb,
5003                               const char**      theArgVec)
5004 {
5005   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5006   {
5007     std::cerr << "Error: wrong number of arguments! See usage:\n";
5008     theDI.PrintHelp (theArgVec[0]);
5009     return 1;
5010   }
5011
5012   // get the active viewer
5013   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5014   if (aViewer.IsNull())
5015   {
5016     std::cerr << "Error: no active viewer. Please call vinit.\n";
5017     return 1;
5018   }
5019
5020   if (theArgNb == 1)
5021   {
5022     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5023     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5024     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5025     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5026     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5027           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5028           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5029     return 0;
5030   }
5031
5032   Standard_Integer anArgIdx = 1;
5033   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5034   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5035   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5036   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5037   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5038   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5039
5040   gp_Ax3 aPriviledgedPlane;
5041   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5042   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5043   if (theArgNb > 7)
5044   {
5045     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5046     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5047     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5048     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5049     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5050   }
5051   else
5052   {
5053     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5054   }
5055
5056   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5057
5058   return 0;
5059 }
5060
5061 //==============================================================================
5062 //function : VConvert
5063 //purpose  :
5064 //==============================================================================
5065
5066 static int VConvert (Draw_Interpretor& theDI,
5067                      Standard_Integer  theArgNb,
5068                      const char**      theArgVec)
5069 {
5070   // get the active view
5071   Handle(V3d_View) aView = ViewerTest::CurrentView();
5072   if (aView.IsNull())
5073   {
5074     std::cerr << "Error: no active view. Please call vinit.\n";
5075     return 1;
5076   }
5077
5078   enum { Model, Ray, View, Window, Grid } aMode = Model;
5079
5080   // access coordinate arguments
5081   TColStd_SequenceOfReal aCoord;
5082   Standard_Integer anArgIdx = 1;
5083   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5084   {
5085     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5086     if (!anArg.IsRealValue())
5087     {
5088       break;
5089     }
5090     aCoord.Append (anArg.RealValue());
5091   }
5092
5093   // non-numeric argument too early
5094   if (aCoord.IsEmpty())
5095   {
5096     std::cerr << "Error: wrong number of arguments! See usage:\n";
5097     theDI.PrintHelp (theArgVec[0]);
5098     return 1;
5099   }
5100
5101   // collect all other arguments and options
5102   for (; anArgIdx < theArgNb; ++anArgIdx)
5103   {
5104     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5105     anArg.LowerCase();
5106     if      (anArg == "window") aMode = Window;
5107     else if (anArg == "view")   aMode = View;
5108     else if (anArg == "grid")   aMode = Grid;
5109     else if (anArg == "ray")    aMode = Ray;
5110     else
5111     {
5112       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5113       theDI.PrintHelp (theArgVec[0]);
5114       return 1;
5115     }
5116   }
5117
5118   // complete input checks
5119   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5120       (aCoord.Length() == 2 && theArgNb > 4) ||
5121       (aCoord.Length() == 3 && theArgNb > 5))
5122   {
5123     std::cerr << "Error: wrong number of arguments! See usage:\n";
5124     theDI.PrintHelp (theArgVec[0]);
5125     return 1;
5126   }
5127
5128   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5129   Standard_Integer aXYp[2] = {0, 0};
5130
5131   // convert one-dimensional coordinate
5132   if (aCoord.Length() == 1)
5133   {
5134     switch (aMode)
5135     {
5136       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
5137       case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
5138       default:
5139         std::cerr << "Error: wrong arguments! See usage:\n";
5140         theDI.PrintHelp (theArgVec[0]);
5141         return 1;
5142     }
5143   }
5144
5145   // convert 2D coordinates from projection or view reference space
5146   if (aCoord.Length() == 2)
5147   {
5148     switch (aMode)
5149     {
5150       case Model :
5151         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5152         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5153         return 0;
5154
5155       case View :
5156         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5157         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5158         return 0;
5159
5160       case Window :
5161         aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
5162         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5163         return 0;
5164
5165       case Grid :
5166         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5167         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5168         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5169         return 0;
5170
5171       case Ray :
5172         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5173                                 (Standard_Integer) aCoord (2),
5174                                 aXYZ[0], aXYZ[1], aXYZ[2],
5175                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5176         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5177         return 0;
5178
5179       default:
5180         std::cerr << "Error: wrong arguments! See usage:\n";
5181         theDI.PrintHelp (theArgVec[0]);
5182         return 1;
5183     }
5184   }
5185
5186   // convert 3D coordinates from view reference space
5187   else if (aCoord.Length() == 3)
5188   {
5189     switch (aMode)
5190     {
5191       case Window :
5192         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5193         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5194         return 0;
5195
5196       case Grid :
5197         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5198         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5199         return 0;
5200
5201       default:
5202         std::cerr << "Error: wrong arguments! See usage:\n";
5203         theDI.PrintHelp (theArgVec[0]);
5204         return 1;
5205     }
5206   }
5207
5208   return 0;
5209 }
5210
5211 //==============================================================================
5212 //function : VFps
5213 //purpose  :
5214 //==============================================================================
5215
5216 static int VFps (Draw_Interpretor& theDI,
5217                  Standard_Integer  theArgNb,
5218                  const char**      theArgVec)
5219 {
5220   // get the active view
5221   Handle(V3d_View) aView = ViewerTest::CurrentView();
5222   if (aView.IsNull())
5223   {
5224     std::cerr << "No active view. Please call vinit.\n";
5225     return 1;
5226   }
5227
5228   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5229   if (aFramesNb <= 0)
5230   {
5231     std::cerr << "Incorrect arguments!\n";
5232     return 1;
5233   }
5234
5235   // the time is meaningless for first call
5236   // due to async OpenGl rendering
5237   aView->Redraw();
5238
5239   // redraw view in loop to estimate average values
5240   OSD_Timer aTimer;
5241   aTimer.Start();
5242   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5243   {
5244     aView->Redraw();
5245   }
5246   aTimer.Stop();
5247   Standard_Real aCpu;
5248   const Standard_Real aTime = aTimer.ElapsedTime();
5249   aTimer.OSD_Chronometer::Show (aCpu);
5250
5251   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5252   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5253
5254   // return statistics
5255   theDI << "FPS: " << aFpsAver << "\n"
5256         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5257
5258   // compute additional statistics in ray-tracing mode
5259   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5260
5261   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5262   {
5263     Standard_Integer aSizeX;
5264     Standard_Integer aSizeY;
5265
5266     aView->Window()->Size (aSizeX, aSizeY);
5267
5268     // 1 shadow ray and 1 secondary ray pew each bounce
5269     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5270
5271     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5272   }
5273
5274   return 0;
5275 }
5276
5277 //==============================================================================
5278 //function : VGlDebug
5279 //purpose  :
5280 //==============================================================================
5281
5282 static int VGlDebug (Draw_Interpretor& theDI,
5283                      Standard_Integer  theArgNb,
5284                      const char**      theArgVec)
5285 {
5286   Handle(OpenGl_GraphicDriver) aDriver;
5287   Handle(V3d_View) aView = ViewerTest::CurrentView();
5288   if (!aView.IsNull())
5289   {
5290     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5291   }
5292   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5293   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5294
5295   if (theArgNb < 2)
5296   {
5297     TCollection_AsciiString aDebActive, aSyncActive;
5298     if (aCaps == NULL)
5299     {
5300       aCaps = aDefCaps;
5301     }
5302     else
5303     {
5304       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5305                                                                   "GL_ARB_debug_output");
5306       aDebActive = isActive ? " (active)" : " (inactive)";
5307       if (isActive)
5308       {
5309         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5310         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5311       }
5312     }
5313
5314     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5315           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5316           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5317           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5318     return 0;
5319   }
5320
5321   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5322   {
5323     Standard_CString        anArg     = theArgVec[anArgIter];
5324     TCollection_AsciiString anArgCase (anArg);
5325     anArgCase.LowerCase();
5326     Standard_Boolean toEnableDebug = Standard_True;
5327     if (anArgCase == "-glsl"
5328      || anArgCase == "-glslwarn"
5329      || anArgCase == "-glslwarns"
5330      || anArgCase == "-glslwarnings")
5331     {
5332       Standard_Boolean toShowWarns = Standard_True;
5333       if (++anArgIter < theArgNb
5334       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5335       {
5336         --anArgIter;
5337       }
5338       aDefCaps->glslWarnings = toShowWarns;
5339       if (aCaps != NULL)
5340       {
5341         aCaps->glslWarnings = toShowWarns;
5342       }
5343     }
5344     else if (anArgCase == "-extra"
5345           || anArgCase == "-extramsg"
5346           || anArgCase == "-extramessages")
5347     {
5348       Standard_Boolean toShow = Standard_True;
5349       if (++anArgIter < theArgNb
5350       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5351       {
5352         --anArgIter;
5353       }
5354       aDefCaps->suppressExtraMsg = !toShow;
5355       if (aCaps != NULL)
5356       {
5357         aCaps->suppressExtraMsg = !toShow;
5358       }
5359     }
5360     else if (anArgCase == "-noextra"
5361           || anArgCase == "-noextramsg"
5362           || anArgCase == "-noextramessages")
5363     {
5364       Standard_Boolean toSuppress = Standard_True;
5365       if (++anArgIter < theArgNb
5366       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5367       {
5368         --anArgIter;
5369       }
5370       aDefCaps->suppressExtraMsg = toSuppress;
5371       if (aCaps != NULL)
5372       {
5373         aCaps->suppressExtraMsg = toSuppress;
5374       }
5375     }
5376     else if (anArgCase == "-sync")
5377     {
5378       Standard_Boolean toSync = Standard_True;
5379       if (++anArgIter < theArgNb
5380       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5381       {
5382         --anArgIter;
5383       }
5384       aDefCaps->contextSyncDebug = toSync;
5385       if (toSync)
5386       {
5387         aDefCaps->contextDebug = Standard_True;
5388       }
5389     }
5390     else if (anArgCase == "-debug")
5391     {
5392       if (++anArgIter < theArgNb
5393       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5394       {
5395         --anArgIter;
5396       }
5397       aDefCaps->contextDebug = toEnableDebug;
5398     }
5399     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5400           && (anArgIter + 1 == theArgNb))
5401     {
5402       // simple alias to turn on almost everything
5403       aDefCaps->contextDebug     = toEnableDebug;
5404       aDefCaps->contextSyncDebug = toEnableDebug;
5405       aDefCaps->glslWarnings     = toEnableDebug;
5406     }
5407     else
5408     {
5409       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5410       return 1;
5411     }
5412   }
5413
5414   return 0;
5415 }
5416
5417 //==============================================================================
5418 //function : VVbo
5419 //purpose  :
5420 //==============================================================================
5421
5422 static int VVbo (Draw_Interpretor& theDI,
5423                  Standard_Integer  theArgNb,
5424                  const char**      theArgVec)
5425 {
5426   const Standard_Boolean toSet    = (theArgNb > 1);
5427   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5428   if (toSet)
5429   {
5430     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5431   }
5432
5433   // get the context
5434   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5435   if (aContextAIS.IsNull())
5436   {
5437     if (!toSet)
5438     {
5439       std::cerr << "No active view!\n";
5440     }
5441     return 1;
5442   }
5443   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5444   if (!aDriver.IsNull())
5445   {
5446     if (!toSet)
5447     {
5448       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5449     }
5450     else
5451     {
5452       aDriver->ChangeOptions().vboDisable = toUseVbo;
5453     }
5454   }
5455
5456   return 0;
5457 }
5458
5459 //==============================================================================
5460 //function : VCaps
5461 //purpose  :
5462 //==============================================================================
5463
5464 static int VCaps (Draw_Interpretor& theDI,
5465                   Standard_Integer  theArgNb,
5466                   const char**      theArgVec)
5467 {
5468   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5469   Handle(OpenGl_GraphicDriver)   aDriver;
5470   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5471   if (!aContext.IsNull())
5472   {
5473     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5474     aCaps   = &aDriver->ChangeOptions();
5475   }
5476
5477   if (theArgNb < 2)
5478   {
5479     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5480     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5481     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5482     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5483     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5484     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5485     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5486     return 0;
5487   }
5488
5489   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5490   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5491   {
5492     Standard_CString        anArg     = theArgVec[anArgIter];
5493     TCollection_AsciiString anArgCase (anArg);
5494     anArgCase.LowerCase();
5495     if (anUpdateTool.parseRedrawMode (anArg))
5496     {
5497       continue;
5498     }
5499     else if (anArgCase == "-vsync"
5500           || anArgCase == "-swapinterval")
5501     {
5502       Standard_Boolean toEnable = Standard_True;
5503       if (++anArgIter < theArgNb
5504       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5505       {
5506         --anArgIter;
5507       }
5508       aCaps->swapInterval = toEnable;
5509     }
5510     else if (anArgCase == "-ffp")
5511     {
5512       Standard_Boolean toEnable = Standard_True;
5513       if (++anArgIter < theArgNb
5514       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5515       {
5516         --anArgIter;
5517       }
5518       aCaps->ffpEnable = toEnable;
5519     }
5520     else if (anArgCase == "-vbo")
5521     {
5522       Standard_Boolean toEnable = Standard_True;
5523       if (++anArgIter < theArgNb
5524       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5525       {
5526         --anArgIter;
5527       }
5528       aCaps->vboDisable = !toEnable;
5529     }
5530     else if (anArgCase == "-sprite"
5531           || anArgCase == "-sprites")
5532     {
5533       Standard_Boolean toEnable = Standard_True;
5534       if (++anArgIter < theArgNb
5535       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5536       {
5537         --anArgIter;
5538       }
5539       aCaps->pntSpritesDisable = !toEnable;
5540     }
5541     else if (anArgCase == "-softmode")
5542     {
5543       Standard_Boolean toEnable = Standard_True;
5544       if (++anArgIter < theArgNb
5545       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5546       {
5547         --anArgIter;
5548       }
5549       aCaps->contextNoAccel = toEnable;
5550     }
5551     else if (anArgCase == "-accel"
5552           || anArgCase == "-acceleration")
5553     {
5554       Standard_Boolean toEnable = Standard_True;
5555       if (++anArgIter < theArgNb
5556       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5557       {
5558         --anArgIter;
5559       }
5560       aCaps->contextNoAccel = !toEnable;
5561     }
5562     else if (anArgCase == "-compat"
5563           || anArgCase == "-compatprofile"
5564           || anArgCase == "-compatible"
5565           || anArgCase == "-compatibleprofile")
5566     {
5567       Standard_Boolean toEnable = Standard_True;
5568       if (++anArgIter < theArgNb
5569       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5570       {
5571         --anArgIter;
5572       }
5573       aCaps->contextCompatible = toEnable;
5574       if (!aCaps->contextCompatible)
5575       {
5576         aCaps->ffpEnable = Standard_False;
5577       }
5578     }
5579     else if (anArgCase == "-core"
5580           || anArgCase == "-coreprofile")
5581     {
5582       Standard_Boolean toEnable = Standard_True;
5583       if (++anArgIter < theArgNb
5584       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5585       {
5586         --anArgIter;
5587       }
5588       aCaps->contextCompatible = !toEnable;
5589       if (!aCaps->contextCompatible)
5590       {
5591         aCaps->ffpEnable = Standard_False;
5592       }
5593     }
5594     else if (anArgCase == "-stereo"
5595           || anArgCase == "-quadbuffer")
5596     {
5597       Standard_Boolean toEnable = Standard_True;
5598       if (++anArgIter < theArgNb
5599       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5600       {
5601         --anArgIter;
5602       }
5603       aCaps->contextStereo = toEnable;
5604     }
5605     else
5606     {
5607       std::cout << "Error: unknown argument '" << anArg << "'\n";
5608       return 1;
5609     }
5610   }
5611   if (aCaps != &ViewerTest_myDefaultCaps)
5612   {
5613     ViewerTest_myDefaultCaps = *aCaps;
5614   }
5615   return 0;
5616 }
5617
5618 //==============================================================================
5619 //function : VMemGpu
5620 //purpose  :
5621 //==============================================================================
5622
5623 static int VMemGpu (Draw_Interpretor& theDI,
5624                     Standard_Integer  theArgNb,
5625                     const char**      theArgVec)
5626 {
5627   // get the context
5628   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5629   if (aContextAIS.IsNull())
5630   {
5631     std::cerr << "No active view. Please call vinit.\n";
5632     return 1;
5633   }
5634
5635   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5636   if (aDriver.IsNull())
5637   {
5638     std::cerr << "Graphic driver not available.\n";
5639     return 1;
5640   }
5641
5642   Standard_Size aFreeBytes = 0;
5643   TCollection_AsciiString anInfo;
5644   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5645   {
5646     std::cerr << "Information not available.\n";
5647     return 1;
5648   }
5649
5650   if (theArgNb > 1 && *theArgVec[1] == 'f')
5651   {
5652     theDI << Standard_Real (aFreeBytes);
5653   }
5654   else
5655   {
5656     theDI << anInfo;
5657   }
5658
5659   return 0;
5660 }
5661
5662 // ==============================================================================
5663 // function : VReadPixel
5664 // purpose  :
5665 // ==============================================================================
5666 static int VReadPixel (Draw_Interpretor& theDI,
5667                        Standard_Integer  theArgNb,
5668                        const char**      theArgVec)
5669 {
5670   // get the active view
5671   Handle(V3d_View) aView = ViewerTest::CurrentView();
5672   if (aView.IsNull())
5673   {
5674     std::cerr << "No active view. Please call vinit.\n";
5675     return 1;
5676   }
5677   else if (theArgNb < 3)
5678   {
5679     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5680     return 1;
5681   }
5682
5683   Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
5684   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
5685
5686   Standard_Integer aWidth, aHeight;
5687   aView->Window()->Size (aWidth, aHeight);
5688   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5689   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5690   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5691   {
5692     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5693     return 1;
5694   }
5695
5696   Standard_Boolean toShowName = Standard_False;
5697   Standard_Boolean toShowHls  = Standard_False;
5698   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5699   {
5700     const char* aParam = theArgVec[anIter];
5701     if ( strcasecmp( aParam, "rgb" ) == 0 )
5702     {
5703       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
5704       aBufferType = Graphic3d_BT_RGB;
5705     }
5706     else if ( strcasecmp( aParam, "hls" ) == 0 )
5707     {
5708       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
5709       aBufferType = Graphic3d_BT_RGB;
5710       toShowHls   = Standard_True;
5711     }
5712     else if ( strcasecmp( aParam, "rgbf" ) == 0 )
5713     {
5714       aFormat     = Image_PixMap::ImgRGBF;
5715       aBufferType = Graphic3d_BT_RGB;
5716     }
5717     else if ( strcasecmp( aParam, "rgba" ) == 0 )
5718     {
5719       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
5720       aBufferType = Graphic3d_BT_RGBA;
5721     }
5722     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
5723     {
5724       aFormat     = Image_PixMap::ImgRGBAF;
5725       aBufferType = Graphic3d_BT_RGBA;
5726     }
5727     else if ( strcasecmp( aParam, "depth" ) == 0 )
5728     {
5729       aFormat     = Image_PixMap::ImgGrayF;
5730       aBufferType = Graphic3d_BT_Depth;
5731     }
5732     else if ( strcasecmp( aParam, "name" ) == 0 )
5733     {
5734       toShowName = Standard_True;
5735     }
5736   }
5737
5738   Image_PixMap anImage;
5739   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5740   {
5741     std::cerr << "Image allocation failed\n";
5742     return 1;
5743   }
5744   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5745   {
5746     std::cerr << "Image dump failed\n";
5747     return 1;
5748   }
5749
5750   Quantity_Parameter anAlpha;
5751   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5752   if (toShowName)
5753   {
5754     if (aBufferType == Graphic3d_BT_RGBA)
5755     {
5756       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5757     }
5758     else
5759     {
5760       theDI << Quantity_Color::StringName (aColor.Name());
5761     }
5762   }
5763   else
5764   {
5765     switch (aBufferType)
5766     {
5767       default:
5768       case Graphic3d_BT_RGB:
5769       {
5770         if (toShowHls)
5771         {
5772           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5773         }
5774         else
5775         {
5776           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5777         }
5778         break;
5779       }
5780       case Graphic3d_BT_RGBA:
5781       {
5782         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5783         break;
5784       }
5785       case Graphic3d_BT_Depth:
5786       {
5787         theDI << aColor.Red();
5788         break;
5789       }
5790     }
5791   }
5792
5793   return 0;
5794 }
5795
5796 //==============================================================================
5797 //function : VDiffImage
5798 //purpose  : The draw-command compares two images.
5799 //==============================================================================
5800
5801 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5802 {
5803   if (theArgNb < 6)
5804   {
5805     theDI << "Not enough arguments.\n";
5806     return 1;
5807   }
5808
5809   // image file names
5810   const char* anImgPathRef = theArgVec[1];
5811   const char* anImgPathNew = theArgVec[2];
5812
5813   // get string tolerance and check its validity
5814   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5815   if (aTolColor < 0.0)
5816     aTolColor = 0.0;
5817   if (aTolColor > 1.0)
5818     aTolColor = 1.0;
5819
5820   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5821   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5822
5823   // image file of difference
5824   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5825
5826   // compare the images
5827   Image_Diff aComparer;
5828   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5829   {
5830     return 1;
5831   }
5832
5833   aComparer.SetColorTolerance (aTolColor);
5834   aComparer.SetBorderFilterOn (isBorderFilterOn);
5835   Standard_Integer aDiffColorsNb = aComparer.Compare();
5836   theDI << aDiffColorsNb << "\n";
5837
5838   // save image of difference
5839   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5840   {
5841     aComparer.SaveDiffImage (aDiffImagePath);
5842   }
5843
5844   return 0;
5845 }
5846
5847 //=======================================================================
5848 //function : VSelect
5849 //purpose  : Emulates different types of selection by mouse:
5850 //           1) single click selection
5851 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5852 //           3) selection with polygon having corners at
5853 //           pixel positions (x1,y1),...,(xn,yn)
5854 //           4) any of these selections with shift button pressed
5855 //=======================================================================
5856 static Standard_Integer VSelect (Draw_Interpretor& di,
5857                                  Standard_Integer argc,
5858                                  const char ** argv)
5859 {
5860   if(argc < 3)
5861   {
5862     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5863     return 1;
5864   }
5865
5866   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5867   if(myAIScontext.IsNull())
5868   {
5869     di << "use 'vinit' command before " << argv[0] << "\n";
5870     return 1;
5871   }
5872
5873   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5874   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5875   TCollection_AsciiString anArg;
5876   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5877   anArg.LowerCase();
5878   if (anArg == "-allowoverlap")
5879   {
5880     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5881       : argc == 7;
5882     if (!isValidated)
5883     {
5884       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5885       return 1;
5886     }
5887
5888     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5889     myAIScontext->MainSelector()->AllowOverlapDetection((Standard_Boolean)isToAllow);
5890     aCoordsNb -= 2;
5891   }
5892
5893   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5894   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5895   if(aCoordsNb == 2)
5896   {
5897     if(isShiftSelection)
5898       aCurrentEventManager->ShiftSelect();
5899     else
5900       aCurrentEventManager->Select();
5901   }
5902   else if(aCoordsNb == 4)
5903   {
5904     if(isShiftSelection)
5905       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5906     else
5907       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5908   }
5909   else
5910   {
5911     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
5912
5913     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
5914       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
5915
5916     if(isShiftSelection)
5917       aCurrentEventManager->ShiftSelect(aPolyline);
5918     else
5919       aCurrentEventManager->Select(aPolyline);
5920   }
5921   return 0;
5922 }
5923
5924 //=======================================================================
5925 //function : VMoveTo
5926 //purpose  : Emulates cursor movement to defined pixel position
5927 //=======================================================================
5928 static Standard_Integer VMoveTo (Draw_Interpretor& di,
5929                                 Standard_Integer argc,
5930                                 const char ** argv)
5931 {
5932   if(argc != 3)
5933   {
5934     di << "Usage : " << argv[0] << " x y\n";
5935     return 1;
5936   }
5937
5938   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5939   if(aContext.IsNull())
5940   {
5941     di << "use 'vinit' command before " << argv[0] << "\n";
5942     return 1;
5943   }
5944   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
5945   return 0;
5946 }
5947
5948 //=================================================================================================
5949 //function : VViewParams
5950 //purpose  : Gets or sets AIS View characteristics
5951 //=================================================================================================
5952 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
5953 {
5954   Handle(V3d_View) anAISView = ViewerTest::CurrentView();
5955   if (anAISView.IsNull())
5956   {
5957     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
5958     return 1;
5959   }
5960
5961   if (theArgsNb == 1)
5962   {
5963     // print all of the available view parameters
5964     Quantity_Factor anAISViewScale = anAISView->Scale();
5965
5966     Standard_Real anAISViewProjX = 0.0;
5967     Standard_Real anAISViewProjY = 0.0;
5968     Standard_Real anAISViewProjZ = 0.0;
5969     anAISView->Proj (anAISViewProjX, anAISViewProjY, anAISViewProjZ);
5970
5971     Standard_Real anAISViewUpX = 0.0;
5972     Standard_Real anAISViewUpY = 0.0;
5973     Standard_Real anAISViewUpZ = 0.0;
5974     anAISView->Up (anAISViewUpX, anAISViewUpY, anAISViewUpZ);
5975
5976     Standard_Real anAISViewAtX = 0.0;
5977     Standard_Real anAISViewAtY = 0.0;
5978     Standard_Real anAISViewAtZ = 0.0;
5979     anAISView->At (anAISViewAtX, anAISViewAtY, anAISViewAtZ);
5980
5981     Standard_Real anAISViewEyeX = 0.0;
5982     Standard_Real anAISViewEyeY = 0.0;
5983     Standard_Real anAISViewEyeZ = 0.0;
5984     anAISView->Eye (anAISViewEyeX, anAISViewEyeY, anAISViewEyeZ);
5985
5986     theDi << "Scale of current view: " << anAISViewScale << "\n";
5987     theDi << "Proj on X : " << anAISViewProjX << "; on Y: " << anAISViewProjY << "; on Z: " << anAISViewProjZ << "\n";
5988     theDi << "Up on X : " << anAISViewUpX << "; on Y: " << anAISViewUpY << "; on Z: " << anAISViewUpZ << "\n";
5989     theDi << "At on X : " << anAISViewAtX << "; on Y: " << anAISViewAtY << "; on Z: " << anAISViewAtZ << "\n";
5990     theDi << "Eye on X : " << anAISViewEyeX << "; on Y: " << anAISViewEyeY << "; on Z: " << anAISViewEyeZ << "\n";
5991     return 0;
5992   }
5993
5994   // -------------------------
5995   //  Parse options and values
5996   // -------------------------
5997
5998   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfKeysByValues;
5999   TCollection_AsciiString aParseKey;
6000   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
6001   {
6002     TCollection_AsciiString anArg (theArgVec [anArgIt]);
6003
6004     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
6005     {
6006       aParseKey = anArg;
6007       aParseKey.Remove (1);
6008       aParseKey.UpperCase();
6009       aMapOfKeysByValues.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
6010       continue;
6011     }
6012
6013     if (aParseKey.IsEmpty())
6014     {
6015       std::cout << theArgVec[0] << ": values should be passed with key.\n";
6016       std::cout << "Type help for more information.\n";
6017       return 1;
6018     }
6019
6020     aMapOfKeysByValues(aParseKey)->Append (anArg);
6021   }
6022
6023   // ---------------------------------------------
6024   //  Change or print parameters, order plays role
6025   // ---------------------------------------------
6026
6027   // Check arguments for validity
6028   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfKeysByValues);
6029   for (; aMapIt.More(); aMapIt.Next())
6030   {
6031     const TCollection_AsciiString& aKey = aMapIt.Key();
6032     const Handle(TColStd_HSequenceOfAsciiString)& aValues = aMapIt.Value();
6033
6034     if (!(aKey.IsEqual ("SCALE")  && (aValues->Length() == 1 || aValues->IsEmpty()))
6035      && !(aKey.IsEqual ("SIZE")   && (aValues->Length() == 1 || aValues->IsEmpty()))
6036      && !(aKey.IsEqual ("EYE")    && (aValues->Length() == 3 || aValues->IsEmpty()))
6037      && !(aKey.IsEqual ("AT")     && (aValues->Length() == 3 || aValues->IsEmpty()))
6038      && !(aKey.IsEqual ("UP")     && (aValues->Length() == 3 || aValues->IsEmpty()))
6039      && !(aKey.IsEqual ("PROJ")   && (aValues->Length() == 3 || aValues->IsEmpty()))
6040      && !(aKey.IsEqual ("CENTER") &&  aValues->Length() == 2))
6041     {
6042       TCollection_AsciiString aLowerKey;
6043       aLowerKey  = "-";
6044       aLowerKey += aKey;
6045       aLowerKey.LowerCase();
6046       std::cout << theArgVec[0] << ": " << aLowerKey << " is unknown option, or number of arguments is invalid.\n";
6047       std::cout << "Type help for more information.\n";
6048       return 1;
6049     }
6050   }
6051
6052   Handle(TColStd_HSequenceOfAsciiString) aValues;
6053
6054   // Change view parameters in proper order
6055   if (aMapOfKeysByValues.Find ("SCALE", aValues))
6056   {
6057     if (aValues->IsEmpty())
6058     {
6059       theDi << "Scale: " << anAISView->Scale() << "\n";
6060     }
6061     else
6062     {
6063       anAISView->SetScale (aValues->Value(1).RealValue());
6064     }
6065   }
6066   if (aMapOfKeysByValues.Find ("SIZE", aValues))
6067   {
6068     if (aValues->IsEmpty())
6069     {
6070       Standard_Real aSizeX = 0.0;
6071       Standard_Real aSizeY = 0.0;
6072       anAISView->Size (aSizeX, aSizeY);
6073       theDi << "Size X: " << aSizeX << " Y: " << aSizeY << "\n";
6074     }
6075     else
6076     {
6077       anAISView->SetSize (aValues->Value(1).RealValue());
6078     }
6079   }
6080   if (aMapOfKeysByValues.Find ("EYE", aValues))
6081   {
6082     if (aValues->IsEmpty())
6083     {
6084       Standard_Real anEyeX = 0.0;
6085       Standard_Real anEyeY = 0.0;
6086       Standard_Real anEyeZ = 0.0;
6087       anAISView->Eye (anEyeX, anEyeY, anEyeZ);
6088       theDi << "Eye X: " << anEyeX << " Y: " << anEyeY << " Z: " << anEyeZ << "\n";
6089     }
6090     else
6091     {
6092       anAISView->SetEye (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
6093     }
6094   }
6095   if (aMapOfKeysByValues.Find ("AT", aValues))
6096   {
6097     if (aValues->IsEmpty())
6098     {
6099       Standard_Real anAtX = 0.0;
6100       Standard_Real anAtY = 0.0;
6101       Standard_Real anAtZ = 0.0;
6102       anAISView->At (anAtX, anAtY, anAtZ);
6103       theDi << "At X: " << anAtX << " Y: " << anAtY << " Z: " << anAtZ << "\n";
6104     }
6105     else
6106     {
6107       anAISView->SetAt (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
6108     }
6109   }
6110   if (aMapOfKeysByValues.Find ("PROJ", aValues))
6111   {
6112     if (aValues->IsEmpty())
6113     {
6114       Standard_Real aProjX = 0.0;
6115       Standard_Real aProjY = 0.0;
6116       Standard_Real aProjZ = 0.0;
6117       anAISView->Proj (aProjX, aProjY, aProjZ);
6118       theDi << "Proj X: " << aProjX << " Y: " << aProjY << " Z: " << aProjZ << "\n";
6119     }
6120     else
6121     {
6122       anAISView->SetProj (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
6123     }
6124   }
6125   if (aMapOfKeysByValues.Find ("UP", aValues))
6126   {
6127     if (aValues->IsEmpty())
6128     {
6129       Standard_Real anUpX = 0.0;
6130       Standard_Real anUpY = 0.0;
6131       Standard_Real anUpZ = 0.0;
6132       anAISView->Up (anUpX, anUpY, anUpZ);
6133       theDi << "Up X: " << anUpX << " Y: " << anUpY << " Z: " << anUpZ << "\n";
6134     }
6135     else
6136     {
6137       anAISView->SetUp (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
6138     }
6139   }
6140   if (aMapOfKeysByValues.Find ("CENTER", aValues))
6141   {
6142     anAISView->SetCenter (aValues->Value(1).IntegerValue(), aValues->Value(2).IntegerValue());
6143   }
6144
6145   return 0;
6146 }
6147
6148 //=======================================================================
6149 //function : VChangeSelected
6150 //purpose  : Adds the shape to selection or remove one from it
6151 //=======================================================================
6152 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6153                                 Standard_Integer argc,
6154                                 const char ** argv)
6155 {
6156   if(argc != 2)
6157   {
6158     di<<"Usage : " << argv[0] << " shape \n";
6159     return 1;
6160   }
6161   //get AIS_Shape:
6162   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6163   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6164   TCollection_AsciiString aName(argv[1]);
6165   Handle(AIS_InteractiveObject) anAISObject;
6166
6167   if(!aMap.IsBound2(aName))
6168   {
6169     di<<"Use 'vdisplay' before";
6170     return 1;
6171   }
6172   else
6173   {
6174     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6175     if(anAISObject.IsNull()){
6176       di<<"No interactive object \n";
6177       return 1;
6178     }
6179
6180     aContext->AddOrRemoveSelected(anAISObject);
6181   }
6182   return 0;
6183 }
6184
6185 //=======================================================================
6186 //function : VZClipping
6187 //purpose  : Gets or sets ZClipping mode, width and depth
6188 //=======================================================================
6189 static Standard_Integer VZClipping (Draw_Interpretor& di,
6190                                 Standard_Integer argc,
6191                                 const char ** argv)
6192 {
6193   if(argc>4)
6194   {
6195     di << "Usage : " << argv[0] << " [mode] [depth  width]\n"
6196       <<"mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]\n";
6197     return -1;
6198   }
6199   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6200   if(aContext.IsNull())
6201   {
6202     di << "use 'vinit' command before " << argv[0] << "\n";
6203     return 1;
6204   }
6205   Handle(V3d_View) aView = ViewerTest::CurrentView();
6206   V3d_TypeOfZclipping aZClippingMode = V3d_OFF;
6207   if(argc==1)
6208   {
6209     TCollection_AsciiString aZClippingModeString;
6210     Quantity_Length aDepth, aWidth;
6211     aZClippingMode = aView->ZClipping(aDepth, aWidth);
6212     switch (aZClippingMode)
6213     {
6214     case V3d_OFF:
6215       aZClippingModeString.Copy("OFF");
6216       break;
6217     case V3d_BACK:
6218       aZClippingModeString.Copy("BACK");
6219       break;
6220     case V3d_FRONT:
6221       aZClippingModeString.Copy("FRONT");
6222       break;
6223     case V3d_SLICE:
6224       aZClippingModeString.Copy("SLICE");
6225       break;
6226     default:
6227       aZClippingModeString.Copy(TCollection_AsciiString(aZClippingMode));
6228       break;
6229     }
6230     di << "ZClippingMode = " << aZClippingModeString.ToCString() << "\n"
6231       << "ZClipping depth = " << aDepth << "\n"
6232       << "ZClipping width = " << aWidth << "\n";
6233   }
6234   else
6235   {
6236     if(argc !=3)
6237     {
6238       Standard_Integer aStatus = 0;
6239       if ( strcmp (argv [1], "OFF") == 0 ) {
6240         aStatus = 1;
6241         aZClippingMode = V3d_OFF;
6242       }
6243       if ( strcmp (argv [1], "BACK") == 0 ) {
6244         aStatus = 1;
6245         aZClippingMode = V3d_BACK;
6246       }
6247       if ( strcmp (argv [1], "FRONT") == 0 ) {
6248         aStatus = 1;
6249         aZClippingMode = V3d_FRONT;
6250       }
6251       if ( strcmp (argv [1], "SLICE") == 0 ) {
6252         aStatus = 1;
6253         aZClippingMode = V3d_SLICE;
6254       }
6255       if (aStatus != 1)
6256       {
6257         di << "Bad mode; Usage : " << argv[0] << " [mode] [depth width]\n"
6258           << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]\n";
6259         return 1;
6260       }
6261       aView->SetZClippingType(aZClippingMode);
6262     }
6263     if(argc >2)
6264     {
6265       Quantity_Length aDepth = 0., aWidth = 1.;
6266       if(argc == 3)
6267       {
6268         aDepth = Draw::Atof (argv[1]);
6269         aWidth = Draw::Atof (argv[2]);
6270       }
6271       else if(argc == 4)
6272       {
6273         aDepth = Draw::Atof (argv[2]);
6274         aWidth = Draw::Atof (argv[3]);
6275       }
6276
6277       if(aDepth<0. || aDepth>1.)
6278       {
6279         di << "Bad depth; Usage : " << argv[0] << " [mode] [depth width]\n"
6280         << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]\n";
6281         return 1;
6282       }
6283       if(aWidth<0. || aWidth>1.)
6284       {
6285         di << "Bad width; Usage : " << argv[0] << " [mode] [depth width]\n"
6286         << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]\n";
6287         return 1;
6288       }
6289
6290       aView->SetZClippingDepth(aDepth);
6291       aView->SetZClippingWidth(aWidth);
6292     }
6293     aView->Redraw();
6294   }
6295   return 0;
6296 }
6297
6298 //=======================================================================
6299 //function : VNbSelected
6300 //purpose  : Returns number of selected objects
6301 //=======================================================================
6302 static Standard_Integer VNbSelected (Draw_Interpretor& di,
6303                                 Standard_Integer argc,
6304                                 const char ** argv)
6305 {
6306   if(argc != 1)
6307   {
6308     di << "Usage : " << argv[0] << "\n";
6309     return 1;
6310   }
6311   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6312   if(aContext.IsNull())
6313   {
6314     di << "use 'vinit' command before " << argv[0] << "\n";
6315     return 1;
6316   }
6317   di << aContext->NbSelected() << "\n";
6318   return 0;
6319 }
6320
6321 //=======================================================================
6322 //function : VAntialiasing
6323 //purpose  : Switches altialiasing on or off
6324 //=======================================================================
6325 static Standard_Integer VAntialiasing (Draw_Interpretor& di,
6326                                 Standard_Integer argc,
6327                                 const char ** argv)
6328 {
6329   if(argc > 2)
6330   {
6331     di << "Usage : " << argv[0] << " [1|0]\n";
6332     return 1;
6333   }
6334
6335   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6336   if(aContext.IsNull())
6337   {
6338     di << "use 'vinit' command before " << argv[0] << "\n";
6339     return 1;
6340   }
6341
6342   Handle(V3d_View) aView = ViewerTest::CurrentView();
6343
6344   if((argc == 2) && (atof(argv[1]) == 0))
6345     aView->SetAntialiasingOff();
6346   else
6347     aView->SetAntialiasingOn();
6348   aView->Update();
6349   return 0;
6350 }
6351
6352 //=======================================================================
6353 //function : VPurgeDisplay
6354 //purpose  : Switches altialiasing on or off
6355 //=======================================================================
6356 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
6357                                 Standard_Integer argc,
6358                                 const char ** argv)
6359 {
6360   if (argc > 1)
6361   {
6362     di << "Usage : " << argv[0] << "\n";
6363     return 1;
6364   }
6365   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6366   if (aContext.IsNull())
6367   {
6368     di << "use 'vinit' command before " << argv[0] << "\n";
6369     return 1;
6370   }
6371   aContext->CloseAllContexts(Standard_False);
6372   di << aContext->PurgeDisplay() << "\n";
6373   return 0;
6374 }
6375
6376 //=======================================================================
6377 //function : VSetViewSize
6378 //purpose  :
6379 //=======================================================================
6380 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
6381                                 Standard_Integer argc,
6382                                 const char ** argv)
6383 {
6384   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6385   if(aContext.IsNull())
6386   {
6387     di << "use 'vinit' command before " << argv[0] << "\n";
6388     return 1;
6389   }
6390   if(argc != 2)
6391   {
6392     di<<"Usage : " << argv[0] << " Size\n";
6393     return 1;
6394   }
6395   Standard_Real aSize = Draw::Atof (argv[1]);
6396   if (aSize <= 0.)
6397   {
6398     di<<"Bad Size value  : " << aSize << "\n";
6399     return 1;
6400   }
6401
6402   Handle(V3d_View) aView = ViewerTest::CurrentView();
6403   aView->SetSize(aSize);
6404   return 0;
6405 }
6406
6407 //=======================================================================
6408 //function : VMoveView
6409 //purpose  :
6410 //=======================================================================
6411 static Standard_Integer VMoveView (Draw_Interpretor& di,
6412                                 Standard_Integer argc,
6413                                 const char ** argv)
6414 {
6415   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6416   if(aContext.IsNull())
6417   {
6418     di << "use 'vinit' command before " << argv[0] << "\n";
6419     return 1;
6420   }
6421   if(argc < 4 || argc > 5)
6422   {
6423     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
6424     return 1;
6425   }
6426   Standard_Real Dx = Draw::Atof (argv[1]);
6427   Standard_Real Dy = Draw::Atof (argv[2]);
6428   Standard_Real Dz = Draw::Atof (argv[3]);
6429   Standard_Boolean aStart = Standard_True;
6430   if (argc == 5)
6431   {
6432       aStart = (Draw::Atoi (argv[4]) > 0);
6433   }
6434
6435   Handle(V3d_View) aView = ViewerTest::CurrentView();
6436   aView->Move(Dx,Dy,Dz,aStart);
6437   return 0;
6438 }
6439
6440 //=======================================================================
6441 //function : VTranslateView
6442 //purpose  :
6443 //=======================================================================
6444 static Standard_Integer VTranslateView (Draw_Interpretor& di,
6445                                 Standard_Integer argc,
6446                                 const char ** argv)
6447 {
6448   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6449   if(aContext.IsNull())
6450   {
6451     di << "use 'vinit' command before " << argv[0] << "\n";
6452     return 1;
6453   }
6454   if(argc < 4 || argc > 5)
6455   {
6456     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
6457     return 1;
6458   }
6459   Standard_Real Dx = Draw::Atof (argv[1]);
6460   Standard_Real Dy = Draw::Atof (argv[2]);
6461   Standard_Real Dz = Draw::Atof (argv[3]);
6462   Standard_Boolean aStart = Standard_True;
6463   if (argc == 5)
6464   {
6465       aStart = (Draw::Atoi (argv[4]) > 0);
6466   }
6467
6468   Handle(V3d_View) aView = ViewerTest::CurrentView();
6469   aView->Translate(Dx,Dy,Dz,aStart);
6470   return 0;
6471 }
6472
6473 //=======================================================================
6474 //function : VTurnView
6475 //purpose  :
6476 //=======================================================================
6477 static Standard_Integer VTurnView (Draw_Interpretor& di,
6478                                 Standard_Integer argc,
6479                                 const char ** argv)
6480 {
6481   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6482   if(aContext.IsNull()) {
6483     di << "use 'vinit' command before " << argv[0] << "\n";
6484     return 1;
6485   }
6486   if(argc < 4 || argc > 5){
6487     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
6488     return 1;
6489   }
6490   Standard_Real Ax = Draw::Atof (argv[1]);
6491   Standard_Real Ay = Draw::Atof (argv[2]);
6492   Standard_Real Az = Draw::Atof (argv[3]);
6493   Standard_Boolean aStart = Standard_True;
6494   if (argc == 5)
6495   {
6496       aStart = (Draw::Atoi (argv[4]) > 0);
6497   }
6498
6499   Handle(V3d_View) aView = ViewerTest::CurrentView();
6500   aView->Turn(Ax,Ay,Az,aStart);
6501   return 0;
6502 }
6503
6504 //==============================================================================
6505 //function : VTextureEnv
6506 //purpose  : ENables or disables environment mapping
6507 //==============================================================================
6508 class OCC_TextureEnv : public Graphic3d_TextureEnv
6509 {
6510 public:
6511   OCC_TextureEnv(const Standard_CString FileName);
6512   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
6513   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
6514                             const Standard_Boolean theModulateFlag,
6515                             const Graphic3d_TypeOfTextureFilter theFilter,
6516                             const Standard_ShortReal theXScale,
6517                             const Standard_ShortReal theYScale,
6518                             const Standard_ShortReal theXShift,
6519                             const Standard_ShortReal theYShift,
6520                             const Standard_ShortReal theAngle);
6521   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
6522 };
6523 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
6524
6525 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
6526   : Graphic3d_TextureEnv(theFileName)
6527 {
6528 }
6529
6530 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
6531   : Graphic3d_TextureEnv(theTexId)
6532 {
6533 }
6534
6535 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
6536                                           const Standard_Boolean theModulateFlag,
6537                                           const Graphic3d_TypeOfTextureFilter theFilter,
6538                                           const Standard_ShortReal theXScale,
6539                                           const Standard_ShortReal theYScale,
6540                                           const Standard_ShortReal theXShift,
6541                                           const Standard_ShortReal theYShift,
6542                                           const Standard_ShortReal theAngle)
6543 {
6544   myParams->SetRepeat     (theRepeatFlag);
6545   myParams->SetModulate   (theModulateFlag);
6546   myParams->SetFilter     (theFilter);
6547   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
6548   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
6549   myParams->SetRotation   (theAngle);
6550 }
6551
6552 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
6553 {
6554   // get the active view
6555   Handle(V3d_View) aView = ViewerTest::CurrentView();
6556   if (aView.IsNull())
6557   {
6558     std::cerr << "No active view. Please call vinit.\n";
6559     return 1;
6560   }
6561
6562   // Checking the input arguments
6563   Standard_Boolean anEnableFlag = Standard_False;
6564   Standard_Boolean isOk         = theArgNb >= 2;
6565   if (isOk)
6566   {
6567     TCollection_AsciiString anEnableOpt(theArgVec[1]);
6568     anEnableFlag = anEnableOpt.IsEqual("on");
6569     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
6570   }
6571   if (anEnableFlag)
6572   {
6573     isOk = (theArgNb == 3 || theArgNb == 11);
6574     if (isOk)
6575     {
6576       TCollection_AsciiString aTextureOpt(theArgVec[2]);
6577       isOk = (!aTextureOpt.IsIntegerValue() ||
6578              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
6579
6580       if (isOk && theArgNb == 11)
6581       {
6582         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
6583                                 aModulateOpt(theArgVec[4]),
6584                                 aFilterOpt  (theArgVec[5]),
6585                                 aSScaleOpt  (theArgVec[6]),
6586                                 aTScaleOpt  (theArgVec[7]),
6587                                 aSTransOpt  (theArgVec[8]),
6588                                 aTTransOpt  (theArgVec[9]),
6589                                 anAngleOpt  (theArgVec[10]);
6590         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
6591                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
6592                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
6593                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
6594                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
6595                 anAngleOpt.IsRealValue());
6596       }
6597     }
6598   }
6599
6600   if (!isOk)
6601   {
6602     std::cerr << "Usage :" << std::endl;
6603     std::cerr << theArgVec[0] << " off" << std::endl;
6604     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;
6605     return 1;
6606   }
6607
6608   if (anEnableFlag)
6609   {
6610     TCollection_AsciiString aTextureOpt(theArgVec[2]);
6611     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
6612                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
6613                                      new OCC_TextureEnv(theArgVec[2]);
6614
6615     if (theArgNb == 11)
6616     {
6617       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
6618       aTexEnv->SetTextureParameters(
6619         aRepeatOpt.  IsEqual("repeat"),
6620         aModulateOpt.IsEqual("modulate"),
6621         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
6622                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
6623                                                                            Graphic3d_TOTF_TRILINEAR,
6624         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
6625         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
6626         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
6627         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
6628         (Standard_ShortReal)Draw::Atof(theArgVec[10])
6629         );
6630     }
6631     aView->SetTextureEnv(aTexEnv);
6632   }
6633   else // Disabling environment mapping
6634   {
6635     Handle(Graphic3d_TextureEnv) aTexture;
6636     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
6637   }
6638
6639   aView->Redraw();
6640   return 0;
6641 }
6642
6643 //===============================================================================================
6644 //function : VClipPlane
6645 //purpose  :
6646 //===============================================================================================
6647 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6648 {
6649   // use short-cut for created clip planes map of created (or "registered by name") clip planes
6650   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
6651   static MapOfPlanes aRegPlanes;
6652
6653   if (theArgsNb < 2)
6654   {
6655     theDi << theArgVec[0] << ": command argument is required. Type help for more information.\n";
6656     return 1;
6657   }
6658
6659   TCollection_AsciiString aCommand (theArgVec[1]);
6660
6661   // print maximum number of planes for current viewer
6662   if (aCommand == "maxplanes")
6663   {
6664     if (theArgsNb < 3)
6665     {
6666       theDi << theArgVec[0] << ": view name is required. Type help for more information.\n";
6667       return 1;
6668     }
6669
6670     TCollection_AsciiString aViewName (theArgVec[2]);
6671
6672     if (!ViewerTest_myViews.IsBound1 (aViewName))
6673     {
6674       theDi << theArgVec[0] << ": view is not found.\n";
6675       return 1;
6676     }
6677
6678     const Handle(V3d_View)& aView = ViewerTest_myViews.Find1 (aViewName);
6679
6680     theDi << theArgVec[0] << ": "
6681                           << aView->Viewer()->Driver()->InquirePlaneLimit()
6682                           << " plane slots provided by driver."
6683                           << " Note that 2 more planes might be used (reserved for z-clipping).\n";
6684
6685     return 0;
6686   }
6687
6688   // create / delete plane instance
6689   if (aCommand == "create" || aCommand == "delete" || aCommand == "clone")
6690   {
6691     if (theArgsNb < 3)
6692     {
6693       theDi << theArgVec[0] << ": plane name is required. Type help for more information.\n";
6694       return 1;
6695     }
6696
6697     Standard_Boolean toCreate = (aCommand == "create");
6698     Standard_Boolean toClone  = (aCommand == "clone");
6699     TCollection_AsciiString aPlane (theArgVec[2]);
6700
6701     if (toCreate)
6702     {
6703       if (aRegPlanes.IsBound (aPlane))
6704       {
6705         theDi << theArgVec[0] << ": plane name is in use.\n";
6706         return 1;
6707       }
6708
6709       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
6710     }
6711     else if (toClone) // toClone
6712     {
6713       if (!aRegPlanes.IsBound (aPlane))
6714       {
6715         theDi << theArgVec[0] << ": no such plane.\n";
6716         return 1;
6717       }
6718
6719       if (theArgsNb < 4)
6720       {
6721         theDi << theArgVec[0] << ": enter name for new plane. Type help for more information.\n";
6722         return 1;
6723       }
6724
6725       TCollection_AsciiString aClone (theArgVec[3]);
6726       if (aRegPlanes.IsBound (aClone))
6727       {
6728         theDi << theArgVec[0] << ": plane name is in use.\n";
6729         return 1;
6730       }
6731
6732       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
6733
6734       aRegPlanes.Bind (aClone, aClipPlane->Clone());
6735     }
6736     else// toDelete
6737     {
6738       if (!aRegPlanes.IsBound (aPlane))
6739       {
6740         theDi << theArgVec[0] << ": no such plane.\n";
6741         return 1;
6742       }
6743
6744       Handle(Graphic3d_ClipPlane) aClipPlane = aRegPlanes.Find (aPlane);
6745       aRegPlanes.UnBind (aPlane);
6746
6747       ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
6748       for (; anIObjIt.More(); anIObjIt.Next())
6749       {
6750         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
6751         aPrs->RemoveClipPlane(aClipPlane);
6752       }
6753
6754       NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
6755       for (; aViewIt.More(); aViewIt.Next())
6756       {
6757         const Handle(V3d_View)& aView = aViewIt.Key2();
6758         aView->RemoveClipPlane(aClipPlane);
6759       }
6760
6761       ViewerTest::RedrawAllViews();
6762     }
6763
6764     return 0;
6765   }
6766
6767   // set / unset plane command
6768   if (aCommand == "set" || aCommand == "unset")
6769   {
6770     if (theArgsNb < 4)
6771     {
6772       theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6773       return 1;
6774     }
6775
6776     Standard_Boolean toSet = (aCommand == "set");
6777     TCollection_AsciiString aPlane (theArgVec [2]);
6778     if (!aRegPlanes.IsBound (aPlane))
6779     {
6780       theDi << theArgVec[0] << ": no such plane.\n";
6781       return 1;
6782     }
6783
6784     const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
6785
6786     TCollection_AsciiString aTarget (theArgVec [3]);
6787     if (aTarget != "object" && aTarget != "view")
6788     {
6789       theDi << theArgVec[0] << ": invalid target.\n";
6790       return 1;
6791     }
6792
6793     if (aTarget == "object" || aTarget == "view")
6794     {
6795       if (theArgsNb < 5)
6796       {
6797         theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6798         return 1;
6799       }
6800
6801       Standard_Boolean isObject = (aTarget == "object");
6802
6803       for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
6804       {
6805         TCollection_AsciiString anEntityName (theArgVec[anIt]);
6806         if (isObject) // to object
6807         {
6808           if (!GetMapOfAIS().IsBound2 (anEntityName))
6809           {
6810             theDi << theArgVec[0] << ": can not find IO with name " << anEntityName << ".\n";
6811             continue;
6812           }
6813
6814           Handle(AIS_InteractiveObject) aIObj =
6815             Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
6816
6817           if (toSet)
6818             aIObj->AddClipPlane (aClipPlane);
6819           else
6820             aIObj->RemoveClipPlane (aClipPlane);
6821         }
6822         else // to view
6823         {
6824           if (!ViewerTest_myViews.IsBound1 (anEntityName))
6825           {
6826             theDi << theArgVec[0] << ": can not find View with name " << anEntityName << ".\n";
6827             continue;
6828           }
6829
6830           Handle(V3d_View) aView = ViewerTest_myViews.Find1(anEntityName);
6831           if (toSet)
6832             aView->AddClipPlane (aClipPlane);
6833           else
6834             aView->RemoveClipPlane (aClipPlane);
6835         }
6836       }
6837
6838       ViewerTest::RedrawAllViews();
6839     }
6840
6841     return 0;
6842   }
6843
6844   // change plane command
6845   if (aCommand == "change")
6846   {
6847     if (theArgsNb < 4)
6848     {
6849       theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6850       return 1;
6851     }
6852
6853     TCollection_AsciiString aPlane (theArgVec [2]);
6854     if (!aRegPlanes.IsBound (aPlane))
6855     {
6856       theDi << theArgVec[0] << ": no such plane.\n";
6857       return 1;
6858     }
6859
6860     const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
6861
6862     TCollection_AsciiString aChangeArg (theArgVec [3]);
6863     if (aChangeArg != "on" && aChangeArg != "off" && aChangeArg != "capping" && aChangeArg != "equation")
6864     {
6865       theDi << theArgVec[0] << ": invalid arguments. Type help for more information.\n";
6866       return 1;
6867     }
6868
6869     if (aChangeArg == "on" || aChangeArg == "off") // on / off
6870     {
6871       aClipPlane->SetOn (aChangeArg == "on");
6872     }
6873     else if (aChangeArg == "equation") // change equation
6874     {
6875       if (theArgsNb < 8)
6876       {
6877         theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6878         return 1;
6879       }
6880
6881       Standard_Real aCoeffA = Draw::Atof (theArgVec [4]);
6882       Standard_Real aCoeffB = Draw::Atof (theArgVec [5]);
6883       Standard_Real aCoeffC = Draw::Atof (theArgVec [6]);
6884       Standard_Real aCoeffD = Draw::Atof (theArgVec [7]);
6885       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
6886     }
6887     else if (aChangeArg == "capping") // change capping aspects
6888     {
6889       if (theArgsNb < 5)
6890       {
6891         theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6892         return 1;
6893       }
6894
6895       TCollection_AsciiString aCappingArg (theArgVec [4]);
6896       if (aCappingArg != "on" && aCappingArg != "off" &&
6897           aCappingArg != "color" && aCappingArg != "texname" &&
6898           aCappingArg != "texscale" && aCappingArg != "texorigin" &&
6899           aCappingArg != "texrotate" && aCappingArg != "hatch")
6900       {
6901         theDi << theArgVec[0] << ": invalid arguments. Type help for more information.\n";
6902         return 1;
6903       }
6904
6905       if (aCappingArg == "on" || aCappingArg == "off") // on / off capping
6906       {
6907         aClipPlane->SetCapping (aCappingArg == "on");
6908       }
6909       else if (aCappingArg == "color") // color aspect for capping
6910       {
6911         if (theArgsNb < 8)
6912         {
6913           theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6914           return 1;
6915         }
6916
6917         Standard_Real aRed = Draw::Atof (theArgVec [5]);
6918         Standard_Real aGrn = Draw::Atof (theArgVec [6]);
6919         Standard_Real aBlu = Draw::Atof (theArgVec [7]);
6920
6921         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
6922         Quantity_Color aColor (aRed, aGrn, aBlu, Quantity_TOC_RGB);
6923         aMat.SetAmbientColor (aColor);
6924         aMat.SetDiffuseColor (aColor);
6925         aClipPlane->SetCappingMaterial (aMat);
6926       }
6927       else if (aCappingArg == "texname") // texture name
6928       {
6929         if (theArgsNb < 6)
6930         {
6931           theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6932           return 1;
6933         }
6934
6935         TCollection_AsciiString aTextureName (theArgVec [5]);
6936
6937         Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
6938         if (!aTexture->IsDone ())
6939         {
6940           aClipPlane->SetCappingTexture (NULL);
6941         }
6942         else
6943         {
6944           aTexture->EnableModulate();
6945           aTexture->EnableRepeat();
6946           aClipPlane->SetCappingTexture (aTexture);
6947         }
6948       }
6949       else if (aCappingArg == "texscale") // texture scale
6950       {
6951         if (aClipPlane->CappingTexture().IsNull())
6952         {
6953           theDi << theArgVec[0] << ": no texture is set.\n";
6954           return 1;
6955         }
6956
6957         if (theArgsNb < 7)
6958         {
6959           theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6960           return 1;
6961         }
6962
6963         Standard_ShortReal aSx = (Standard_ShortReal)atof (theArgVec [5]);
6964         Standard_ShortReal aSy = (Standard_ShortReal)atof (theArgVec [6]);
6965
6966         aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
6967       }
6968       else if (aCappingArg == "texorigin") // texture origin
6969       {
6970         if (aClipPlane->CappingTexture().IsNull())
6971         {
6972           theDi << theArgVec[0] << ": no texture is set.\n";
6973           return 1;
6974         }
6975
6976         if (theArgsNb < 7)
6977         {
6978           theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6979           return 1;
6980         }
6981
6982         Standard_ShortReal aTx = (Standard_ShortReal)atof (theArgVec [5]);
6983         Standard_ShortReal aTy = (Standard_ShortReal)atof (theArgVec [6]);
6984
6985         aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
6986       }
6987       else if (aCappingArg == "texrotate") // texture rotation
6988       {
6989         if (aClipPlane->CappingTexture().IsNull())
6990         {
6991           theDi << theArgVec[0] << ": no texture is set.\n";
6992           return 1;
6993         }
6994
6995         if (theArgsNb < 6)
6996         {
6997           theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
6998           return 1;
6999         }
7000
7001         Standard_ShortReal aRot = (Standard_ShortReal)atof (theArgVec[5]);
7002
7003         aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
7004       }
7005       else if (aCappingArg == "hatch") // hatch style
7006       {
7007         if (theArgsNb < 6)
7008         {
7009           theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
7010           return 1;
7011         }
7012
7013         TCollection_AsciiString aHatchStr (theArgVec [5]);
7014         if (aHatchStr == "on")
7015         {
7016           aClipPlane->SetCappingHatchOn();
7017         }
7018         else if (aHatchStr == "off")
7019         {
7020           aClipPlane->SetCappingHatchOff();
7021         }
7022         else
7023         {
7024           aClipPlane->SetCappingHatch ((Aspect_HatchStyle)atoi (theArgVec[5]));
7025         }
7026       }
7027     }
7028
7029     ViewerTest::RedrawAllViews();
7030
7031     return 0;
7032   }
7033
7034   theDi << theArgVec[0] << ": invalid command. Type help for more information.\n";
7035   return 1;
7036 }
7037
7038 //===============================================================================================
7039 //function : VZRange
7040 //purpose  :
7041 //===============================================================================================
7042 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7043 {
7044   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7045
7046   if (aCurrentView.IsNull())
7047   {
7048     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7049     return 1;
7050   }
7051
7052   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
7053
7054   if (theArgsNb < 2)
7055   {
7056     theDi << "ZNear: " << aCamera->ZNear() << "\n";
7057     theDi << "ZFar: " << aCamera->ZFar() << "\n";
7058     return 0;
7059   }
7060
7061   if (theArgsNb == 3)
7062   {
7063     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
7064     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
7065
7066     if (aNewZNear >= aNewZFar)
7067     {
7068       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
7069       return 1;
7070     }
7071
7072     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
7073     {
7074       std::cout << theArgVec[0] << ": invalid arguments: ";
7075       std::cout << "znear, zfar should be positive for perspective camera.\n";
7076       return 1;
7077     }
7078
7079     aCamera->SetZRange (aNewZNear, aNewZFar);
7080   }
7081   else
7082   {
7083     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7084     return 1;
7085   }
7086
7087   aCurrentView->Redraw();
7088
7089   return 0;
7090 }
7091
7092 //===============================================================================================
7093 //function : VAutoZFit
7094 //purpose  :
7095 //===============================================================================================
7096 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7097 {
7098   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7099
7100   if (aCurrentView.IsNull())
7101   {
7102     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7103     return 1;
7104   }
7105
7106   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
7107
7108   if (theArgsNb > 3)
7109   {
7110     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7111     return 1;
7112   }
7113
7114   if (theArgsNb < 2)
7115   {
7116     theDi << "Auto z-fit mode: \n"
7117           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
7118           << "Scale: " << aScale << "\n";
7119     return 0;
7120   }
7121
7122   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
7123
7124   if (theArgsNb >= 3)
7125   {
7126     aScale = Draw::Atoi (theArgVec[2]);
7127   }
7128
7129   aCurrentView->SetAutoZFitMode (isOn, aScale);
7130   aCurrentView->AutoZFit();
7131   aCurrentView->Redraw();
7132
7133   return 0;
7134 }
7135
7136 //! Auxiliary function to print projection type
7137 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
7138 {
7139   switch (theProjType)
7140   {
7141     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
7142     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
7143     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
7144     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
7145     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
7146   }
7147   return "UNKNOWN";
7148 }
7149
7150 //===============================================================================================
7151 //function : VCamera
7152 //purpose  :
7153 //===============================================================================================
7154 static int VCamera (Draw_Interpretor& theDI,
7155                     Standard_Integer  theArgsNb,
7156                     const char**      theArgVec)
7157 {
7158   Handle(V3d_View) aView = ViewerTest::CurrentView();
7159   if (aView.IsNull())
7160   {
7161     std::cout << "Error: no active view.\n";
7162     return 1;
7163   }
7164
7165   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7166   if (theArgsNb < 2)
7167   {
7168     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7169     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7170     theDI << "Distance:   " << aCamera->Distance() << "\n";
7171     theDI << "IOD:        " << aCamera->IOD() << "\n";
7172     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7173     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7174     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7175     return 0;
7176   }
7177
7178   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7179   {
7180     Standard_CString        anArg = theArgVec[anArgIter];
7181     TCollection_AsciiString anArgCase (anArg);
7182     anArgCase.LowerCase();
7183     if (anArgCase == "-proj"
7184      || anArgCase == "-projection"
7185      || anArgCase == "-projtype"
7186      || anArgCase == "-projectiontype")
7187     {
7188       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7189     }
7190     else if (anArgCase == "-ortho"
7191           || anArgCase == "-orthographic")
7192     {
7193       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
7194     }
7195     else if (anArgCase == "-persp"
7196           || anArgCase == "-perspective"
7197           || anArgCase == "-perspmono"
7198           || anArgCase == "-perspectivemono"
7199           || anArgCase == "-mono")
7200     {
7201       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7202     }
7203     else if (anArgCase == "-stereo"
7204           || anArgCase == "-stereoscopic"
7205           || anArgCase == "-perspstereo"
7206           || anArgCase == "-perspectivestereo")
7207     {
7208       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7209     }
7210     else if (anArgCase == "-left"
7211           || anArgCase == "-lefteye"
7212           || anArgCase == "-monoleft"
7213           || anArgCase == "-monolefteye"
7214           || anArgCase == "-perpsleft"
7215           || anArgCase == "-perpslefteye")
7216     {
7217       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
7218     }
7219     else if (anArgCase == "-right"
7220           || anArgCase == "-righteye"
7221           || anArgCase == "-monoright"
7222           || anArgCase == "-monorighteye"
7223           || anArgCase == "-perpsright")
7224     {
7225       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
7226     }
7227     else if (anArgCase == "-dist"
7228           || anArgCase == "-distance")
7229     {
7230       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7231       if (anArgValue != NULL
7232       && *anArgValue != '-')
7233       {
7234         ++anArgIter;
7235         aCamera->SetDistance (Draw::Atof (anArgValue));
7236         continue;
7237       }
7238       theDI << aCamera->Distance() << " ";
7239     }
7240     else if (anArgCase == "-iod")
7241     {
7242       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7243       if (anArgValue != NULL
7244       && *anArgValue != '-')
7245       {
7246         ++anArgIter;
7247         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
7248         continue;
7249       }
7250       theDI << aCamera->IOD() << " ";
7251     }
7252     else if (anArgCase == "-iodtype")
7253     {
7254       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
7255       TCollection_AsciiString anValueCase (anArgValue);
7256       anValueCase.LowerCase();
7257       if (anValueCase == "abs"
7258        || anValueCase == "absolute")
7259       {
7260         ++anArgIter;
7261         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
7262         continue;
7263       }
7264       else if (anValueCase == "rel"
7265             || anValueCase == "relative")
7266       {
7267         ++anArgIter;
7268         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
7269         continue;
7270       }
7271       else if (*anArgValue != '-')
7272       {
7273         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
7274         return 1;
7275       }
7276       switch (aCamera->GetIODType())
7277       {
7278         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
7279         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
7280       }
7281     }
7282     else if (anArgCase == "-zfocus")
7283     {
7284       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7285       if (anArgValue != NULL
7286       && *anArgValue != '-')
7287       {
7288         ++anArgIter;
7289         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
7290         continue;
7291       }
7292       theDI << aCamera->ZFocus() << " ";
7293     }
7294     else if (anArgCase == "-zfocustype")
7295     {
7296       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
7297       TCollection_AsciiString anValueCase (anArgValue);
7298       anValueCase.LowerCase();
7299       if (anValueCase == "abs"
7300        || anValueCase == "absolute")
7301       {
7302         ++anArgIter;
7303         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
7304         continue;
7305       }
7306       else if (anValueCase == "rel"
7307             || anValueCase == "relative")
7308       {
7309         ++anArgIter;
7310         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
7311         continue;
7312       }
7313       else if (*anArgValue != '-')
7314       {
7315         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
7316         return 1;
7317       }
7318       switch (aCamera->ZFocusType())
7319       {
7320         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
7321         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
7322       }
7323     }
7324     else if (anArgCase == "-fov"
7325           || anArgCase == "-fovy")
7326     {
7327       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7328       if (anArgValue != NULL
7329       && *anArgValue != '-')
7330       {
7331         ++anArgIter;
7332         aCamera->SetFOVy (Draw::Atof (anArgValue));
7333         continue;
7334       }
7335       theDI << aCamera->FOVy() << " ";
7336     }
7337     else
7338     {
7339       std::cout << "Error: unknown argument '" << anArg << "'\n";
7340       return 1;
7341     }
7342   }
7343
7344   aView->AutoZFit();
7345   aView->Redraw();
7346
7347   return 0;
7348 }
7349
7350 //! Parse stereo output mode
7351 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
7352                                          Graphic3d_StereoMode& theMode)
7353 {
7354   TCollection_AsciiString aFlag (theArg);
7355   aFlag.LowerCase();
7356   if (aFlag == "quadbuffer")
7357   {
7358     theMode = Graphic3d_StereoMode_QuadBuffer;
7359   }
7360   else if (aFlag == "anaglyph")
7361   {
7362     theMode = Graphic3d_StereoMode_Anaglyph;
7363   }
7364   else if (aFlag == "row"
7365         || aFlag == "rowinterlaced")
7366   {
7367     theMode = Graphic3d_StereoMode_RowInterlaced;
7368   }
7369   else if (aFlag == "col"
7370         || aFlag == "colinterlaced"
7371         || aFlag == "columninterlaced")
7372   {
7373     theMode = Graphic3d_StereoMode_ColumnInterlaced;
7374   }
7375   else if (aFlag == "chess"
7376         || aFlag == "chessboard")
7377   {
7378     theMode = Graphic3d_StereoMode_ChessBoard;
7379   }
7380   else if (aFlag == "sbs"
7381         || aFlag == "sidebyside")
7382   {
7383     theMode = Graphic3d_StereoMode_SideBySide;
7384   }
7385   else if (aFlag == "ou"
7386         || aFlag == "overunder")
7387   {
7388     theMode = Graphic3d_StereoMode_OverUnder;
7389   }
7390   else if (aFlag == "pageflip"
7391         || aFlag == "softpageflip")
7392   {
7393     theMode = Graphic3d_StereoMode_SoftPageFlip;
7394   }
7395   else
7396   {
7397     return Standard_False;
7398   }
7399   return Standard_True;
7400 }
7401
7402 //! Parse anaglyph filter
7403 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
7404                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
7405 {
7406   TCollection_AsciiString aFlag (theArg);
7407   aFlag.LowerCase();
7408   if (aFlag == "redcyansimple")
7409   {
7410     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
7411   }
7412   else if (aFlag == "redcyan"
7413         || aFlag == "redcyanoptimized")
7414   {
7415     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
7416   }
7417   else if (aFlag == "yellowbluesimple")
7418   {
7419     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
7420   }
7421   else if (aFlag == "yellowblue"
7422         || aFlag == "yellowblueoptimized")
7423   {
7424     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
7425   }
7426   else if (aFlag == "greenmagenta"
7427         || aFlag == "greenmagentasimple")
7428   {
7429     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
7430   }
7431   else
7432   {
7433     return Standard_False;
7434   }
7435   return Standard_True;
7436 }
7437
7438 //==============================================================================
7439 //function : VStereo
7440 //purpose  :
7441 //==============================================================================
7442
7443 static int VStereo (Draw_Interpretor& theDI,
7444                     Standard_Integer  theArgNb,
7445                     const char**      theArgVec)
7446 {
7447   Handle(V3d_View) aView = ViewerTest::CurrentView();
7448   if (theArgNb < 2)
7449   {
7450     if (aView.IsNull())
7451     {
7452       std::cout << "Error: no active viewer!\n";
7453       return 0;
7454     }
7455
7456     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
7457     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
7458     if (isActive)
7459     {
7460       TCollection_AsciiString aMode;
7461       switch (aView->RenderingParams().StereoMode)
7462       {
7463         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
7464         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
7465         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
7466         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
7467         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
7468         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
7469         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
7470         case Graphic3d_StereoMode_Anaglyph  :
7471           aMode = "anaglyph";
7472           switch (aView->RenderingParams().AnaglyphFilter)
7473           {
7474             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
7475             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
7476             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
7477             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
7478             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
7479             default: break;
7480           }
7481         default: break;
7482       }
7483       theDI << "Mode " << aMode << "\n";
7484     }
7485     return 0;
7486   }
7487
7488   Handle(Graphic3d_Camera) aCamera;
7489   Graphic3d_RenderingParams*   aParams   = NULL;
7490   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
7491   if (!aView.IsNull())
7492   {
7493     aParams   = &aView->ChangeRenderingParams();
7494     aMode     = aParams->StereoMode;
7495     aCamera   = aView->Camera();
7496   }
7497
7498   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7499   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
7500   {
7501     Standard_CString        anArg = theArgVec[anArgIter];
7502     TCollection_AsciiString aFlag (anArg);
7503     aFlag.LowerCase();
7504     if (anUpdateTool.parseRedrawMode (aFlag))
7505     {
7506       continue;
7507     }
7508     else if (aFlag == "0"
7509           || aFlag == "off")
7510     {
7511       if (++anArgIter < theArgNb)
7512       {
7513         std::cout << "Error: wrong number of arguments!\n";
7514         return 1;
7515       }
7516
7517       if (!aCamera.IsNull()
7518        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
7519       {
7520         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7521       }
7522       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
7523       return 0;
7524     }
7525     else if (aFlag == "1"
7526           || aFlag == "on")
7527     {
7528       if (++anArgIter < theArgNb)
7529       {
7530         std::cout << "Error: wrong number of arguments!\n";
7531         return 1;
7532       }
7533
7534       if (!aCamera.IsNull())
7535       {
7536         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7537       }
7538       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7539       return 0;
7540     }
7541     else if (aFlag == "-reverse"
7542           || aFlag == "-reversed"
7543           || aFlag == "-swap")
7544     {
7545       Standard_Boolean toEnable = Standard_True;
7546       if (++anArgIter < theArgNb
7547       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7548       {
7549         --anArgIter;
7550       }
7551       aParams->ToReverseStereo = toEnable;
7552     }
7553     else if (aFlag == "-noreverse"
7554           || aFlag == "-noswap")
7555     {
7556       Standard_Boolean toDisable = Standard_True;
7557       if (++anArgIter < theArgNb
7558       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
7559       {
7560         --anArgIter;
7561       }
7562       aParams->ToReverseStereo = !toDisable;
7563     }
7564     else if (aFlag == "-mode"
7565           || aFlag == "-stereomode")
7566     {
7567       if (++anArgIter >= theArgNb
7568       || !parseStereoMode (theArgVec[anArgIter], aMode))
7569       {
7570         std::cout << "Error: syntax error at '" << anArg << "'\n";
7571         return 1;
7572       }
7573
7574       if (aMode == Graphic3d_StereoMode_QuadBuffer)
7575       {
7576         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7577       }
7578     }
7579     else if (aFlag == "-anaglyph"
7580           || aFlag == "-anaglyphfilter")
7581     {
7582       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
7583       if (++anArgIter >= theArgNb
7584       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
7585       {
7586         std::cout << "Error: syntax error at '" << anArg << "'\n";
7587         return 1;
7588       }
7589
7590       aMode = Graphic3d_StereoMode_Anaglyph;
7591       aParams->AnaglyphFilter = aFilter;
7592     }
7593     else if (parseStereoMode (anArg, aMode)) // short syntax
7594     {
7595       if (aMode == Graphic3d_StereoMode_QuadBuffer)
7596       {
7597         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7598       }
7599     }
7600     else
7601     {
7602       std::cout << "Error: syntax error at '" << anArg << "'\n";
7603       return 1;
7604     }
7605   }
7606
7607   if (!aView.IsNull())
7608   {
7609     aParams->StereoMode = aMode;
7610     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7611   }
7612   return 0;
7613 }
7614
7615 //===============================================================================================
7616 //function : VDefaults
7617 //purpose  :
7618 //===============================================================================================
7619 static int VDefaults (Draw_Interpretor& theDi,
7620                       Standard_Integer  theArgsNb,
7621                       const char**      theArgVec)
7622 {
7623   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7624   if (aCtx.IsNull())
7625   {
7626     std::cerr << "No active viewer!\n";
7627     return 1;
7628   }
7629
7630   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
7631   if (theArgsNb < 2)
7632   {
7633     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
7634     {
7635       theDi << "DeflType:           relative\n"
7636             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
7637     }
7638     else
7639     {
7640       theDi << "DeflType:           absolute\n"
7641             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
7642     }
7643     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
7644     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
7645     return 0;
7646   }
7647
7648   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7649   {
7650     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7651     anArg.UpperCase();
7652     if (anArg == "-ABSDEFL"
7653      || anArg == "-ABSOLUTEDEFLECTION"
7654      || anArg == "-DEFL"
7655      || anArg == "-DEFLECTION")
7656     {
7657       if (++anArgIter >= theArgsNb)
7658       {
7659         std::cout << "Error: wrong syntax at " << anArg << "\n";
7660         return 1;
7661       }
7662       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
7663       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
7664     }
7665     else if (anArg == "-RELDEFL"
7666           || anArg == "-RELATIVEDEFLECTION"
7667           || anArg == "-DEVCOEFF"
7668           || anArg == "-DEVIATIONCOEFF"
7669           || anArg == "-DEVIATIONCOEFFICIENT")
7670     {
7671       if (++anArgIter >= theArgsNb)
7672       {
7673         std::cout << "Error: wrong syntax at " << anArg << "\n";
7674         return 1;
7675       }
7676       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
7677       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
7678     }
7679     else if (anArg == "-ANGDEFL"
7680           || anArg == "-ANGULARDEFL"
7681           || anArg == "-ANGULARDEFLECTION")
7682     {
7683       if (++anArgIter >= theArgsNb)
7684       {
7685         std::cout << "Error: wrong syntax at " << anArg << "\n";
7686         return 1;
7687       }
7688       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
7689       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
7690     }
7691     else if (anArg == "-AUTOTR"
7692           || anArg == "-AUTOTRIANG"
7693           || anArg == "-AUTOTRIANGULATION")
7694     {
7695       if (++anArgIter >= theArgsNb)
7696       {
7697         std::cout << "Error: wrong syntax at " << anArg << "\n";
7698         return 1;
7699       }
7700       TCollection_AsciiString aValue (theArgVec[anArgIter]);
7701       aValue.LowerCase();
7702       if (aValue == "on"
7703        || aValue == "1")
7704       {
7705         aDefParams->SetAutoTriangulation (Standard_True);
7706       }
7707       else if (aValue == "off"
7708             || aValue == "0")
7709       {
7710         aDefParams->SetAutoTriangulation (Standard_False);
7711       }
7712     }
7713     else
7714     {
7715       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
7716     }
7717   }
7718
7719   return 0;
7720 }
7721
7722 //! Auxiliary method
7723 inline void addLight (const Handle(V3d_Light)& theLightNew,
7724                       const Standard_Boolean   theIsGlobal)
7725 {
7726   if (theLightNew.IsNull())
7727   {
7728     return;
7729   }
7730
7731   if (theIsGlobal)
7732   {
7733     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
7734   }
7735   else
7736   {
7737     ViewerTest::CurrentView()->SetLightOn (theLightNew);
7738   }
7739 }
7740
7741 //! Auxiliary method
7742 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
7743 {
7744   TCollection_AsciiString anArgNextCase (theArgNext);
7745   anArgNextCase.UpperCase();
7746   if (anArgNextCase.Length() > 5
7747    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
7748   {
7749     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
7750   }
7751   else
7752   {
7753     return theArgNext.IntegerValue();
7754   }
7755 }
7756
7757 //===============================================================================================
7758 //function : VLight
7759 //purpose  :
7760 //===============================================================================================
7761 static int VLight (Draw_Interpretor& theDi,
7762                    Standard_Integer  theArgsNb,
7763                    const char**      theArgVec)
7764 {
7765   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
7766   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
7767   if (aView.IsNull()
7768    || aViewer.IsNull())
7769   {
7770     std::cerr << "No active viewer!\n";
7771     return 1;
7772   }
7773
7774   Standard_Real        anXYZ[3];
7775   Quantity_Coefficient anAtten[2];
7776   if (theArgsNb < 2)
7777   {
7778     // print lights info
7779     Standard_Integer aLightId = 0;
7780     for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightId)
7781     {
7782       Handle(V3d_Light) aLight = aView->ActiveLight();
7783       const Quantity_Color aColor = aLight->Color();
7784       theDi << "Light" << aLightId << "\n";
7785       switch (aLight->Type())
7786       {
7787         case V3d_AMBIENT:
7788         {
7789           theDi << "  Type:       Ambient\n";
7790           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7791           break;
7792         }
7793         case V3d_DIRECTIONAL:
7794         {
7795           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
7796           theDi << "  Type:       Directional\n";
7797           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7798           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7799           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
7800           if (!aLightDir.IsNull())
7801           {
7802             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7803             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7804             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
7805             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7806           }
7807           break;
7808         }
7809         case V3d_POSITIONAL:
7810         {
7811           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
7812           theDi << "  Type:       Positional\n";
7813           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7814           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7815           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
7816           if (!aLightPos.IsNull())
7817           {
7818             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7819             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7820             aLightPos->Attenuation (anAtten[0], anAtten[1]);
7821             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
7822           }
7823           break;
7824         }
7825         case V3d_SPOT:
7826         {
7827           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
7828           theDi << "  Type:       Spot\n";
7829           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7830           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7831           if (!aLightSpot.IsNull())
7832           {
7833             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7834             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7835             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
7836             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7837             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
7838             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
7839             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
7840             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
7841           }
7842           break;
7843         }
7844         default:
7845         {
7846           theDi << "  Type:       UNKNOWN\n";
7847           break;
7848         }
7849       }
7850       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
7851     }
7852   }
7853
7854   Handle(V3d_Light) aLightNew;
7855   Handle(V3d_Light) aLightOld;
7856   Standard_Boolean  isGlobal = Standard_True;
7857   Standard_Boolean  toCreate = Standard_False;
7858   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7859   {
7860     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
7861     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
7862     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
7863     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
7864     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
7865
7866     TCollection_AsciiString aName, aValue;
7867     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
7868     TCollection_AsciiString anArgCase (anArg);
7869     anArgCase.UpperCase();
7870     if (anArgCase.IsEqual ("NEW")
7871      || anArgCase.IsEqual ("ADD")
7872      || anArgCase.IsEqual ("CREATE"))
7873     {
7874       toCreate = Standard_True;
7875     }
7876     else if (anArgCase.IsEqual ("GLOB")
7877           || anArgCase.IsEqual ("GLOBAL"))
7878     {
7879       isGlobal = Standard_True;
7880     }
7881     else if (anArgCase.IsEqual ("LOC")
7882           || anArgCase.IsEqual ("LOCAL"))
7883     {
7884       isGlobal = Standard_False;
7885     }
7886     else if (anArgCase.IsEqual ("DEF")
7887           || anArgCase.IsEqual ("DEFAULTS"))
7888     {
7889       toCreate = Standard_False;
7890       aViewer->SetDefaultLights();
7891     }
7892     else if (anArgCase.IsEqual ("CLR")
7893           || anArgCase.IsEqual ("CLEAR"))
7894     {
7895       toCreate = Standard_False;
7896       aView->InitActiveLights();
7897       while (aView->MoreActiveLights())
7898       {
7899         aViewer->DelLight (aView->ActiveLight());
7900         aView->InitActiveLights();
7901       }
7902     }
7903     else if (anArgCase.IsEqual ("AMB")
7904           || anArgCase.IsEqual ("AMBIENT")
7905           || anArgCase.IsEqual ("AMBLIGHT"))
7906     {
7907       addLight (aLightNew, isGlobal);
7908       if (!toCreate)
7909       {
7910         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7911         return 1;
7912       }
7913       toCreate  = Standard_False;
7914       aLightNew = new V3d_AmbientLight (aViewer);
7915     }
7916     else if (anArgCase.IsEqual ("DIRECTIONAL")
7917           || anArgCase.IsEqual ("DIRLIGHT"))
7918     {
7919       addLight (aLightNew, isGlobal);
7920       if (!toCreate)
7921       {
7922         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7923         return 1;
7924       }
7925       toCreate  = Standard_False;
7926       aLightNew = new V3d_DirectionalLight (aViewer);
7927     }
7928     else if (anArgCase.IsEqual ("SPOT")
7929           || anArgCase.IsEqual ("SPOTLIGHT"))
7930     {
7931       addLight (aLightNew, isGlobal);
7932       if (!toCreate)
7933       {
7934         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7935         return 1;
7936       }
7937       toCreate  = Standard_False;
7938       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
7939     }
7940     else if (anArgCase.IsEqual ("POSLIGHT")
7941           || anArgCase.IsEqual ("POSITIONAL"))
7942     {
7943       addLight (aLightNew, isGlobal);
7944       if (!toCreate)
7945       {
7946         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7947         return 1;
7948       }
7949       toCreate  = Standard_False;
7950       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
7951     }
7952     else if (anArgCase.IsEqual ("CHANGE"))
7953     {
7954       addLight (aLightNew, isGlobal);
7955       aLightNew.Nullify();
7956       if (++anArgIt >= theArgsNb)
7957       {
7958         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7959         return 1;
7960       }
7961
7962       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
7963       Standard_Integer aLightIt = 0;
7964       for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
7965       {
7966         if (aLightIt == aLightId)
7967         {
7968           aLightOld = aView->ActiveLight();
7969           break;
7970         }
7971       }
7972
7973       if (aLightOld.IsNull())
7974       {
7975         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
7976         return 1;
7977       }
7978     }
7979     else if (anArgCase.IsEqual ("DEL")
7980           || anArgCase.IsEqual ("DELETE"))
7981     {
7982       Handle(V3d_Light) aLightDel;
7983       if (++anArgIt >= theArgsNb)
7984       {
7985         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7986         return 1;
7987       }
7988
7989       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
7990       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
7991       Standard_Integer aLightIt = 0;
7992       for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
7993       {
7994         aLightDel = aView->ActiveLight();
7995         if (aLightIt == aLightDelId)
7996         {
7997           break;
7998         }
7999       }
8000       if (!aLightDel.IsNull())
8001       {
8002         aViewer->DelLight (aLightDel);
8003       }
8004     }
8005     else if (anArgCase.IsEqual ("COLOR")
8006           || anArgCase.IsEqual ("COLOUR"))
8007     {
8008       if (++anArgIt >= theArgsNb)
8009       {
8010         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8011         return 1;
8012       }
8013
8014       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8015       anArgNext.UpperCase();
8016       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
8017       if (!aLightCurr.IsNull())
8018       {
8019         aLightCurr->SetColor (aColor);
8020       }
8021     }
8022     else if (anArgCase.IsEqual ("POS")
8023           || anArgCase.IsEqual ("POSITION"))
8024     {
8025       if ((anArgIt + 3) >= theArgsNb)
8026       {
8027         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8028         return 1;
8029       }
8030
8031       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8032       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8033       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8034       if (!aLightDir.IsNull())
8035       {
8036         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8037       }
8038       else if (!aLightPos.IsNull())
8039       {
8040         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8041       }
8042       else if (!aLightSpot.IsNull())
8043       {
8044         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8045       }
8046       else
8047       {
8048         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8049         return 1;
8050       }
8051     }
8052     else if (anArgCase.IsEqual ("DIR")
8053           || anArgCase.IsEqual ("DIRECTION"))
8054     {
8055       if ((anArgIt + 3) >= theArgsNb)
8056       {
8057         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8058         return 1;
8059       }
8060
8061       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8062       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8063       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8064       if (!aLightDir.IsNull())
8065       {
8066         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8067       }
8068       else if (!aLightSpot.IsNull())
8069       {
8070         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8071       }
8072       else
8073       {
8074         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8075         return 1;
8076       }
8077     }
8078     else if (anArgCase.IsEqual ("SM")
8079           || anArgCase.IsEqual ("SMOOTHNESS"))
8080     {
8081       if (++anArgIt >= theArgsNb)
8082       {
8083         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8084         return 1;
8085       }
8086
8087       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
8088
8089       if (fabs (aSmoothness) < Precision::Confusion())
8090       {
8091         aLightCurr->SetIntensity (1.f);
8092       }
8093       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
8094       {
8095         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
8096       }
8097       else
8098       {
8099         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
8100         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
8101       }
8102
8103       if (!aLightPos.IsNull())
8104       {
8105         aLightPos->SetSmoothRadius (aSmoothness);
8106       }
8107       else if (!aLightDir.IsNull())
8108       {
8109         aLightDir->SetSmoothAngle (aSmoothness);
8110       }
8111     }
8112     else if (anArgCase.IsEqual ("INT")
8113           || anArgCase.IsEqual ("INTENSITY"))
8114     {
8115       if (++anArgIt >= theArgsNb)
8116       {
8117         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8118         return 1;
8119       }
8120
8121       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
8122
8123       if (!aLightCurr.IsNull())
8124       {
8125         aLightCurr->SetIntensity (aIntensity);
8126       }
8127     }
8128     else if (anArgCase.IsEqual ("ANG")
8129           || anArgCase.IsEqual ("ANGLE"))
8130     {
8131       if (++anArgIt >= theArgsNb)
8132       {
8133         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8134         return 1;
8135       }
8136
8137       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
8138
8139       if (!aLightSpot.IsNull())
8140       {
8141         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
8142       }
8143     }
8144     else if (anArgCase.IsEqual ("CONSTATTEN")
8145           || anArgCase.IsEqual ("CONSTATTENUATION"))
8146     {
8147       if (++anArgIt >= theArgsNb)
8148       {
8149         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8150         return 1;
8151       }
8152
8153       if (!aLightPos.IsNull())
8154       {
8155         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8156         anAtten[0] = Atof (theArgVec[anArgIt]);
8157         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8158       }
8159       else if (!aLightSpot.IsNull())
8160       {
8161         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8162         anAtten[0] = Atof (theArgVec[anArgIt]);
8163         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8164       }
8165       else
8166       {
8167         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8168         return 1;
8169       }
8170     }
8171     else if (anArgCase.IsEqual ("LINATTEN")
8172           || anArgCase.IsEqual ("LINEARATTEN")
8173           || anArgCase.IsEqual ("LINEARATTENUATION"))
8174     {
8175       if (++anArgIt >= theArgsNb)
8176       {
8177         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8178         return 1;
8179       }
8180
8181       if (!aLightPos.IsNull())
8182       {
8183         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8184         anAtten[1] = Atof (theArgVec[anArgIt]);
8185         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8186       }
8187       else if (!aLightSpot.IsNull())
8188       {
8189         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8190         anAtten[1] = Atof (theArgVec[anArgIt]);
8191         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8192       }
8193       else
8194       {
8195         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8196         return 1;
8197       }
8198     }
8199     else if (anArgCase.IsEqual ("EXP")
8200           || anArgCase.IsEqual ("EXPONENT")
8201           || anArgCase.IsEqual ("SPOTEXP")
8202           || anArgCase.IsEqual ("SPOTEXPONENT"))
8203     {
8204       if (++anArgIt >= theArgsNb)
8205       {
8206         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8207         return 1;
8208       }
8209
8210       if (!aLightSpot.IsNull())
8211       {
8212         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
8213       }
8214       else
8215       {
8216         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8217         return 1;
8218       }
8219     }
8220     else if (anArgCase.IsEqual ("HEAD")
8221           || anArgCase.IsEqual ("HEADLIGHT"))
8222     {
8223       if (++anArgIt >= theArgsNb)
8224       {
8225         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8226         return 1;
8227       }
8228
8229       if (aLightAmb.IsNull()
8230        && !aLightCurr.IsNull())
8231       {
8232         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
8233       }
8234       else
8235       {
8236         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8237         return 1;
8238       }
8239     }
8240     else
8241     {
8242       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
8243     }
8244   }
8245
8246   addLight (aLightNew, isGlobal);
8247   aViewer->UpdateLights();
8248
8249   return 0;
8250 }
8251
8252 //=======================================================================
8253 //function : VRenderParams
8254 //purpose  : Enables/disables rendering features
8255 //=======================================================================
8256
8257 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
8258                                        Standard_Integer  theArgNb,
8259                                        const char**      theArgVec)
8260 {
8261   Handle(V3d_View) aView = ViewerTest::CurrentView();
8262   if (aView.IsNull())
8263   {
8264     std::cerr << "Error: no active viewer!\n";
8265     return 1;
8266   }
8267
8268   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
8269   TCollection_AsciiString aCmdName (theArgVec[0]);
8270   aCmdName.LowerCase();
8271   if (aCmdName == "vraytrace")
8272   {
8273     if (theArgNb == 1)
8274     {
8275       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
8276       return 0;
8277     }
8278     else if (theArgNb == 2)
8279     {
8280       TCollection_AsciiString aValue (theArgVec[1]);
8281       aValue.LowerCase();
8282       if (aValue == "on"
8283        || aValue == "1")
8284       {
8285         aParams.Method = Graphic3d_RM_RAYTRACING;
8286         aView->Redraw();
8287         return 0;
8288       }
8289       else if (aValue == "off"
8290             || aValue == "0")
8291       {
8292         aParams.Method = Graphic3d_RM_RASTERIZATION;
8293         aView->Redraw();
8294         return 0;
8295       }
8296       else
8297       {
8298         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
8299         return 1;
8300       }
8301     }
8302     else
8303     {
8304       std::cout << "Error: wrong number of arguments\n";
8305       return 1;
8306     }
8307   }
8308
8309   if (theArgNb < 2)
8310   {
8311     theDI << "renderMode:  ";
8312     switch (aParams.Method)
8313     {
8314       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
8315       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
8316     }
8317     theDI << "\n";
8318     theDI << "msaa:         " <<  aParams.NbMsaaSamples << "\n";
8319     theDI << "rayDepth:     " <<  aParams.RaytracingDepth                             << "\n";
8320     theDI << "fsaa:         " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
8321     theDI << "shadows:      " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
8322     theDI << "reflections:  " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
8323     theDI << "gleam:        " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
8324     theDI << "GI:           " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
8325     theDI << "blocked RNG:  " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
8326     theDI << "shadingModel: ";
8327     switch (aView->ShadingModel())
8328     {
8329       case V3d_COLOR:   theDI << "color";   break;
8330       case V3d_FLAT:    theDI << "flat";    break;
8331       case V3d_GOURAUD: theDI << "gouraud"; break;
8332       case V3d_PHONG:   theDI << "phong";   break;
8333     }
8334     theDI << "\n";
8335     return 0;
8336   }
8337
8338   Standard_Boolean toPrint = Standard_False;
8339   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8340   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8341   {
8342     Standard_CString        anArg (theArgVec[anArgIter]);
8343     TCollection_AsciiString aFlag (anArg);
8344     aFlag.LowerCase();
8345     if (anUpdateTool.parseRedrawMode (aFlag))
8346     {
8347       continue;
8348     }
8349     else if (aFlag == "-echo"
8350           || aFlag == "-print")
8351     {
8352       toPrint = Standard_True;
8353       anUpdateTool.Invalidate();
8354     }
8355     else if (aFlag == "-mode"
8356           || aFlag == "-rendermode"
8357           || aFlag == "-render_mode")
8358     {
8359       if (toPrint)
8360       {
8361         switch (aParams.Method)
8362         {
8363           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
8364           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
8365         }
8366         continue;
8367       }
8368       else
8369       {
8370         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8371         return 1;
8372       }
8373     }
8374     else if (aFlag == "-ray"
8375           || aFlag == "-raytrace")
8376     {
8377       if (toPrint)
8378       {
8379         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
8380         continue;
8381       }
8382
8383       aParams.Method = Graphic3d_RM_RAYTRACING;
8384     }
8385     else if (aFlag == "-rast"
8386           || aFlag == "-raster"
8387           || aFlag == "-rasterization")
8388     {
8389       if (toPrint)
8390       {
8391         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
8392         continue;
8393       }
8394
8395       aParams.Method = Graphic3d_RM_RASTERIZATION;
8396     }
8397     else if (aFlag == "-msaa")
8398     {
8399       if (toPrint)
8400       {
8401         theDI << aParams.NbMsaaSamples << " ";
8402         continue;
8403       }
8404       else if (++anArgIter >= theArgNb)
8405       {
8406         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8407         return 1;
8408       }
8409
8410       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
8411       if (aNbSamples < 0)
8412       {
8413         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
8414         return 1;
8415       }
8416       else
8417       {
8418         aParams.NbMsaaSamples = aNbSamples;
8419       }
8420     }
8421     else if (aFlag == "-raydepth"
8422           || aFlag == "-ray_depth")
8423     {
8424       if (toPrint)
8425       {
8426         theDI << aParams.RaytracingDepth << " ";
8427         continue;
8428       }
8429       else if (++anArgIter >= theArgNb)
8430       {
8431         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8432         return 1;
8433       }
8434
8435       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
8436
8437       // We allow RaytracingDepth be more than 10 in case of GI enabled
8438       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
8439       {
8440         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
8441         return 1;
8442       }
8443       else
8444       {
8445         aParams.RaytracingDepth = aDepth;
8446       }
8447     }
8448     else if (aFlag == "-shad"
8449           || aFlag == "-shadows")
8450     {
8451       if (toPrint)
8452       {
8453         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
8454         continue;
8455       }
8456
8457       Standard_Boolean toEnable = Standard_True;
8458       if (++anArgIter < theArgNb
8459       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8460       {
8461         --anArgIter;
8462       }
8463       aParams.IsShadowEnabled = toEnable;
8464     }
8465     else if (aFlag == "-refl"
8466           || aFlag == "-reflections")
8467     {
8468       if (toPrint)
8469       {
8470         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
8471         continue;
8472       }
8473
8474       Standard_Boolean toEnable = Standard_True;
8475       if (++anArgIter < theArgNb
8476       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8477       {
8478         --anArgIter;
8479       }
8480       aParams.IsReflectionEnabled = toEnable;
8481     }
8482     else if (aFlag == "-fsaa")
8483     {
8484       if (toPrint)
8485       {
8486         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
8487         continue;
8488       }
8489
8490       Standard_Boolean toEnable = Standard_True;
8491       if (++anArgIter < theArgNb
8492       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8493       {
8494         --anArgIter;
8495       }
8496       aParams.IsAntialiasingEnabled = toEnable;
8497     }
8498     else if (aFlag == "-gleam")
8499     {
8500       if (toPrint)
8501       {
8502         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
8503         continue;
8504       }
8505
8506       Standard_Boolean toEnable = Standard_True;
8507       if (++anArgIter < theArgNb
8508       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8509       {
8510         --anArgIter;
8511       }
8512       aParams.IsTransparentShadowEnabled = toEnable;
8513     }
8514     else if (aFlag == "-gi")
8515     {
8516       if (toPrint)
8517       {
8518         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
8519         continue;
8520       }
8521
8522       Standard_Boolean toEnable = Standard_True;
8523       if (++anArgIter < theArgNb
8524       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8525       {
8526         --anArgIter;
8527       }
8528       aParams.IsGlobalIlluminationEnabled = toEnable;
8529       if (!toEnable)
8530       {
8531         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
8532       }
8533     }
8534     else if (aFlag == "-blockedrng"
8535           || aFlag == "-brng")
8536     {
8537       if (toPrint)
8538       {
8539         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
8540         continue;
8541       }
8542
8543       Standard_Boolean toEnable = Standard_True;
8544       if (++anArgIter < theArgNb
8545         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8546       {
8547         --anArgIter;
8548       }
8549       aParams.CoherentPathTracingMode = toEnable;
8550     }
8551     else if (aFlag == "-env")
8552     {
8553       if (toPrint)
8554       {
8555         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
8556         continue;
8557       }
8558
8559       Standard_Boolean toEnable = Standard_True;
8560       if (++anArgIter < theArgNb
8561         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8562       {
8563         --anArgIter;
8564       }
8565       aParams.UseEnvironmentMapBackground = toEnable;
8566     }
8567     else if (aFlag == "-shademodel"
8568           || aFlag == "-shadingmodel"
8569           || aFlag == "-shading")
8570     {
8571       if (toPrint)
8572       {
8573         switch (aView->ShadingModel())
8574         {
8575           case V3d_COLOR:   theDI << "color ";   break;
8576           case V3d_FLAT:    theDI << "flat ";    break;
8577           case V3d_GOURAUD: theDI << "gouraud "; break;
8578           case V3d_PHONG:   theDI << "phong ";   break;
8579         }
8580         continue;
8581       }
8582
8583       if (++anArgIter >= theArgNb)
8584       {
8585         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8586       }
8587
8588       TCollection_AsciiString aMode (theArgVec[anArgIter]);
8589       aMode.LowerCase();
8590       if (aMode == "color"
8591        || aMode == "none")
8592       {
8593         aView->SetShadingModel (V3d_COLOR);
8594       }
8595       else if (aMode == "flat"
8596             || aMode == "facet")
8597       {
8598         aView->SetShadingModel (V3d_FLAT);
8599       }
8600       else if (aMode == "gouraud"
8601             || aMode == "vertex"
8602             || aMode == "vert")
8603       {
8604         aView->SetShadingModel (V3d_GOURAUD);
8605       }
8606       else if (aMode == "phong"
8607             || aMode == "fragment"
8608             || aMode == "frag"
8609             || aMode == "pixel")
8610       {
8611         aView->SetShadingModel (V3d_PHONG);
8612       }
8613       else
8614       {
8615         std::cout << "Error: unknown shading model '" << aMode << "'\n";
8616         return 1;
8617       }
8618     }
8619     else if (aFlag == "-resolution")
8620     {
8621       if (++anArgIter >= theArgNb)
8622       {
8623         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8624         return 1;
8625       }
8626
8627       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
8628       if (aResolution.IsIntegerValue())
8629       {
8630         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
8631       }
8632       else
8633       {
8634         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
8635         return 1;
8636       }
8637     }
8638     else
8639     {
8640       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
8641       return 1;
8642     }
8643   }
8644
8645   return 0;
8646 }
8647
8648 //=======================================================================
8649 //function : VProgressiveMode
8650 //purpose  :
8651 //=======================================================================
8652 #if defined(_WIN32)
8653 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
8654                                           Standard_Integer  /*theNbArgs*/,
8655                                           const char**      /*theArgs*/)
8656 {
8657   Handle(V3d_View) aView = ViewerTest::CurrentView();
8658   if (aView.IsNull())
8659   {
8660     std::cerr << "Error: no active viewer!\n";
8661     return 1;
8662   }
8663
8664   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
8665
8666   for (;;)
8667   {
8668     aView->Redraw();
8669
8670     Standard_Boolean toExit = Standard_False;
8671
8672     MSG aMsg;
8673     while (PeekMessage (&aMsg, NULL, 0, 0, PM_REMOVE))
8674     {
8675       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
8676       {
8677         toExit = Standard_True;
8678       }
8679
8680       TranslateMessage (&aMsg);
8681       DispatchMessage  (&aMsg);
8682     }
8683
8684     if (toExit)
8685     {
8686       break;
8687     }
8688   }
8689
8690   return 0;
8691 }
8692 #endif
8693
8694 //=======================================================================
8695 //function : VFrustumCulling
8696 //purpose  : enables/disables view volume's culling.
8697 //=======================================================================
8698 static int VFrustumCulling (Draw_Interpretor& theDI,
8699                             Standard_Integer  theArgNb,
8700                             const char**      theArgVec)
8701 {
8702   Handle(V3d_View) aView = ViewerTest::CurrentView();
8703   if (aView.IsNull())
8704   {
8705     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
8706     return 1;
8707   }
8708
8709   if (theArgNb < 2)
8710   {
8711     theDI << (aView->IsCullingEnabled() ? "on" : "off");
8712     return 0;
8713   }
8714   else if (theArgNb != 2)
8715   {
8716     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
8717     return 1;
8718   }
8719
8720   TCollection_AsciiString aModeStr (theArgVec[1]);
8721   aModeStr.LowerCase();
8722   Standard_Boolean toEnable = 0;
8723   if (aModeStr == "on")
8724   {
8725     toEnable = 1;
8726   }
8727   else if (aModeStr == "off")
8728   {
8729     toEnable = 0;
8730   }
8731   else
8732   {
8733     toEnable = Draw::Atoi (theArgVec[1]) != 0;
8734   }
8735
8736   aView->SetFrustumCulling (toEnable);
8737   aView->Redraw();
8738   return 0;
8739 }
8740
8741 //=======================================================================
8742 //function : VHighlightSelected
8743 //purpose  : 
8744 //=======================================================================
8745 static int VHighlightSelected (Draw_Interpretor& theDI,
8746                                Standard_Integer  theArgNb,
8747                                const char**      theArgVec)
8748 {
8749   if (ViewerTest::GetAISContext().IsNull())
8750   {
8751     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
8752     return 1;
8753   }
8754
8755   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8756
8757   if (theArgNb < 2)
8758   {
8759     theDI << (aContext->ToHilightSelected() ? "on" : "off");
8760     return 0;
8761   }
8762
8763   if (theArgNb != 2)
8764   {
8765     std::cout  << theArgVec[0] << " error : wrong number of parameters."
8766           << "Type 'help" << theArgVec[0] << "' for more information.";
8767     return 1;
8768   }
8769
8770   // Parse parameter
8771   TCollection_AsciiString aMode (theArgVec[1]);
8772   aMode.LowerCase();
8773   Standard_Boolean toEnable = Standard_False;
8774   if (aMode.IsEqual ("on"))
8775   {
8776     toEnable = Standard_True;
8777   }
8778   else if (aMode.IsEqual ("off"))
8779   {
8780     toEnable = Standard_False;
8781   }
8782   else
8783   {
8784     toEnable = Draw::Atoi (theArgVec[1]) != 0;
8785   }
8786
8787   if (toEnable != aContext->ToHilightSelected())
8788   {
8789     aContext->SetToHilightSelected (toEnable);
8790
8791     // Move cursor to null position and  back to process updating of detection
8792     // and highlighting of selected object immediatly.
8793     Standard_Integer aPixX = 0;
8794     Standard_Integer aPixY = 0;
8795     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
8796
8797     anEventManager->GetCurrentPosition (aPixX, aPixY);
8798     anEventManager->MoveTo (0, 0);
8799     anEventManager->MoveTo (aPixX, aPixY);
8800   }
8801
8802   return 0;
8803 }
8804
8805 //=======================================================================
8806 //function : VXRotate
8807 //purpose  :
8808 //=======================================================================
8809 static Standard_Integer VXRotate (Draw_Interpretor& di,
8810                                    Standard_Integer argc,
8811                                    const char ** argv)
8812 {
8813   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8814   if (aContext.IsNull())
8815   {
8816     di << argv[0] << "ERROR : use 'vinit' command before \n";
8817     return 1;
8818   }
8819   
8820   if (argc != 3)
8821   {
8822     di << "ERROR : Usage : " << argv[0] << " name angle\n";
8823     return 1;
8824   }
8825
8826   TCollection_AsciiString aName (argv[1]);
8827   Standard_Real anAngle = Draw::Atof (argv[2]);
8828
8829   // find object
8830   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
8831   Handle(AIS_InteractiveObject) anIObj;
8832   if (!aMap.IsBound2 (aName) )
8833   {
8834     di << "Use 'vdisplay' before\n";
8835     return 1;
8836   }
8837   else
8838   {
8839     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
8840
8841     gp_Trsf aTransform;
8842     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
8843     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
8844
8845     aContext->SetLocation (anIObj, aTransform);
8846     aContext->UpdateCurrentViewer();
8847   }
8848
8849   return 0;
8850 }
8851
8852 //===============================================================================================
8853 //class   : ViewerTest_AISManipulator
8854 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
8855 //===============================================================================================
8856 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
8857
8858 class ViewerTest_AISManipulator : public AIS_Manipulator
8859 {
8860 public:
8861
8862   ViewerTest_AISManipulator() : AIS_Manipulator()
8863   {
8864     GetMapOfAISManipulators().Add (this);
8865   }
8866
8867   virtual ~ViewerTest_AISManipulator()
8868   {
8869     GetMapOfAISManipulators().Remove (this);
8870   }
8871
8872   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
8873 };
8874
8875 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
8876 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
8877
8878 //===============================================================================================
8879 //function : VManipulator
8880 //purpose  :
8881 //===============================================================================================
8882 static int VManipulator (Draw_Interpretor& theDi,
8883                          Standard_Integer  theArgsNb,
8884                          const char**      theArgVec)
8885 {
8886   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8887   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8888   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
8889   if (aView.IsNull()
8890    || aViewer.IsNull())
8891   {
8892     std::cerr << "No active viewer!\n";
8893     return 1;
8894   }
8895
8896   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
8897   Standard_Integer anArgIter = 1;
8898   for (; anArgIter < theArgsNb; ++anArgIter)
8899   {
8900     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
8901   }
8902
8903   ViewerTest_CmdParser aCmd;
8904   aCmd.AddDescription ("Manages manipulator for interactive objects:");
8905   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
8906   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
8907   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
8908   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
8909   aCmd.AddOption ("detach",         "...       - detach manipulator");
8910
8911   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
8912   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
8913   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
8914
8915   aCmd.AddOption ("move",   "... x y z - move object");
8916   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
8917   aCmd.AddOption ("scale",  "... factor - scale object");
8918
8919   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
8920   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
8921   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
8922   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
8923   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
8924   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
8925   aCmd.AddOption ("size",              "... size - set size of manipulator");
8926   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
8927
8928   aCmd.Parse (theArgsNb, theArgVec);
8929
8930   if (aCmd.HasOption ("help"))
8931   {
8932     theDi.PrintHelp (theArgVec[0]);
8933     return 0;
8934   }
8935
8936   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
8937
8938   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
8939
8940   if (aName.IsEmpty())
8941   {
8942     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
8943     return 1;
8944   }
8945
8946   // ----------------------------------
8947   // detach existing manipulator object
8948   // ----------------------------------
8949
8950   if (aCmd.HasOption ("detach"))
8951   {
8952     if (!aMapAIS.IsBound2 (aName))
8953     {
8954       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
8955       return 1;
8956     }
8957
8958     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
8959     if (aManipulator.IsNull())
8960     {
8961       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
8962       return 1;
8963     }
8964
8965     aManipulator->Detach();
8966     aMapAIS.UnBind2 (aName);
8967     ViewerTest::GetAISContext()->Remove (aManipulator);
8968
8969     return 0;
8970   }
8971
8972   // -----------------------------------------------
8973   // find or create manipulator if it does not exist
8974   // -----------------------------------------------
8975
8976   Handle(AIS_Manipulator) aManipulator;
8977   if (!aMapAIS.IsBound2 (aName))
8978   {
8979     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
8980
8981     aManipulator = new ViewerTest_AISManipulator();
8982     aMapAIS.Bind (aManipulator, aName);
8983   }
8984   else
8985   {
8986     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
8987     if (aManipulator.IsNull())
8988     {
8989       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
8990       return 1;
8991     }
8992   }
8993
8994   // -----------------------------------------
8995   // change properties of manipulator instance
8996   // -----------------------------------------
8997
8998   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
8999   {
9000     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
9001   }
9002   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
9003   {
9004     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
9005   }
9006   if (aCmd.HasOption ("followRotation", 1, Standard_True))
9007   {
9008     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
9009   }
9010   if (aCmd.HasOption ("gap", 1, Standard_True))
9011   {
9012     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
9013   }
9014   if (aCmd.HasOption ("part", 3, Standard_True))
9015   {
9016     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
9017     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
9018     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
9019     if (aMode < 1 || aMode > 3)
9020     {
9021       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
9022       return 1;
9023     }
9024
9025     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
9026   }
9027   if (aCmd.HasOption ("pos", 3, Standard_True))
9028   {
9029     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
9030     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
9031     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
9032
9033     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
9034   }
9035   if (aCmd.HasOption ("size", 1, Standard_True))
9036   {
9037     aManipulator->SetSize (aCmd.ArgFloat ("size"));
9038   }
9039   if (aCmd.HasOption ("zoomable", 1, Standard_True))
9040   {
9041     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
9042
9043     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
9044     {
9045       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
9046       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
9047     }
9048   }
9049
9050   // ---------------------------------------------------
9051   // attach, detach or access manipulator from an object
9052   // ---------------------------------------------------
9053
9054   if (aCmd.HasOption ("attach"))
9055   {
9056     // Find an object and attach manipulator to it
9057     if (!aCmd.HasOption ("attach", 1, Standard_True))
9058     {
9059       return 1;
9060     }
9061
9062     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
9063     if (!aMapAIS.IsBound2 (anObjName))
9064     {
9065       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
9066       return 1;
9067     }
9068
9069     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
9070     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
9071     for (; anIt.More(); anIt.Next())
9072     {
9073       if (anIt.Value()->IsAttached()
9074        && anIt.Value()->Object() == anObject)
9075       {
9076         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
9077         return 1;
9078       }
9079     }
9080
9081     AIS_Manipulator::OptionsForAttach anOptions;
9082     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
9083     {
9084       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
9085     }
9086     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
9087     {
9088       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
9089     }
9090     if (aCmd.HasOption ("enableModes", 1, Standard_True))
9091     {
9092       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
9093     }
9094
9095     aManipulator->Attach (anObject, anOptions);
9096   }
9097
9098   // --------------------------------------
9099   // apply transformation using manipulator
9100   // --------------------------------------
9101
9102   if (aCmd.HasOption ("startTransform", 2, Standard_True))
9103   {
9104     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
9105   }
9106   if (aCmd.HasOption ("transform", 2, Standard_True))
9107   {
9108     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
9109   }
9110   if (aCmd.HasOption ("stopTransform"))
9111   {
9112     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
9113
9114     aManipulator->StopTransform (toApply);
9115   }
9116
9117   gp_Trsf aT;
9118   if (aCmd.HasOption ("move", 3, Standard_True))
9119   {
9120     aT.SetTranslationPart (aCmd.ArgVec ("move"));
9121   }
9122   if (aCmd.HasOption ("rotate", 7, Standard_True))
9123   {
9124     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
9125   }
9126   if (aCmd.HasOption ("scale", 1))
9127   {
9128     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
9129   }
9130
9131   if (aT.Form() != gp_Identity)
9132   {
9133     aManipulator->Transform (aT);
9134   }
9135
9136   ViewerTest::GetAISContext()->Redisplay (aManipulator);
9137
9138   return 0;
9139 }
9140
9141 //=======================================================================
9142 //function : ViewerCommands
9143 //purpose  :
9144 //=======================================================================
9145
9146 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
9147 {
9148
9149   const char *group = "ZeViewer";
9150   theCommands.Add("vinit",
9151 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
9152     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
9153 #else
9154     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
9155 #endif
9156     " - Creates new View window with specified name view_name.\n"
9157     "By default the new view is created in the viewer and in"
9158     " graphic driver shared with active view.\n"
9159     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
9160     "If driverName isn't specified the driver will be shared with active view.\n"
9161     "If viewerName isn't specified the viewer will be shared with active view.\n"
9162 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
9163     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
9164     "is used in creation of graphic driver\n"
9165 #endif
9166     " - l, t: pixel position of left top corner of the window\n"
9167     " - w,h: width and heigth of window respectively.\n"
9168     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
9169     __FILE__,VInit,group);
9170   theCommands.Add("vclose" ,
9171     "[view_id [keep_context=0|1]]\n"
9172     "or vclose ALL - to remove all created views\n"
9173     " - removes view(viewer window) defined by its view_id.\n"
9174     " - keep_context: by default 0; if 1 and the last view is deleted"
9175     " the current context is not removed.",
9176     __FILE__,VClose,group);
9177   theCommands.Add("vactivate" ,
9178     "view_id"
9179     " - activates view(viewer window) defined by its view_id",
9180     __FILE__,VActivate,group);
9181   theCommands.Add("vviewlist",
9182     "vviewlist [format={tree, long}]"
9183     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
9184     " - format: format of result output, if tree the output is a tree view;"
9185     "otherwise it's a list of full view names. By default format = tree",
9186     __FILE__,VViewList,group);
9187   theCommands.Add("vhelp" ,
9188     "vhelp            : display help on the viewer commands",
9189     __FILE__,VHelp,group);
9190   theCommands.Add("vtop" ,
9191     "vtop or <T>      : Top view. Orientation +X+Y" ,
9192     __FILE__,VTop,group);
9193   theCommands.Add("vbottom" ,
9194     "vbottom          : Bottom view. Orientation +X-Y" ,
9195     __FILE__,VBottom,group);
9196   theCommands.Add("vleft" ,
9197     "vleft            : Left view. Orientation -Y+Z" ,
9198     __FILE__,VLeft,group);
9199   theCommands.Add("vright" ,
9200     "vright           : Right view. Orientation +Y+Z" ,
9201     __FILE__,VRight,group);
9202   theCommands.Add("vaxo" ,
9203     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
9204     __FILE__,VAxo,group);
9205   theCommands.Add("vfront" ,
9206     "vfront           : Front view. Orientation +X+Z" ,
9207     __FILE__,VFront,group);
9208   theCommands.Add("vback" ,
9209     "vback            : Back view. Orientation -X+Z" ,
9210     __FILE__,VBack,group);
9211   theCommands.Add("vpick" ,
9212     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
9213     VPick,group);
9214   theCommands.Add("vfit"    ,
9215     "vfit or <F> [-selected]"
9216     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
9217     __FILE__,VFit,group);
9218   theCommands.Add ("vfitarea",
9219     "vfitarea x1 y1 x2 y2"
9220     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
9221     "\n\t\t: Fit view to show area located between two points"
9222     "\n\t\t: given in world 2D or 3D corrdinates.",
9223     __FILE__, VFitArea, group);
9224   theCommands.Add ("vzfit", "vzfit [scale]\n"
9225     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
9226     "   \"scale\" - specifies factor to scale computed z range.\n",
9227     __FILE__, VZFit, group);
9228   theCommands.Add("vrepaint",
9229     "vrepaint        : vrepaint, force redraw",
9230     __FILE__,VRepaint,group);
9231   theCommands.Add("vclear",
9232     "vclear          : vclear"
9233     "\n\t\t: remove all the object from the viewer",
9234     __FILE__,VClear,group);
9235   theCommands.Add("vsetbg",
9236     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
9237     __FILE__,VSetBg,group);
9238   theCommands.Add("vsetbgmode",
9239     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
9240     __FILE__,VSetBgMode,group);
9241   theCommands.Add("vsetgradientbg",
9242     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
9243     __FILE__,VSetGradientBg,group);
9244   theCommands.Add("vsetgrbgmode",
9245     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
9246     __FILE__,VSetGradientBgMode,group);
9247   theCommands.Add("vsetcolorbg",
9248     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
9249     __FILE__,VSetColorBg,group);
9250   theCommands.Add("vsetdefaultbg",
9251     "vsetdefaultbg r g b\n"
9252     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
9253     "\n\t\t: Set default viewer background fill color (flat/gradient).",
9254     __FILE__,VSetDefaultBg,group);
9255   theCommands.Add("vscale",
9256     "vscale          : vscale X Y Z",
9257     __FILE__,VScale,group);
9258   theCommands.Add("vzbufftrihedron",
9259             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
9260     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
9261     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
9262     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
9263     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
9264     "\n\t\t: Displays a trihedron",
9265     __FILE__,VZBuffTrihedron,group);
9266   theCommands.Add("vrotate",
9267     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
9268     "\n                : Option -mouseStart starts rotation according to the mouse position"
9269     "\n                : Option -mouseMove continues rotation with angle computed"
9270     "\n                : from last and new mouse position."
9271     "\n                : vrotate AX AY AZ [X Y Z]",
9272     __FILE__,VRotate,group);
9273   theCommands.Add("vzoom",
9274     "vzoom           : vzoom coef",
9275     __FILE__,VZoom,group);
9276   theCommands.Add("vpan",
9277     "vpan            : vpan dx dy",
9278     __FILE__,VPan,group);
9279   theCommands.Add("vexport",
9280     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
9281     " : exports the view to a vector file of a given format"
9282     " : notice that EMF format requires patched gl2ps",
9283     __FILE__,VExport,group);
9284   theCommands.Add("vcolorscale",
9285     "vcolorscale     : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16  -textpos "
9286     "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n"
9287     "-demo/-demoversion draw a demoversion of color scale.\n"
9288     "-show/display display color scale.\n"
9289     "-hide/erase erase color scale.\n"
9290     "Please note that -show/-hide option must be the first argument!\n"
9291     "-color Index R G B: set color for indexed interval\n"
9292     "-color Index ColorName: set color for indexed interval\n"
9293     "-colors R G B R G B ...: set colors for all intervals\n"
9294     "-colors ColorName1 ColorName2 ...: set colors for all intervals\n"
9295     "-colors supports both color names and rgb values in one call\n"
9296     "-label Index Text: set label for indexed interval\n"
9297     "-labels Text Text Text ...: set labels for all intervals\n"
9298     "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n"
9299     "Available text positions: left, right, center, none;\n",
9300     __FILE__,VColorScale,group);
9301   theCommands.Add("vgraduatedtrihedron",
9302     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
9303     "\t[-namefont Name] [-valuesfont Name]\n"
9304     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
9305     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
9306     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
9307     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
9308     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
9309     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
9310     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
9311     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
9312     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
9313     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
9314     " - Displays or erases graduated trihedron"
9315     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
9316     " - namefont - font of axes names. Default: Arial\n"
9317     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
9318     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
9319     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
9320     " - valuesfont - font of axes values. Default: Arial\n"
9321     " - xcolor, ycolor, zcolor - color of axis and values\n"
9322     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
9323     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
9324     __FILE__,VGraduatedTrihedron,group);
9325   theCommands.Add("vprintview" ,
9326     "vprintview : width height filename [algo=0] [tile_width tile_height] : Test print algorithm: algo = 0 - stretch, algo = 1 - tile",
9327     __FILE__,VPrintView,group);
9328   theCommands.Add("vzlayer",
9329     "vzlayer add/del/get/settings/enable/disable [id]\n"
9330     " add - add new z layer to viewer and print its id\n"
9331     " del - del z layer by its id\n"
9332     " get - print sequence of z layers in increasing order of their overlay level\n"
9333     " settings - print status of z layer settings\n"
9334     " enable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    enables given setting for the z layer\n"
9335     " enable (p[ositive]offset/n[egative]offset) \n    enables given setting for the z layer\n"
9336     " enable textureenv \n    enables environment texture mapping\n"
9337     " disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    disables given setting for the z layer\n"
9338     " disable textureenv \n    disables environment texture mapping\n"
9339     "\nWhere id is the layer identificator\n"
9340     "\nExamples:\n"
9341     "   vzlayer add\n"
9342     "   vzlayer enable poffset 1\n"
9343     "   vzlayer disable depthtest 1\n"
9344     "   vzlayer del 1\n",
9345     __FILE__,VZLayer,group);
9346   theCommands.Add("vlayerline",
9347     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
9348     __FILE__,VLayerLine,group);
9349   theCommands.Add ("vgrid",
9350     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
9351     " : Mode - rectangular or circular"
9352     " : Type - lines or points",
9353     __FILE__, VGrid, group);
9354   theCommands.Add ("vpriviledgedplane",
9355     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
9356     "\n\t\t:   Ox, Oy, Oz - plane origin"
9357     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
9358     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
9359     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
9360     __FILE__, VPriviledgedPlane, group);
9361   theCommands.Add ("vconvert",
9362     "vconvert v [Mode={window|view}]"
9363     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
9364     "\n\t\t: vconvert x y z [Mode={window|grid}]"
9365     "\n\t\t:   window - convert to window coordinates, pixels"
9366     "\n\t\t:   view   - convert to view projection plane"
9367     "\n\t\t:   grid   - convert to model coordinates, given on grid"
9368     "\n\t\t:   ray    - convert projection ray to model coordiantes"
9369     "\n\t\t: - vconvert v window : convert view to window;"
9370     "\n\t\t: - vconvert v view   : convert window to view;"
9371     "\n\t\t: - vconvert x y window : convert view to window;"
9372     "\n\t\t: - vconvert x y view : convert window to view;"
9373     "\n\t\t: - vconvert x y : convert window to model;"
9374     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
9375     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
9376     "\n\t\t: - vconvert x y z window : convert model to window;"
9377     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
9378     "\n\t\t: Converts the given coordinates to window/view/model space.",
9379     __FILE__, VConvert, group);
9380   theCommands.Add ("vfps",
9381     "vfps [framesNb=100] : estimate average frame rate for active view",
9382     __FILE__, VFps, group);
9383   theCommands.Add ("vgldebug",
9384             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
9385     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
9386     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
9387     "\n\t\t: Debug context can be requested only on Windows"
9388     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
9389     "\n\t\t:  -sync     - request synchronized debug GL context"
9390     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
9391     "\n\t\t:              which are suppressed by default,"
9392     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
9393     "\n\t\t:              which are suppressed by default",
9394     __FILE__, VGlDebug, group);
9395   theCommands.Add ("vvbo",
9396     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
9397     __FILE__, VVbo, group);
9398   theCommands.Add ("vstereo",
9399             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
9400     "\n\t\t:         [-anaglyph Filter]"
9401     "\n\t\t: Control stereo output mode. Available modes for -mode:"
9402     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
9403     "\n\t\t:                     requires driver support."
9404     "\n\t\t:                     Should be called BEFORE vinit!"
9405     "\n\t\t:  anaglyph         - Anaglyph glasses"
9406     "\n\t\t:  rowInterlaced    - row-interlaced display"
9407     "\n\t\t:  columnInterlaced - column-interlaced display"
9408     "\n\t\t:  chessBoard       - chess-board output"
9409     "\n\t\t:  sideBySide       - horizontal pair"
9410     "\n\t\t:  overUnder        - vertical   pair"
9411     "\n\t\t: Available Anaglyph filters for -anaglyph:"
9412     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
9413     "\n\t\t:  greenMagentaSimple",
9414     __FILE__, VStereo, group);
9415   theCommands.Add ("vcaps",
9416             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
9417     "\n\t\t:       [-compatibleProfile {0|1}]"
9418     "\n\t\t:       [-vsync {0|1}]"
9419     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
9420     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
9421     "\n\t\t: Modify particular graphic driver options:"
9422     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
9423     "\n\t\t:             built-in GLSL programs"
9424     "\n\t\t:            (requires compatible profile)"
9425     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
9426     "\n\t\t:             arrays to GPU memory)"
9427     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
9428     "\n\t\t:  vsync    - switch VSync on or off"
9429     "\n\t\t: Context creation options:"
9430     "\n\t\t:  softMode          - software OpenGL implementation"
9431     "\n\t\t:  compatibleProfile - backward-compatible profile"
9432     "\n\t\t:  quadbuffer        - QuadBuffer"
9433     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
9434     "\n\t\t: rendering paths producing the same visual result when"
9435     "\n\t\t: possible."
9436     "\n\t\t: Command is intended for testing old hardware compatibility.",
9437     __FILE__, VCaps, group);
9438   theCommands.Add ("vmemgpu",
9439     "vmemgpu [f]: print system-dependent GPU memory information if available;"
9440     " with f option returns free memory in bytes",
9441     __FILE__, VMemGpu, group);
9442   theCommands.Add ("vreadpixel",
9443     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
9444     " : Read pixel value for active view",
9445     __FILE__, VReadPixel, group);
9446   theCommands.Add("diffimage",
9447     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
9448     __FILE__, VDiffImage, group);
9449   theCommands.Add ("vselect",
9450     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
9451     "- emulates different types of selection:\n"
9452     "- 1) single click selection\n"
9453     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
9454     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
9455     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
9456     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
9457     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
9458     " (partial inclusion - overlap - is not allowed by default)\n"
9459     "- 5) any of these selections with shift button pressed",
9460     __FILE__, VSelect, group);
9461   theCommands.Add ("vmoveto",
9462     "vmoveto x y"
9463     "- emulates cursor movement to pixel postion (x,y)",
9464     __FILE__, VMoveTo, group);
9465   theCommands.Add ("vviewparams", "vviewparams usage:\n"
9466     "- vviewparams\n"
9467     "- vviewparams [-scale [s]] [-eye [x y z]] [-at [x y z]] [-up [x y z]]\n"
9468     "              [-proj [x y z]] [-center x y] [-size sx]\n"
9469     "-   Gets or sets current view parameters.\n"
9470     "-   If called without arguments, all view parameters are printed.\n"
9471     "-   The options are:\n"
9472     "      -scale [s]    : prints or sets viewport relative scale.\n"
9473     "      -eye [x y z]  : prints or sets eye location.\n"
9474     "      -at [x y z]   : prints or sets center of look.\n"
9475     "      -up [x y z]   : prints or sets direction of up vector.\n"
9476     "      -proj [x y z] : prints or sets direction of look.\n"
9477     "      -center x y   : sets location of center of the screen in pixels.\n"
9478     "      -size [sx]    : prints viewport projection width and height sizes\n"
9479     "                    : or changes the size of its maximum dimension.\n",
9480     __FILE__, VViewParams, group);
9481   theCommands.Add("vchangeselected",
9482     "vchangeselected shape"
9483     "- adds to shape to selection or remove one from it",
9484                 __FILE__, VChangeSelected, group);
9485   theCommands.Add("vzclipping",
9486     "vzclipping [mode] [depth width]\n"
9487     "- mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]\n"
9488     "- gets or sets ZClipping mode, width and depth",
9489     __FILE__,VZClipping,group);
9490   theCommands.Add ("vnbselected",
9491     "vnbselected"
9492     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
9493   theCommands.Add ("vcamera",
9494               "vcamera [-ortho] [-projtype]"
9495       "\n\t\t:         [-persp]"
9496       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
9497       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
9498       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
9499       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
9500       "\n\t\t: Manage camera parameters."
9501       "\n\t\t: Prints current value when option called without argument."
9502       "\n\t\t: Orthographic camera:"
9503       "\n\t\t:   -ortho      activate orthographic projection"
9504       "\n\t\t: Perspective camera:"
9505       "\n\t\t:   -persp      activate perspective  projection (mono)"
9506       "\n\t\t:   -fovy       field of view in y axis, in degrees"
9507       "\n\t\t:   -distance   distance of eye from camera center"
9508       "\n\t\t: Stereoscopic camera:"
9509       "\n\t\t:   -stereo     perspective  projection (stereo)"
9510       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
9511       "\n\t\t:   -rightEye   perspective  projection (right eye)"
9512       "\n\t\t:   -iod        intraocular distance value"
9513       "\n\t\t:   -iodType    distance type, absolute or relative"
9514       "\n\t\t:   -zfocus     stereographic focus value"
9515       "\n\t\t:   -zfocusType focus type, absolute or relative",
9516     __FILE__, VCamera, group);
9517   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
9518     "- vautozfit [on={1|0}] [scale]\n"
9519     "    Prints or changes parameters of automatic z-fit mode:\n"
9520     "   \"on\" - turns automatic z-fit on or off\n"
9521     "   \"scale\" - specifies factor to scale computed z range.\n",
9522     __FILE__, VAutoZFit, group);
9523   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
9524     "   vzrange                - without parameters shows current values\n"
9525     "   vzrange [znear] [zfar] - applies provided values to view",
9526     __FILE__,VZRange, group);
9527   theCommands.Add("vantialiasing",
9528     "vantialiasing 1|0"
9529     "\n\t\t: Switches altialiasing on or off",
9530     __FILE__,VAntialiasing,group);
9531   theCommands.Add ("vpurgedisplay",
9532     "vpurgedisplay"
9533     "- removes structures which don't belong to objects displayed in neutral point",
9534     __FILE__, VPurgeDisplay, group);
9535   theCommands.Add("vsetviewsize",
9536     "vsetviewsize size",
9537     __FILE__,VSetViewSize,group);
9538   theCommands.Add("vmoveview",
9539     "vmoveview Dx Dy Dz [Start = 1|0]",
9540     __FILE__,VMoveView,group);
9541   theCommands.Add("vtranslateview",
9542     "vtranslateview Dx Dy Dz [Start = 1|0)]",
9543     __FILE__,VTranslateView,group);
9544   theCommands.Add("vturnview",
9545     "vturnview Ax Ay Az [Start = 1|0]",
9546     __FILE__,VTurnView,group);
9547   theCommands.Add("vtextureenv",
9548     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
9549     "or user-defined file and optionally applying texture mapping parameters\n"
9550     "                  Usage:\n"
9551     "                  vtextureenv off - disables environment mapping\n"
9552     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
9553     "                              std_texture = (0..7)\n"
9554     "                              rep         = {clamp|repeat}\n"
9555     "                              mod         = {decal|modulate}\n"
9556     "                              flt         = {nearest|bilinear|trilinear}\n"
9557     "                              ss, st      - scale factors for s and t texture coordinates\n"
9558     "                              ts, tt      - translation for s and t texture coordinates\n"
9559     "                              rot         - texture rotation angle in degrees",
9560     __FILE__, VTextureEnv, group);
9561   theCommands.Add("vhlr" ,
9562     "is_enabled={on|off} [show_hidden={1|0}]"
9563     " - Hidden line removal algorithm:"
9564     " - is_enabled: if is on HLR algorithm is applied\n"
9565     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
9566     __FILE__,VHLR,group);
9567   theCommands.Add("vhlrtype" ,
9568     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
9569     " - Changes the type of HLR algorithm using for shapes."
9570     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
9571     "   if equals to polyalgo, polygonal HLR algorithm is applied."
9572     "If shapes are not given HLR algoithm of given type is applied"
9573     " to all shapes in the view\n",
9574     __FILE__,VHLRType,group);
9575   theCommands.Add("vclipplane", "vclipplane usage: \n"
9576     "  maxplanes <view_name> - get plane limit for view.\n"
9577     "  create <plane_name> - create new plane.\n"
9578     "  delete <plane_name> - delete plane.\n"
9579     "  clone <source_plane> <plane_name> - clone the plane definition.\n"
9580     "  set/unset <plane_name> object <object list> - set/unset plane for IO.\n"
9581     "  set/unset <plane_name> view <view list> - set/unset plane for view.\n"
9582     "  change <plane_name> on/off - turn clipping on/off.\n"
9583     "  change <plane_name> equation <a> <b> <c> <d> - change plane equation.\n"
9584     "  change <plane_name> capping on/off - turn capping on/off.\n"
9585     "  change <plane_name> capping color <r> <g> <b> - set color.\n"
9586     "  change <plane name> capping texname <texture> - set texture.\n"
9587     "  change <plane_name> capping texscale <sx> <sy> - set tex scale.\n"
9588     "  change <plane_name> capping texorigin <tx> <ty> - set tex origin.\n"
9589     "  change <plane_name> capping texrotate <angle> - set tex rotation.\n"
9590     "  change <plane_name> capping hatch on/off/<id> - set hatching mask.\n"
9591     "  please use VSetTextureMode command to enable texture rendering in view.\n"
9592     , __FILE__, VClipPlane, group);
9593   theCommands.Add("vdefaults",
9594                "vdefaults [-absDefl value]"
9595        "\n\t\t:           [-devCoeff value]"
9596        "\n\t\t:           [-angDefl value]"
9597        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
9598     , __FILE__, VDefaults, group);
9599   theCommands.Add("vlight",
9600     "tool to manage light sources, without arguments shows list of lights."
9601     "\n    Main commands: "
9602     "\n      'clear' to clear lights"
9603     "\n      '{def}aults' to load deafault lights"
9604     "\n      'add' (or 'new') <type> to add any light source"
9605     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
9606     "\n      'change' <lightId> to edit light source with specified lightId"
9607     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
9608     "\n        {pos}ition X Y Z"
9609     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
9610     "\n        color colorName"
9611     "\n        {head}light 0|1"
9612     "\n        {sm}oothness value"
9613     "\n        {int}ensity value"
9614     "\n        {constAtten}uation value"
9615     "\n        {linearAtten}uation value"
9616     "\n        angle angleDeg"
9617     "\n        {spotexp}onent value"
9618     "\n        local|global"
9619     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
9620     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
9621     __FILE__, VLight, group);
9622   theCommands.Add("vraytrace",
9623             "vraytrace [0|1]"
9624     "\n\t\t: Turns on/off ray-tracing renderer."
9625     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
9626     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
9627     __FILE__, VRenderParams, group);
9628   theCommands.Add("vrenderparams",
9629     "\n    Manages rendering parameters: "
9630     "\n      '-raster'               Disables GPU ray-tracing"
9631     "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
9632     "\n      '-rayTrace'             Enables  GPU ray-tracing"
9633     "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
9634     "\n      '-shadows      on|off'  Enables/disables shadows rendering"
9635     "\n      '-reflections  on|off'  Enables/disables specular reflections"
9636     "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
9637     "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
9638     "\n      '-gi           on|off'  Enables/disables global illumination effects"
9639     "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
9640     "\n      '-env          on|off'  Enables/disables environment map background"
9641     "\n      '-shadingModel model'   Controls shading model from enumeration"
9642     "\n                              color, flat, gouraud, phong"
9643     "\n      '-resolution   value'   Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
9644     "\n    Unlike vcaps, these parameters dramatically change visual properties."
9645     "\n    Command is intended to control presentation quality depending on"
9646     "\n    hardware capabilities and performance.",
9647     __FILE__, VRenderParams, group);
9648   theCommands.Add("vfrustumculling",
9649     "vfrustumculling [toEnable]: enables/disables objects clipping",
9650     __FILE__,VFrustumCulling,group);
9651   theCommands.Add("vhighlightselected",
9652     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
9653     "Without arguments it shows if highlighting of selected objects is enabled now.",
9654     __FILE__,VHighlightSelected,group);
9655   theCommands.Add ("vplace",
9656             "vplace dx dy"
9657     "\n\t\t: Places the point (in pixels) at the center of the window",
9658     __FILE__, VPlace, group);
9659   theCommands.Add("vxrotate",
9660     "vxrotate",
9661     __FILE__,VXRotate,group);
9662
9663     theCommands.Add("vmanipulator",
9664       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
9665       "\n    tool to create and manage AIS manipulators."
9666       "\n    Options: "
9667       "\n      '-attach AISObject'                 attach manipulator to AISObject"
9668       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
9669       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
9670       "\n      '-enableModes    {0|1}'             enable modes when attaching"
9671       "\n      '-detach'                           detach manipulator"
9672       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
9673       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
9674       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
9675       "\n      '-move x y z'                     - move attached object"
9676       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
9677       "\n      '-scale factor'                   - scale attached object"
9678       "\n      '-autoActivate      {0|1}'        - set activation on detection"
9679       "\n      '-followTranslation {0|1}'        - set following translation transform"
9680       "\n      '-followRotation    {0|1}'        - set following rotation transform"
9681       "\n      '-gap value'                      - set gap between sub-parts"
9682       "\n      '-part axis mode    {0|1}'        - set visual part"
9683       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
9684       "\n      '-size value'                     - set size of manipulator"
9685       "\n      '-zoomable {0|1}'                 - set zoom persistence",
9686     __FILE__, VManipulator, group);
9687
9688 #if defined(_WIN32)
9689   theCommands.Add("vprogressive",
9690     "vprogressive",
9691     __FILE__, VProgressiveMode, group);
9692 #endif
9693 }