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