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