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