a8f65a72a57a4fd2efafb00de7662a74a82e393d
[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
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_ColorScale.hxx>
23 #include <AIS_Manipulator.hxx>
24 #include <AIS_RubberBand.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_InteractiveObject.hxx>
27 #include <AIS_ListOfInteractive.hxx>
28 #include <AIS_ListIteratorOfListOfInteractive.hxx>
29 #include <DBRep.hxx>
30 #include <Draw_ProgressIndicator.hxx>
31 #include <Graphic3d_ArrayOfPolylines.hxx>
32 #include <Graphic3d_AspectMarker3d.hxx>
33 #include <Graphic3d_ExportFormat.hxx>
34 #include <Graphic3d_NameOfTextureEnv.hxx>
35 #include <Graphic3d_GraduatedTrihedron.hxx>
36 #include <Graphic3d_TextureEnv.hxx>
37 #include <Graphic3d_TextureParams.hxx>
38 #include <Graphic3d_TypeOfTextureFilter.hxx>
39 #include <Graphic3d_AspectFillArea3d.hxx>
40 #include <ViewerTest.hxx>
41 #include <ViewerTest_AutoUpdater.hxx>
42 #include <ViewerTest_EventManager.hxx>
43 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
45 #include <ViewerTest_CmdParser.hxx>
46 #include <V3d_AmbientLight.hxx>
47 #include <V3d_DirectionalLight.hxx>
48 #include <V3d_PositionalLight.hxx>
49 #include <V3d_SpotLight.hxx>
50 #include <Message_ProgressSentry.hxx>
51 #include <NCollection_DoubleMap.hxx>
52 #include <NCollection_List.hxx>
53 #include <NCollection_Vector.hxx>
54 #include <AIS_InteractiveContext.hxx>
55 #include <Draw_Interpretor.hxx>
56 #include <Draw.hxx>
57 #include <Draw_Appli.hxx>
58 #include <Image_AlienPixMap.hxx>
59 #include <Image_VideoRecorder.hxx>
60 #include <OpenGl_GraphicDriver.hxx>
61 #include <OSD_Timer.hxx>
62 #include <TColStd_HSequenceOfAsciiString.hxx>
63 #include <TColStd_SequenceOfInteger.hxx>
64 #include <TColStd_HSequenceOfReal.hxx>
65 #include <TColgp_Array1OfPnt2d.hxx>
66 #include <TColStd_MapOfAsciiString.hxx>
67 #include <Aspect_TypeOfLine.hxx>
68 #include <Image_Diff.hxx>
69 #include <Aspect_DisplayConnection.hxx>
70 #include <gp_Pnt.hxx>
71 #include <gp_Dir.hxx>
72 #include <gp_Pln.hxx>
73 #include <PrsMgr_PresentableObject.hxx>
74 #include <Graphic3d_ClipPlane.hxx>
75 #include <NCollection_DataMap.hxx>
76 #include <Graphic3d_Texture2Dmanual.hxx>
77 #include <Prs3d_ShadingAspect.hxx>
78 #include <Prs3d_Drawer.hxx>
79 #include <Prs3d_LineAspect.hxx>
80 #include <Prs3d_Root.hxx>
81 #include <Prs3d_Text.hxx>
82 #include <Select3D_SensitivePrimitiveArray.hxx>
83
84 #ifdef _WIN32
85 #undef DrawText
86 #endif
87
88 #include <cstdlib>
89
90 #if defined(_WIN32)
91   #include <WNT_WClass.hxx>
92   #include <WNT_Window.hxx>
93 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
94   #include <Cocoa_Window.hxx>
95 #else
96   #include <Xw_Window.hxx>
97   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
98   #include <X11/Xutil.h>
99   #include <tk.h>
100 #endif
101
102 // Auxiliary definitions
103 static const char THE_KEY_DELETE = 127;
104 static const char THE_KEY_ESCAPE = 27;
105
106 //==============================================================================
107 //  VIEWER GLOBAL VARIABLES
108 //==============================================================================
109
110 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
111 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
112
113 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
114 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
115
116 extern int VErase (Draw_Interpretor& theDI,
117                    Standard_Integer  theArgNb,
118                    const char**      theArgVec);
119
120 #if defined(_WIN32)
121 static Handle(WNT_Window)& VT_GetWindow() {
122   static Handle(WNT_Window) WNTWin;
123   return WNTWin;
124 }
125 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
126 static Handle(Cocoa_Window)& VT_GetWindow()
127 {
128   static Handle(Cocoa_Window) aWindow;
129   return aWindow;
130 }
131 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
132 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
133 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
134
135 #else
136 static Handle(Xw_Window)& VT_GetWindow(){
137   static Handle(Xw_Window) XWWin;
138   return XWWin;
139 }
140
141 static void VProcessEvents(ClientData,int);
142 #endif
143
144 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
145 {
146   static Handle(Aspect_DisplayConnection) aDisplayConnection;
147   return aDisplayConnection;
148 }
149
150 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
151 {
152   GetDisplayConnection() = theDisplayConnection;
153 }
154
155 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
156 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
157 {
158   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
159 #if defined(_WIN32)
160   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
161   if (!aWindow.IsNull())
162     return aWindow->HWindow();
163 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
164   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
165   if (!aWindow.IsNull())
166   return aWindow->XWindow();
167 #endif
168   return aWindowHandle;
169 }
170 #endif
171
172 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
173 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
174 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
175 static OpenGl_Caps ViewerTest_myDefaultCaps;
176
177 static void OSWindowSetup();
178
179 static struct
180 {
181   Quantity_Color FlatColor;
182   Quantity_Color GradientColor1;
183   Quantity_Color GradientColor2;
184   Aspect_GradientFillMethod FillMethod;
185 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
186
187 //==============================================================================
188 //  EVENT GLOBAL VARIABLES
189 //==============================================================================
190
191 static int Start_Rot = 0;
192 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
193 int X_Motion = 0; // Current cursor position
194 int Y_Motion = 0;
195 int X_ButtonPress = 0; // Last ButtonPress position
196 int Y_ButtonPress = 0;
197 Standard_Boolean IsDragged = Standard_False;
198 Standard_Boolean DragFirst = Standard_False;
199 Standard_Boolean TheIsAnimating = Standard_False;
200 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
201 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
202
203
204 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
205 {
206   static Handle(AIS_RubberBand) aBand;
207   if (aBand.IsNull())
208   {
209     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
210     aBand->SetDisplayMode (0);
211   }
212   return aBand;
213 }
214
215 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
216
217 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
218 {
219   static ViewerTest_MapOfAISManipulators aMap;
220   return aMap;
221 }
222
223 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
224 {
225   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
226   for (; anIt.More(); anIt.Next())
227   {
228     if (anIt.Value()->HasActiveMode())
229     {
230       return anIt.Value();
231     }
232   }
233   return NULL;
234 }
235
236 //==============================================================================
237
238 #ifdef _WIN32
239 static LRESULT WINAPI ViewerWindowProc(
240                                        HWND hwnd,
241                                        UINT uMsg,
242                                        WPARAM wParam,
243                                        LPARAM lParam );
244 static LRESULT WINAPI AdvViewerWindowProc(
245   HWND hwnd,
246   UINT uMsg,
247   WPARAM wParam,
248   LPARAM lParam );
249 #endif
250
251
252 //==============================================================================
253 //function : WClass
254 //purpose  :
255 //==============================================================================
256
257 const Handle(Standard_Transient)& ViewerTest::WClass()
258 {
259   static Handle(Standard_Transient) theWClass;
260 #if defined(_WIN32)
261   if (theWClass.IsNull())
262   {
263     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
264                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
265                                 ::LoadCursor (NULL, IDC_ARROW));
266   }
267 #endif
268   return theWClass;
269 }
270
271 //==============================================================================
272 //function : CreateName
273 //purpose  : Create numerical name for new object in theMap
274 //==============================================================================
275 template <typename ObjectType>
276 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
277                                     const TCollection_AsciiString& theDefaultString)
278 {
279   if (theObjectMap.IsEmpty())
280     return theDefaultString + TCollection_AsciiString(1);
281
282   Standard_Integer aNextKey = 1;
283   Standard_Boolean isFound = Standard_False;
284   while (!isFound)
285   {
286     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
287     // Look for objects with default names
288     if (theObjectMap.IsBound1(aStringKey))
289     {
290       aNextKey++;
291     }
292     else
293       isFound = Standard_True;
294   }
295
296   return theDefaultString + TCollection_AsciiString(aNextKey);
297 }
298
299 //==============================================================================
300 //structure : ViewerTest_Names
301 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
302 //==============================================================================
303 struct ViewerTest_Names
304 {
305 private:
306   TCollection_AsciiString myDriverName;
307   TCollection_AsciiString myViewerName;
308   TCollection_AsciiString myViewName;
309
310 public:
311
312   const TCollection_AsciiString& GetDriverName () const
313   {
314     return myDriverName;
315   }
316   void SetDriverName (const TCollection_AsciiString& theDriverName)
317   {
318     myDriverName = theDriverName;
319   }
320   const TCollection_AsciiString& GetViewerName () const
321   {
322     return myViewerName;
323   }
324   void SetViewerName (const TCollection_AsciiString& theViewerName)
325   {
326     myViewerName = theViewerName;
327   }
328   const TCollection_AsciiString& GetViewName () const
329   {
330     return myViewName;
331   }
332   void SetViewName (const TCollection_AsciiString& theViewName)
333   {
334     myViewName = theViewName;
335   }
336
337   //===========================================================================
338   //function : Constructor for ViewerTest_Names
339   //purpose  : Get view, viewer, driver names from custom string
340   //===========================================================================
341
342   ViewerTest_Names (const TCollection_AsciiString& theInputString)
343   {
344     TCollection_AsciiString aName(theInputString);
345     if (theInputString.IsEmpty())
346     {
347       // Get current configuration
348       if (ViewerTest_myDrivers.IsEmpty())
349         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
350           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
351       else
352         myDriverName = ViewerTest_myDrivers.Find2
353         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
354
355       if(ViewerTest_myContexts.IsEmpty())
356       {
357         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
358           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
359       }
360       else
361       {
362         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
363       }
364
365       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
366     }
367     else
368     {
369       // There is at least view name
370       Standard_Integer aParserNumber = 0;
371       for (Standard_Integer i = 0; i < 3; ++i)
372       {
373         Standard_Integer aParserPos = aName.SearchFromEnd("/");
374         if(aParserPos != -1)
375         {
376           aParserNumber++;
377           aName.Split(aParserPos-1);
378         }
379         else
380           break;
381       }
382       if (aParserNumber == 0)
383       {
384         // Only view name
385         if (!ViewerTest::GetAISContext().IsNull())
386         {
387           myDriverName = ViewerTest_myDrivers.Find2
388           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
389           myViewerName = ViewerTest_myContexts.Find2
390           (ViewerTest::GetAISContext());
391         }
392         else
393         {
394           // There is no opened contexts here, need to create names for viewer and driver
395           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
396             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
397
398           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
399             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
400         }
401         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
402       }
403       else if (aParserNumber == 1)
404       {
405         // Here is viewerName/viewName
406         if (!ViewerTest::GetAISContext().IsNull())
407           myDriverName = ViewerTest_myDrivers.Find2
408           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
409         else
410         {
411           // There is no opened contexts here, need to create name for driver
412           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
413             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
414         }
415         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
416
417         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
418       }
419       else
420       {
421         //Here is driverName/viewerName/viewName
422         myDriverName = TCollection_AsciiString(aName);
423
424         TCollection_AsciiString aViewerName(theInputString);
425         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
426         myViewerName = TCollection_AsciiString(aViewerName);
427
428         myViewName = TCollection_AsciiString(theInputString);
429       }
430     }
431   }
432 };
433
434 //==============================================================================
435 //function : FindContextByView
436 //purpose  : Find AIS_InteractiveContext by View
437 //==============================================================================
438
439 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
440 {
441   Handle(AIS_InteractiveContext) anAISContext;
442
443   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
444        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
445   {
446     if (anIter.Value()->CurrentViewer() == theView->Viewer())
447        return anIter.Key2();
448   }
449   return anAISContext;
450 }
451
452
453 //==============================================================================
454 //function : SetWindowTitle
455 //purpose  : Set window title
456 //==============================================================================
457
458 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
459                      Standard_CString theTitle)
460 {
461 #if defined(_WIN32)
462   const TCollection_ExtendedString theTitleW (theTitle);
463   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
464 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
465   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
466 #else
467   if(GetDisplayConnection()->GetDisplay())
468   {
469     Window aWindow =
470       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
471     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
472   }
473 #endif
474 }
475
476 //==============================================================================
477 //function : IsWindowOverlapped
478 //purpose  : Check if theWindow overlapp another view
479 //==============================================================================
480
481 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
482                                      const Standard_Integer thePxTop,
483                                      const Standard_Integer thePxRight,
484                                      const Standard_Integer thePxBottom,
485                                      TCollection_AsciiString& theViewId)
486 {
487   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
488       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
489   {
490     Standard_Integer aTop = 0,
491       aLeft = 0,
492       aRight = 0,
493       aBottom = 0;
494     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
495     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
496         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
497         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
498         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
499     {
500       theViewId = anIter.Key1();
501       return Standard_True;
502     }
503   }
504   return Standard_False;
505 }
506
507 // Workaround: to create and delete non-orthographic views outside ViewerTest
508 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
509 {
510   ViewerTest_myViews.UnBind1 (theName);
511 }
512
513 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
514                                const Handle(V3d_View)& theView)
515 {
516   ViewerTest_myViews.Bind (theName, theView);
517 }
518
519 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
520 {
521   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
522 }
523 //==============================================================================
524 //function : ViewerInit
525 //purpose  : Create the window viewer and initialize all the global variable
526 //==============================================================================
527
528 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
529                                                 const Standard_Integer thePxTop,
530                                                 const Standard_Integer thePxWidth,
531                                                 const Standard_Integer thePxHeight,
532                                                 Standard_CString theViewName,
533                                                 Standard_CString theDisplayName)
534 {
535   // Default position and dimension of the viewer window.
536   // Note that left top corner is set to be sufficiently small to have
537   // window fit in the small screens (actual for remote desktops, see #23003).
538   // The position corresponds to the window's client area, thus some
539   // gap is added for window frame to be visible.
540   Standard_Integer aPxLeft   = 20;
541   Standard_Integer aPxTop    = 40;
542   Standard_Integer aPxWidth  = 409;
543   Standard_Integer aPxHeight = 409;
544   Standard_Boolean toCreateViewer = Standard_False;
545
546   Handle(OpenGl_GraphicDriver) aGraphicDriver;
547   ViewerTest_Names aViewNames(theViewName);
548   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
549     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
550
551   if (thePxLeft != 0)
552     aPxLeft = thePxLeft;
553   if (thePxTop != 0)
554     aPxTop = thePxTop;
555   if (thePxWidth != 0)
556     aPxWidth = thePxWidth;
557   if (thePxHeight != 0)
558     aPxHeight = thePxHeight;
559
560   // Get graphic driver (create it or get from another view)
561   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
562   {
563     // Get connection string
564   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
565     TCollection_AsciiString aDisplayName(theDisplayName);
566     if (!aDisplayName.IsEmpty())
567       SetDisplayConnection (new Aspect_DisplayConnection ());
568     else
569       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
570   #else
571     (void)theDisplayName; // avoid warning on unused argument
572     SetDisplayConnection (new Aspect_DisplayConnection ());
573   #endif
574
575     if (Draw_VirtualWindows)
576     {
577       // don't waste the time waiting for VSync when window is not displayed on the screen
578       ViewerTest_myDefaultCaps.swapInterval = 0;
579       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
580       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
581     }
582     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
583     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
584
585     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
586     toCreateViewer = Standard_True;
587   }
588   else
589   {
590     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
591   }
592
593   //Dispose the window if input parameters are default
594   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
595   {
596     Standard_Integer aTop = 0,
597                      aLeft = 0,
598                      aRight = 0,
599                      aBottom = 0,
600                      aScreenWidth = 0,
601                      aScreenHeight = 0;
602
603     // Get screen resolution
604 #if defined(_WIN32) || defined(__WIN32__)
605     RECT aWindowSize;
606     GetClientRect(GetDesktopWindow(), &aWindowSize);
607     aScreenHeight = aWindowSize.bottom;
608     aScreenWidth = aWindowSize.right;
609 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
610     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
611 #else
612     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
613     aScreenWidth = WidthOfScreen(aScreen);
614     aScreenHeight = HeightOfScreen(aScreen);
615 #endif
616
617     TCollection_AsciiString anOverlappedViewId("");
618
619     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
620     {
621       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
622
623       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
624         && aRight + 2*aPxWidth + 40 > aScreenWidth)
625       {
626         if (aBottom + aPxHeight + 40 > aScreenHeight)
627         {
628           aPxLeft = 20;
629           aPxTop = 40;
630           break;
631         }
632         aPxLeft = 20;
633         aPxTop = aBottom + 40;
634       }
635       else
636         aPxLeft = aRight + 20;
637     }
638   }
639
640   // Get viewer name
641   TCollection_AsciiString aTitle("3D View - ");
642   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
643
644   // Change name of current active window
645   if (!ViewerTest::CurrentView().IsNull())
646   {
647     TCollection_AsciiString anActiveWindowTitle("3D View - ");
648     anActiveWindowTitle = anActiveWindowTitle
649       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
650     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
651   }
652
653   // Create viewer
654   Handle(V3d_Viewer) a3DViewer;
655   // If it's the single view, we first look for empty context
656   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
657   {
658     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
659       anIter(ViewerTest_myContexts);
660     if (anIter.More())
661       ViewerTest::SetAISContext (anIter.Value());
662     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
663   }
664   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
665   {
666     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
667     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
668   }
669   else if (a3DViewer.IsNull())
670   {
671     toCreateViewer = Standard_True;
672     a3DViewer = new V3d_Viewer(aGraphicDriver);
673     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
674     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
675                                            ViewerTest_DefaultBackground.GradientColor2,
676                                            ViewerTest_DefaultBackground.FillMethod);
677   }
678
679   // AIS context setup
680   if (ViewerTest::GetAISContext().IsNull() ||
681       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
682   {
683     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
684     ViewerTest::SetAISContext (aContext);
685     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
686   }
687   else
688   {
689     ViewerTest::ResetEventManager();
690   }
691
692   // Create window
693 #if defined(_WIN32)
694   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
695                                     Handle(WNT_WClass)::DownCast (WClass()),
696                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
697                                     aPxLeft, aPxTop,
698                                     aPxWidth, aPxHeight,
699                                     Quantity_NOC_BLACK);
700 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
701   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
702                                      aPxLeft, aPxTop,
703                                      aPxWidth, aPxHeight);
704   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
705 #else
706   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
707                                   aTitle.ToCString(),
708                                   aPxLeft, aPxTop,
709                                   aPxWidth, aPxHeight);
710 #endif
711   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
712
713   // View setup
714   Handle(V3d_View) aView = a3DViewer->CreateView();
715   aView->SetWindow (VT_GetWindow());
716   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
717
718   ViewerTest::CurrentView(aView);
719   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
720
721   // Setup for X11 or NT
722   OSWindowSetup();
723
724   // Set parameters for V3d_View and V3d_Viewer
725   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
726   aV3dView->SetComputedMode(Standard_False);
727
728   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
729   if (toCreateViewer)
730   {
731     a3DViewer->SetDefaultLights();
732     a3DViewer->SetLightOn();
733   }
734
735   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
736   #if TCL_MAJOR_VERSION  < 8
737   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
738       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
739   #else
740   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
741       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
742   #endif
743   #endif
744
745   VT_GetWindow()->Map();
746
747   // Set the handle of created view in the event manager
748   ViewerTest::ResetEventManager();
749
750   ViewerTest::CurrentView()->Redraw();
751
752   aView.Nullify();
753   a3DViewer.Nullify();
754
755   return aViewNames.GetViewName();
756 }
757
758 //==============================================================================
759 //function : RedrawAllViews
760 //purpose  : Redraw all created views
761 //==============================================================================
762 void ViewerTest::RedrawAllViews()
763 {
764   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
765   for (; aViewIt.More(); aViewIt.Next())
766   {
767     const Handle(V3d_View)& aView = aViewIt.Key2();
768     aView->Redraw();
769   }
770 }
771
772 //==============================================================================
773 //function : Vinit
774 //purpose  : Create the window viewer and initialize all the global variable
775 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
776 //==============================================================================
777
778 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
779 {
780   TCollection_AsciiString aViewName, aDisplayName;
781   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
782   TCollection_AsciiString aName, aValue;
783   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
784   {
785     const TCollection_AsciiString anArg = theArgVec[anArgIt];
786     TCollection_AsciiString anArgCase = anArg;
787     anArgCase.LowerCase();
788     if (anArgIt + 1 < theArgsNb
789      && anArgCase == "-name")
790     {
791       aViewName = theArgVec[++anArgIt];
792     }
793     else if (anArgIt + 1 < theArgsNb
794           && (anArgCase == "-left"
795            || anArgCase == "-l"))
796     {
797       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
798     }
799     else if (anArgIt + 1 < theArgsNb
800           && (anArgCase == "-top"
801            || anArgCase == "-t"))
802     {
803       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
804     }
805     else if (anArgIt + 1 < theArgsNb
806           && (anArgCase == "-width"
807            || anArgCase == "-w"))
808     {
809       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
810     }
811     else if (anArgIt + 1 < theArgsNb
812           && (anArgCase == "-height"
813            || anArgCase == "-h"))
814     {
815       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
816     }
817     else if (anArgCase == "-exitonclose")
818     {
819       Draw_ToExitOnCloseView = true;
820       if (anArgIt + 1 < theArgsNb
821        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
822       {
823         ++anArgIt;
824       }
825     }
826     else if (anArgCase == "-closeonescape"
827           || anArgCase == "-closeonesc")
828     {
829       Draw_ToCloseViewOnEsc = true;
830       if (anArgIt + 1 < theArgsNb
831        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
832       {
833         ++anArgIt;
834       }
835     }
836     else if (anArgIt + 1 < theArgsNb
837           && (anArgCase == "-disp"
838            || anArgCase == "-display"))
839     {
840       aDisplayName = theArgVec[++anArgIt];
841     }
842     // old syntax
843     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
844     {
845       aName.LowerCase();
846       if (aName == "name")
847       {
848         aViewName = aValue;
849       }
850       else if (aName == "l"
851             || aName == "left")
852       {
853         aPxLeft = aValue.IntegerValue();
854       }
855       else if (aName == "t"
856             || aName == "top")
857       {
858         aPxTop = aValue.IntegerValue();
859       }
860       else if (aName == "disp"
861             || aName == "display")
862       {
863         aDisplayName = aValue;
864       }
865       else if (aName == "w"
866             || aName == "width")
867       {
868         aPxWidth = aValue.IntegerValue();
869       }
870       else if (aName == "h"
871             || aName == "height")
872       {
873         aPxHeight = aValue.IntegerValue();
874       }
875       else
876       {
877         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
878         return 1;
879       }
880     }
881     else if (aViewName.IsEmpty())
882     {
883       aViewName = anArg;
884     }
885     else
886     {
887       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
888       return 1;
889     }
890   }
891
892 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
893   if (!aDisplayName.IsEmpty())
894   {
895     aDisplayName.Clear();
896     std::cout << "Warning: display parameter will be ignored.\n";
897   }
898 #endif
899
900   ViewerTest_Names aViewNames (aViewName);
901   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
902   {
903     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
904     theDi.Eval (aCommand.ToCString());
905     return 0;
906   }
907
908   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
909                                                             aViewName.ToCString(),
910                                                             aDisplayName.ToCString());
911   theDi << aViewId;
912   return 0;
913 }
914
915 //! Parse HLR algo type.
916 static Standard_Boolean parseHlrAlgoType (const char* theName,
917                                           Prs3d_TypeOfHLR& theType)
918 {
919   TCollection_AsciiString aName (theName);
920   aName.LowerCase();
921   if (aName == "polyalgo")
922   {
923     theType = Prs3d_TOH_PolyAlgo;
924   }
925   else if (aName == "algo")
926   {
927     theType = Prs3d_TOH_Algo;
928   }
929   else
930   {
931     return Standard_False;
932   }
933   return Standard_True;
934 }
935
936 //==============================================================================
937 //function : VHLR
938 //purpose  : hidden lines removal algorithm
939 //==============================================================================
940
941 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
942 {
943   const Handle(V3d_View) aView = ViewerTest::CurrentView();
944   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
945   if (aView.IsNull())
946   {
947     std::cerr << "Error: No opened viewer!\n";
948     return 1;
949   }
950
951   Standard_Boolean hasHlrOnArg = Standard_False;
952   Standard_Boolean hasShowHiddenArg = Standard_False;
953   Standard_Boolean isHLROn = Standard_False;
954   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
955   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
956   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
957   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
958   {
959     TCollection_AsciiString anArg (argv[anArgIter]);
960     anArg.LowerCase();
961     if (anUpdateTool.parseRedrawMode (anArg))
962     {
963       continue;
964     }
965     else if (anArg == "-showhidden"
966           && anArgIter + 1 < argc
967           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
968     {
969       ++anArgIter;
970       hasShowHiddenArg = Standard_True;
971       continue;
972     }
973     else if ((anArg == "-type"
974            || anArg == "-algo"
975            || anArg == "-algotype")
976           && anArgIter + 1 < argc
977           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
978     {
979       ++anArgIter;
980       continue;
981     }
982     else if (!hasHlrOnArg
983           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
984     {
985       hasHlrOnArg = Standard_True;
986       continue;
987     }
988     // old syntax
989     else if (!hasShowHiddenArg
990           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
991     {
992       hasShowHiddenArg = Standard_True;
993       continue;
994     }
995     else
996     {
997       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
998       return 1;
999     }
1000   }
1001   if (!hasHlrOnArg)
1002   {
1003     di << "HLR:        " << aView->ComputedMode() << "\n";
1004     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1005     di << "HlrAlgo:    ";
1006     switch (aCtx->DefaultDrawer()->TypeOfHLR())
1007     {
1008       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
1009       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1010       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
1011     }
1012     anUpdateTool.Invalidate();
1013     return 0;
1014   }
1015
1016   Standard_Boolean toRecompute = Standard_False;
1017   if (aTypeOfHLR != Prs3d_TOH_NotSet
1018    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
1019   {
1020     toRecompute = Standard_True;
1021     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1022   }
1023   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1024   {
1025     toRecompute = Standard_True;
1026     if (toShowHidden)
1027     {
1028       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
1029     }
1030     else
1031     {
1032       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
1033     }
1034   }
1035
1036   // redisplay shapes
1037   if (aView->ComputedMode() && isHLROn && toRecompute)
1038   {
1039     AIS_ListOfInteractive aListOfShapes;
1040     aCtx->DisplayedObjects (aListOfShapes);
1041     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
1042     {
1043       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
1044       {
1045         aCtx->Redisplay (aShape, Standard_False);
1046       }
1047     }
1048   }
1049
1050   aView->SetComputedMode (isHLROn);
1051   return 0;
1052 }
1053
1054 //==============================================================================
1055 //function : VHLRType
1056 //purpose  : change type of using HLR algorithm
1057 //==============================================================================
1058
1059 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1060 {
1061   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1062   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1063   if (aView.IsNull())
1064   {
1065     std::cerr << "Error: No opened viewer!\n";
1066     return 1;
1067   }
1068
1069   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1070   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1071   AIS_ListOfInteractive aListOfShapes;
1072   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1073   {
1074     TCollection_AsciiString anArg (argv[anArgIter]);
1075     anArg.LowerCase();
1076     if (anUpdateTool.parseRedrawMode (anArg))
1077     {
1078       continue;
1079     }
1080     else if ((anArg == "-type"
1081            || anArg == "-algo"
1082            || anArg == "-algotype")
1083           && anArgIter + 1 < argc
1084           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1085     {
1086       ++anArgIter;
1087       continue;
1088     }
1089     // old syntax
1090     else if (aTypeOfHLR == Prs3d_TOH_NotSet
1091           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1092     {
1093       continue;
1094     }
1095     else
1096     {
1097       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1098       TCollection_AsciiString aName (argv[anArgIter]);
1099       if (!aMap.IsBound2 (aName))
1100       {
1101         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
1102         return 1;
1103       }
1104
1105       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1106       if (aShape.IsNull())
1107       {
1108         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
1109         return 1;
1110       }
1111       aListOfShapes.Append (aShape);
1112       continue;
1113     }
1114   }
1115   if (aTypeOfHLR == Prs3d_TOH_NotSet)
1116   {
1117     std::cout << "Syntax error: wrong number of arguments!\n";
1118     return 1;
1119   }
1120
1121   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1122   if (isGlobal)
1123   {
1124     aCtx->DisplayedObjects (aListOfShapes);
1125     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1126   }
1127
1128   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1129   {
1130     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1131     if (aShape.IsNull())
1132     {
1133       continue;
1134     }
1135
1136     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1137                             && aView->ComputedMode();
1138     if (!isGlobal
1139      || aShape->TypeOfHLR() != aTypeOfHLR)
1140     {
1141       aShape->SetTypeOfHLR (aTypeOfHLR);
1142     }
1143     if (toUpdateShape)
1144     {
1145       aCtx->Redisplay (aShape, Standard_False);
1146     }
1147   }
1148   return 0;
1149 }
1150
1151 //==============================================================================
1152 //function : FindViewIdByWindowHandle
1153 //purpose  : Find theView Id in the map of views by window handle
1154 //==============================================================================
1155 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1156 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1157 {
1158   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1159        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1160   {
1161     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1162     if (aWindowHandle == theWindowHandle)
1163       return anIter.Key1();
1164   }
1165   return TCollection_AsciiString("");
1166 }
1167 #endif
1168
1169 //==============================================================================
1170 //function : ActivateView
1171 //purpose  : Make the view active
1172 //==============================================================================
1173
1174 void ActivateView (const TCollection_AsciiString& theViewName)
1175 {
1176   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1177   if (!aView.IsNull())
1178   {
1179     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1180     if (!anAISContext.IsNull())
1181     {
1182       if (!ViewerTest::CurrentView().IsNull())
1183       {
1184         TCollection_AsciiString aTitle("3D View - ");
1185         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1186         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1187       }
1188
1189       ViewerTest::CurrentView (aView);
1190       ViewerTest::SetAISContext (anAISContext);
1191       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
1192       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1193 #if defined(_WIN32)
1194       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1195 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1196       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1197 #else
1198       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1199 #endif
1200       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1201       ViewerTest::CurrentView()->Redraw();
1202     }
1203   }
1204 }
1205
1206 //==============================================================================
1207 //function : RemoveView
1208 //purpose  :
1209 //==============================================================================
1210 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1211                              const Standard_Boolean  theToRemoveContext)
1212 {
1213   if (!ViewerTest_myViews.IsBound2 (theView))
1214   {
1215     return;
1216   }
1217
1218   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1219   RemoveView (aViewName, theToRemoveContext);
1220 }
1221
1222 //==============================================================================
1223 //function : RemoveView
1224 //purpose  : Close and remove view from display, clear maps if neccessary
1225 //==============================================================================
1226 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1227 {
1228   if (!ViewerTest_myViews.IsBound1(theViewName))
1229   {
1230     cout << "Wrong view name\n";
1231     return;
1232   }
1233
1234   // Activate another view if it's active now
1235   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1236   {
1237     if (ViewerTest_myViews.Extent() > 1)
1238     {
1239       TCollection_AsciiString aNewViewName;
1240       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1241            anIter.More(); anIter.Next())
1242       {
1243         if (anIter.Key1() != theViewName)
1244         {
1245           aNewViewName = anIter.Key1();
1246           break;
1247         }
1248       }
1249       ActivateView (aNewViewName);
1250     }
1251     else
1252     {
1253       Handle(V3d_View) anEmptyView;
1254 #if defined(_WIN32) || defined(__WIN32__)
1255       Handle(WNT_Window) anEmptyWindow;
1256 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1257       Handle(Cocoa_Window) anEmptyWindow;
1258 #else
1259       Handle(Xw_Window) anEmptyWindow;
1260 #endif
1261       VT_GetWindow() = anEmptyWindow;
1262       ViewerTest::CurrentView (anEmptyView);
1263       if (isContextRemoved)
1264       {
1265         Handle(AIS_InteractiveContext) anEmptyContext;
1266         ViewerTest::SetAISContext(anEmptyContext);
1267       }
1268     }
1269   }
1270
1271   // Delete view
1272   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1273   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1274
1275   // Remove view resources
1276   ViewerTest_myViews.UnBind1(theViewName);
1277   aView->Window()->Unmap();
1278   aView->Remove();
1279
1280 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1281   XFlush (GetDisplayConnection()->GetDisplay());
1282 #endif
1283
1284   // Keep context opened only if the closed view is last to avoid
1285   // unused empty contexts
1286   if (!aCurrentContext.IsNull())
1287   {
1288     // Check if there are more difined views in the viewer
1289     aCurrentContext->CurrentViewer()->InitDefinedViews();
1290     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1291     {
1292       // Remove driver if there is no viewers that use it
1293       Standard_Boolean isRemoveDriver = Standard_True;
1294       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1295           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1296       {
1297         if (aCurrentContext != anIter.Key2() &&
1298           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1299         {
1300           isRemoveDriver = Standard_False;
1301           break;
1302         }
1303       }
1304
1305       aCurrentContext->RemoveAll (Standard_False);
1306       if(isRemoveDriver)
1307       {
1308         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1309       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1310         #if TCL_MAJOR_VERSION  < 8
1311         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1312         #else
1313         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1314         #endif
1315       #endif
1316       }
1317
1318       ViewerTest_myContexts.UnBind2(aCurrentContext);
1319     }
1320   }
1321   cout << "3D View - " << theViewName << " was deleted.\n";
1322   if (Draw_ToExitOnCloseView)
1323   {
1324     Draw_Interprete ("exit");
1325   }
1326 }
1327
1328 //==============================================================================
1329 //function : VClose
1330 //purpose  : Remove the view defined by its name
1331 //==============================================================================
1332
1333 static int VClose (Draw_Interpretor& /*theDi*/,
1334                    Standard_Integer  theArgsNb,
1335                    const char**      theArgVec)
1336 {
1337   NCollection_List<TCollection_AsciiString> aViewList;
1338   if (theArgsNb > 1)
1339   {
1340     TCollection_AsciiString anArg (theArgVec[1]);
1341     anArg.UpperCase();
1342     if (anArg.IsEqual ("ALL")
1343      || anArg.IsEqual ("*"))
1344     {
1345       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1346            anIter.More(); anIter.Next())
1347       {
1348         aViewList.Append (anIter.Key1());
1349       }
1350       if (aViewList.IsEmpty())
1351       {
1352         std::cout << "No view to close\n";
1353         return 0;
1354       }
1355     }
1356     else
1357     {
1358       ViewerTest_Names aViewName (theArgVec[1]);
1359       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1360       {
1361         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1362         return 1;
1363       }
1364       aViewList.Append (aViewName.GetViewName());
1365     }
1366   }
1367   else
1368   {
1369     // close active view
1370     if (ViewerTest::CurrentView().IsNull())
1371     {
1372       std::cerr << "No active view!\n";
1373       return 1;
1374     }
1375     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1376   }
1377
1378   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1379   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1380        anIter.More(); anIter.Next())
1381   {
1382     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1383   }
1384
1385   return 0;
1386 }
1387
1388 //==============================================================================
1389 //function : VActivate
1390 //purpose  : Activate the view defined by its ID
1391 //==============================================================================
1392
1393 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1394 {
1395   if (theArgsNb > 2)
1396   {
1397     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1398     << "Usage: " << theArgVec[0] << " ViewID\n";
1399     return 1;
1400   }
1401   if(theArgsNb == 1)
1402   {
1403     theDi.Eval("vviewlist");
1404     return 0;
1405   }
1406
1407   TCollection_AsciiString aNameString(theArgVec[1]);
1408   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1409   {
1410     TCollection_AsciiString aTitle("3D View - ");
1411     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1412     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1413     Handle(V3d_View) anEmptyView;
1414 #if defined(_WIN32) || defined(__WIN32__)
1415     Handle(WNT_Window) anEmptyWindow;
1416 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1417     Handle(Cocoa_Window) anEmptyWindow;
1418 #else
1419     Handle(Xw_Window) anEmptyWindow;
1420 #endif
1421     VT_GetWindow() = anEmptyWindow;
1422     ViewerTest::CurrentView (anEmptyView);
1423     ViewerTest::ResetEventManager();
1424     theDi << theArgVec[0] << ": all views are inactive\n";
1425     return 0;
1426   }
1427
1428   ViewerTest_Names aViewNames(aNameString);
1429
1430   // Check if this view exists in the viewer with the driver
1431   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1432   {
1433     theDi << "Wrong view name\n";
1434     return 1;
1435   }
1436
1437   // Check if it is active already
1438   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1439   {
1440     theDi << theArgVec[0] << ": the view is active already\n";
1441     return 0;
1442   }
1443
1444   ActivateView (aViewNames.GetViewName());
1445   return 0;
1446 }
1447
1448 //==============================================================================
1449 //function : VViewList
1450 //purpose  : Print current list of views per viewer and graphic driver ID
1451 //           shared between viewers
1452 //==============================================================================
1453
1454 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1455 {
1456   if (theArgsNb > 2)
1457   {
1458     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1459           << "Usage: " << theArgVec[0] << " name";
1460     return 1;
1461   }
1462   if (ViewerTest_myContexts.Size() < 1)
1463     return 0;
1464
1465   Standard_Boolean isTreeView =
1466     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1467
1468   if (isTreeView)
1469   {
1470     theDi << theArgVec[0] <<":\n";
1471   }
1472
1473   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1474        aDriverIter.More(); aDriverIter.Next())
1475   {
1476     if (isTreeView)
1477       theDi << aDriverIter.Key1() << ":\n";
1478
1479     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1480       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1481     {
1482       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1483       {
1484         if (isTreeView)
1485         {
1486           TCollection_AsciiString aContextName(aContextIter.Key1());
1487           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1488         }
1489
1490         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1491              aViewIter.More(); aViewIter.Next())
1492         {
1493           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1494           {
1495             TCollection_AsciiString aViewName(aViewIter.Key1());
1496             if (isTreeView)
1497             {
1498               if (aViewIter.Value() == ViewerTest::CurrentView())
1499                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1500               else
1501                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1502             }
1503             else
1504             {
1505               theDi << aViewName << " ";
1506             }
1507           }
1508         }
1509       }
1510     }
1511   }
1512   return 0;
1513 }
1514
1515 //==============================================================================
1516 //function : VT_ProcessKeyPress
1517 //purpose  : Handle KeyPress event from a CString
1518 //==============================================================================
1519 void VT_ProcessKeyPress (const char* buf_ret)
1520 {
1521   //cout << "KeyPress" << endl;
1522   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1523   // Letter in alphabetic order
1524
1525   if (!strcasecmp (buf_ret, "A"))
1526   {
1527     // AXO
1528     aView->SetProj(V3d_XposYnegZpos);
1529   }
1530   else if (!strcasecmp (buf_ret, "D"))
1531   {
1532     // Reset
1533     aView->Reset();
1534   }
1535   else if (!strcasecmp (buf_ret, "F"))
1536   {
1537     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1538     {
1539       ViewerTest::GetAISContext()->FitSelected (aView);
1540     }
1541     else
1542     {
1543       // FitAll
1544       aView->FitAll();
1545     }
1546   }
1547   else if (!strcasecmp (buf_ret, "H"))
1548   {
1549     // HLR
1550     std::cout << "HLR" << std::endl;
1551     aView->SetComputedMode (!aView->ComputedMode());
1552     aView->Redraw();
1553   }
1554   else if (!strcasecmp (buf_ret, "P"))
1555   {
1556     // Type of HLR
1557     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1558     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1559       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1560     else
1561       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1562     if (aContext->NbSelected()==0)
1563     {
1564       AIS_ListOfInteractive aListOfShapes;
1565       aContext->DisplayedObjects(aListOfShapes);
1566       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1567         anIter.More(); anIter.Next())
1568       {
1569         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1570         if (aShape.IsNull())
1571           continue;
1572         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1573           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1574         else
1575           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1576         aContext->Redisplay (aShape, Standard_False);
1577       }
1578     }
1579     else
1580     {
1581       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1582       {
1583         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1584         if (aShape.IsNull())
1585           continue;
1586         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1587           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1588         else
1589           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1590         aContext->Redisplay (aShape, Standard_False);
1591       }
1592     }
1593
1594     aContext->UpdateCurrentViewer();
1595
1596   }
1597   else if (!strcasecmp (buf_ret, "S"))
1598   {
1599     std::cout << "setup Shaded display mode" << std::endl;
1600
1601     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1602     if(Ctx->NbSelected()==0)
1603       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1604     else{
1605       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1606         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1607       Ctx->UpdateCurrentViewer();
1608     }
1609   }
1610   else if (!strcasecmp (buf_ret, "U"))
1611   {
1612     // Unset display mode
1613     std::cout << "reset display mode to defaults" << std::endl;
1614
1615     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1616     if(Ctx->NbSelected()==0)
1617       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1618     else{
1619       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1620         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1621       Ctx->UpdateCurrentViewer();
1622     }
1623
1624   }
1625   else if (!strcasecmp (buf_ret, "T"))
1626   {
1627     // Top
1628     aView->SetProj(V3d_Zpos);
1629   }
1630   else if (!strcasecmp (buf_ret, "B"))
1631   {
1632     // Bottom
1633     aView->SetProj(V3d_Zneg);
1634   }
1635   else if (!strcasecmp (buf_ret, "L"))
1636   {
1637     // Left
1638     aView->SetProj(V3d_Xneg);
1639   }
1640   else if (!strcasecmp (buf_ret, "R"))
1641   {
1642     // Right
1643     aView->SetProj(V3d_Xpos);
1644   }
1645   else if (!strcasecmp (buf_ret, "W"))
1646   {
1647     std::cout << "setup WireFrame display mode" << std::endl;
1648     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1649     if(Ctx->NbSelected()==0)
1650       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1651     else{
1652       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1653         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1654       Ctx->UpdateCurrentViewer();
1655     }
1656   }
1657   else if (!strcasecmp (buf_ret, ","))
1658   {
1659     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1660   }
1661   else if (!strcasecmp (buf_ret, "."))
1662   {
1663     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1664   }
1665   else if (!strcasecmp (buf_ret, "/"))
1666   {
1667     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1668     if (aCamera->IsStereo())
1669     {
1670       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1671       aView->Redraw();
1672     }
1673   }
1674   else if (!strcasecmp (buf_ret, "*"))
1675   {
1676     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1677     if (aCamera->IsStereo())
1678     {
1679       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1680       aView->Redraw();
1681     }
1682   }
1683   else if (*buf_ret == THE_KEY_DELETE)
1684   {
1685     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1686     if (!aCtx.IsNull()
1687      && aCtx->NbSelected() > 0)
1688     {
1689       Draw_Interprete ("verase");
1690     }
1691   }
1692   else if (*buf_ret == THE_KEY_ESCAPE)
1693   {
1694     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1695     if (!aCtx.IsNull()
1696      && Draw_ToCloseViewOnEsc)
1697     {
1698       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
1699     }
1700   }
1701   else
1702   {
1703     // Number
1704     Standard_Integer Num = Draw::Atoi(buf_ret);
1705     if(Num>=0 && Num<=7)
1706       ViewerTest::StandardModeActivation(Num);
1707   }
1708 }
1709
1710 //==============================================================================
1711 //function : VT_ProcessExpose
1712 //purpose  : Redraw the View on an Expose Event
1713 //==============================================================================
1714 void VT_ProcessExpose()
1715 {
1716   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1717   if (!aView3d.IsNull())
1718   {
1719     aView3d->Redraw();
1720   }
1721 }
1722
1723 //==============================================================================
1724 //function : VT_ProcessConfigure
1725 //purpose  : Resize the View on an Configure Event
1726 //==============================================================================
1727 void VT_ProcessConfigure()
1728 {
1729   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1730   if (aView3d.IsNull())
1731   {
1732     return;
1733   }
1734
1735   aView3d->MustBeResized();
1736   aView3d->Update();
1737   aView3d->Redraw();
1738 }
1739
1740 //==============================================================================
1741 //function : VT_ProcessButton1Press
1742 //purpose  : Picking
1743 //==============================================================================
1744 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1745                                          const char**     theArgVec,
1746                                          Standard_Boolean theToPick,
1747                                          Standard_Boolean theIsShift)
1748 {
1749   if (TheIsAnimating)
1750   {
1751     TheIsAnimating = Standard_False;
1752     return Standard_False;
1753   }
1754
1755   if (theToPick)
1756   {
1757     Standard_Real X, Y, Z;
1758     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1759
1760     Draw::Set (theArgVec[1], X);
1761     Draw::Set (theArgVec[2], Y);
1762     Draw::Set (theArgVec[3], Z);
1763   }
1764
1765   if (theIsShift)
1766   {
1767     ViewerTest::CurrentEventManager()->ShiftSelect();
1768   }
1769   else
1770   {
1771     ViewerTest::CurrentEventManager()->Select();
1772   }
1773
1774   return Standard_False;
1775 }
1776
1777 //==============================================================================
1778 //function : VT_ProcessButton1Release
1779 //purpose  : End selecting
1780 //==============================================================================
1781 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1782 {
1783   if (IsDragged)
1784   {
1785     IsDragged = Standard_False;
1786     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1787     if (theIsShift)
1788     {
1789       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1790                        X_Motion, Y_Motion);
1791     }
1792     else
1793     {
1794       EM->Select (X_ButtonPress, Y_ButtonPress,
1795                   X_Motion, Y_Motion);
1796     }
1797   }
1798 }
1799
1800 //==============================================================================
1801 //function : VT_ProcessButton3Press
1802 //purpose  : Start Rotation
1803 //==============================================================================
1804 void VT_ProcessButton3Press()
1805 {
1806   Start_Rot = 1;
1807   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
1808   if (HasHlrOnBeforeRotation)
1809   {
1810     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1811   }
1812   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1813 }
1814
1815 //==============================================================================
1816 //function : VT_ProcessButton3Release
1817 //purpose  : End rotation
1818 //==============================================================================
1819 void VT_ProcessButton3Release()
1820 {
1821   if (Start_Rot)
1822   {
1823     Start_Rot = 0;
1824     if (HasHlrOnBeforeRotation)
1825     {
1826       HasHlrOnBeforeRotation = Standard_False;
1827       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1828       ViewerTest::CurrentView()->Redraw();
1829     }
1830   }
1831 }
1832
1833 //==============================================================================
1834 //function : ProcessControlButton1Motion
1835 //purpose  : Zoom
1836 //==============================================================================
1837
1838 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1839 static void ProcessControlButton1Motion()
1840 {
1841   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1842
1843   X_ButtonPress = X_Motion;
1844   Y_ButtonPress = Y_Motion;
1845 }
1846 #endif
1847
1848 //==============================================================================
1849 //function : VT_ProcessControlButton2Motion
1850 //purpose  : Panning
1851 //==============================================================================
1852 void VT_ProcessControlButton2Motion()
1853 {
1854   Standard_Integer aDx = X_Motion - X_ButtonPress;
1855   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1856
1857   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1858
1859   ViewerTest::CurrentView()->Pan (aDx, aDy);
1860
1861   X_ButtonPress = X_Motion;
1862   Y_ButtonPress = Y_Motion;
1863 }
1864
1865 //==============================================================================
1866 //function : VT_ProcessControlButton3Motion
1867 //purpose  : Rotation
1868 //==============================================================================
1869 void VT_ProcessControlButton3Motion()
1870 {
1871   if (Start_Rot)
1872   {
1873     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1874   }
1875 }
1876
1877 //==============================================================================
1878 //function : VT_ProcessMotion
1879 //purpose  :
1880 //==============================================================================
1881 void VT_ProcessMotion()
1882 {
1883   //pre-hilights detected objects at mouse position
1884
1885   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1886   EM->MoveTo(X_Motion, Y_Motion);
1887 }
1888
1889
1890 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1891 {
1892   Xpix = X_Motion;Ypix=Y_Motion;
1893 }
1894
1895 //==============================================================================
1896 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1897 //purpose  : Switches to an axonometric, top, left and other views
1898 //==============================================================================
1899
1900 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1901 {
1902   if ( ViewerTest::CurrentView().IsNull() )
1903   {
1904     di<<"Call vinit before this command, please\n";
1905     return 1;
1906   }
1907
1908   ViewerTest::CurrentView()->SetProj(ori);
1909   return 0;
1910 }
1911
1912 //==============================================================================
1913 //function : VAxo
1914 //purpose  : Switch to an Axonometric view
1915 //Draw arg : No args
1916 //==============================================================================
1917
1918 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1919 {
1920   return ViewProject(di, V3d_XposYnegZpos);
1921 }
1922
1923 //==============================================================================
1924 //function : VTop
1925 //purpose  : Switch to a Top View
1926 //Draw arg : No args
1927 //==============================================================================
1928
1929 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1930 {
1931   return ViewProject(di, V3d_Zpos);
1932 }
1933
1934 //==============================================================================
1935 //function : VBottom
1936 //purpose  : Switch to a Bottom View
1937 //Draw arg : No args
1938 //==============================================================================
1939
1940 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1941 {
1942   return ViewProject(di, V3d_Zneg);
1943 }
1944
1945 //==============================================================================
1946 //function : VLeft
1947 //purpose  : Switch to a Left View
1948 //Draw arg : No args
1949 //==============================================================================
1950
1951 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1952 {
1953   return ViewProject(di, V3d_Xneg);
1954 }
1955
1956 //==============================================================================
1957 //function : VRight
1958 //purpose  : Switch to a Right View
1959 //Draw arg : No args
1960 //==============================================================================
1961
1962 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1963 {
1964   return ViewProject(di, V3d_Xpos);
1965 }
1966
1967 //==============================================================================
1968 //function : VFront
1969 //purpose  : Switch to a Front View
1970 //Draw arg : No args
1971 //==============================================================================
1972
1973 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1974 {
1975   return ViewProject(di, V3d_Yneg);
1976 }
1977
1978 //==============================================================================
1979 //function : VBack
1980 //purpose  : Switch to a Back View
1981 //Draw arg : No args
1982 //==============================================================================
1983
1984 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1985 {
1986   return ViewProject(di, V3d_Ypos);
1987 }
1988
1989 //==============================================================================
1990 //function : VHelp
1991 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1992 //Draw arg : No args
1993 //==============================================================================
1994
1995 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1996 {
1997
1998   di << "Q : Quit the application\n";
1999
2000   di << "=========================\n";
2001   di << "F : FitAll\n";
2002   di << "T : TopView\n";
2003   di << "B : BottomView\n";
2004   di << "R : RightView\n";
2005   di << "L : LeftView\n";
2006   di << "A : AxonometricView\n";
2007   di << "D : ResetView\n";
2008
2009   di << "=========================\n";
2010   di << "S : Shading\n";
2011   di << "W : Wireframe\n";
2012   di << "H : HidelLineRemoval\n";
2013   di << "U : Unset display mode\n";
2014   di << "Delete : Remove selection from viewer\n";
2015
2016   di << "=========================\n";
2017   di << "Selection mode \n";
2018   di << "0 : Shape\n";
2019   di << "1 : Vertex\n";
2020   di << "2 : Edge\n";
2021   di << "3 : Wire\n";
2022   di << "4 : Face\n";
2023   di << "5 : Shell\n";
2024   di << "6 : Solid\n";
2025   di << "7 : Compound\n";
2026
2027   di << "=========================\n";
2028   di << "Z : Switch Z clipping On/Off\n";
2029   di << ", : Hilight next detected\n";
2030   di << ". : Hilight previous detected\n";
2031
2032   return 0;
2033 }
2034
2035 #ifdef _WIN32
2036
2037 static Standard_Boolean Ppick = 0;
2038 static Standard_Integer Pargc = 0;
2039 static const char**           Pargv = NULL;
2040
2041
2042 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
2043                                           UINT Msg,
2044                                           WPARAM wParam,
2045                                           LPARAM lParam )
2046 {
2047   if (!ViewerTest_myViews.IsEmpty()) {
2048
2049     WPARAM fwKeys = wParam;
2050
2051     switch( Msg ) {
2052     case WM_CLOSE:
2053        {
2054          // Delete view from map of views
2055          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
2056          return 0;
2057        }
2058        break;
2059     case WM_ACTIVATE:
2060       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
2061         || ViewerTest::CurrentView().IsNull())
2062       {
2063         // Activate inactive window
2064         if(GetWindowHandle(VT_GetWindow()) != hwnd)
2065         {
2066           ActivateView (FindViewIdByWindowHandle(hwnd));
2067         }
2068       }
2069       break;
2070
2071     case WM_LBUTTONUP:
2072       if (IsDragged && !DragFirst)
2073       {
2074         if (!GetActiveAISManipulator().IsNull())
2075         {
2076           GetActiveAISManipulator()->StopTransform();
2077           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2078         }
2079
2080         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2081         {
2082           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2083           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2084         }
2085
2086         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
2087       }
2088       IsDragged = Standard_False;
2089       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2090
2091     case WM_RBUTTONUP:
2092       if (IsDragged && !DragFirst)
2093       {
2094         if (!GetActiveAISManipulator().IsNull())
2095         {
2096           GetActiveAISManipulator()->StopTransform (Standard_False);
2097           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2098         }
2099         IsDragged = Standard_False;
2100       }
2101       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
2102
2103     case WM_LBUTTONDOWN:
2104       if (!GetActiveAISManipulator().IsNull())
2105       {
2106         IsDragged = ( fwKeys == MK_LBUTTON );
2107       }
2108       else
2109       {
2110         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
2111       }
2112
2113       if (IsDragged)
2114       {
2115         DragFirst = Standard_True;
2116         X_ButtonPress = LOWORD(lParam);
2117         Y_ButtonPress = HIWORD(lParam);
2118       }
2119       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2120
2121     case WM_MOUSEMOVE:
2122       if (IsDragged)
2123       {
2124         X_Motion = LOWORD (lParam);
2125         Y_Motion = HIWORD (lParam);
2126         if (!GetActiveAISManipulator().IsNull())
2127         {
2128           if (DragFirst)
2129           {
2130             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
2131           }
2132           else
2133           {
2134             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
2135             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
2136           }
2137         }
2138         else
2139         {
2140           bool toRedraw = false;
2141           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2142           {
2143             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2144             toRedraw = true;
2145           }
2146
2147           RECT aRect;
2148           if (GetClientRect (hwnd, &aRect))
2149           {
2150             int aHeight = aRect.bottom - aRect.top;
2151             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2152             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2153             toRedraw = true;
2154           }
2155           if (toRedraw)
2156           {
2157             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2158           }
2159         }
2160
2161         DragFirst = Standard_False;
2162       }
2163       else
2164         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2165       break;
2166
2167     default:
2168       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2169     }
2170     return 0;
2171   }
2172   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2173 }
2174
2175
2176 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2177                                        UINT Msg,
2178                                        WPARAM wParam,
2179                                        LPARAM lParam )
2180 {
2181   static int Up = 1;
2182   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2183   if (aView.IsNull())
2184   {
2185     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2186   }
2187
2188     PAINTSTRUCT    ps;
2189
2190     switch( Msg ) {
2191     case WM_PAINT:
2192       BeginPaint(hwnd, &ps);
2193       EndPaint(hwnd, &ps);
2194       VT_ProcessExpose();
2195       break;
2196
2197     case WM_SIZE:
2198       VT_ProcessConfigure();
2199       break;
2200     case WM_MOVE:
2201     case WM_MOVING:
2202     case WM_SIZING:
2203       switch (aView->RenderingParams().StereoMode)
2204       {
2205         case Graphic3d_StereoMode_RowInterlaced:
2206         case Graphic3d_StereoMode_ColumnInterlaced:
2207         case Graphic3d_StereoMode_ChessBoard:
2208           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2209           break;
2210         default:
2211           break;
2212       }
2213       break;
2214
2215     case WM_KEYDOWN:
2216       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2217       {
2218         char c[2];
2219         c[0] = (char) wParam;
2220         c[1] = '\0';
2221         if (wParam == VK_DELETE)
2222         {
2223           c[0] = THE_KEY_DELETE;
2224         }
2225         else if (wParam == VK_ESCAPE)
2226         {
2227           c[0] = THE_KEY_ESCAPE;
2228         }
2229         // comma
2230         else if (wParam == VK_OEM_COMMA)
2231         {
2232           c[0] = ',';
2233         }
2234         // dot
2235         else if (wParam == VK_OEM_PERIOD)
2236         {
2237           c[0] = '.';
2238         }
2239         else if (wParam == VK_DIVIDE)
2240         {
2241           c[0] = '/';
2242         }
2243         // dot
2244         else if (wParam == VK_MULTIPLY)
2245         {
2246           c[0] = '*';
2247         }
2248         VT_ProcessKeyPress (c);
2249       }
2250       break;
2251
2252     case WM_LBUTTONUP:
2253     case WM_MBUTTONUP:
2254     case WM_RBUTTONUP:
2255       Up = 1;
2256       VT_ProcessButton3Release();
2257       break;
2258
2259     case WM_LBUTTONDOWN:
2260     case WM_MBUTTONDOWN:
2261     case WM_RBUTTONDOWN:
2262       {
2263         WPARAM fwKeys = wParam;
2264
2265         Up = 0;
2266
2267         X_ButtonPress = LOWORD(lParam);
2268         Y_ButtonPress = HIWORD(lParam);
2269
2270         if (Msg == WM_LBUTTONDOWN)
2271         {
2272           if ((fwKeys & MK_CONTROL) != 0)
2273           {
2274             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2275           }
2276           else
2277           {
2278             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2279           }
2280         }
2281         else if (Msg == WM_RBUTTONDOWN)
2282         {
2283           // Start rotation
2284           VT_ProcessButton3Press();
2285         }
2286       }
2287       break;
2288
2289     case WM_MOUSEWHEEL:
2290     {
2291       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2292       if (wParam & MK_CONTROL)
2293       {
2294         if (aView->Camera()->IsStereo())
2295         {
2296           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2297           if (aFocus > 0.2
2298            && aFocus < 2.0)
2299           {
2300             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2301             aView->Redraw();
2302           }
2303         }
2304       }
2305       else
2306       {
2307         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2308       }
2309       break;
2310     }
2311
2312     case WM_MOUSEMOVE:
2313       {
2314         //cout << "\t WM_MOUSEMOVE" << endl;
2315         WPARAM fwKeys = wParam;
2316         X_Motion = LOWORD(lParam);
2317         Y_Motion = HIWORD(lParam);
2318
2319         if ( Up &&
2320           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2321           {
2322             Up = 0;
2323             X_ButtonPress = LOWORD(lParam);
2324             Y_ButtonPress = HIWORD(lParam);
2325
2326             if ((fwKeys & MK_RBUTTON) != 0) {
2327               // Start rotation
2328               VT_ProcessButton3Press();
2329             }
2330           }
2331
2332           if ((fwKeys & MK_CONTROL) != 0)
2333           {
2334             if ((fwKeys & MK_LBUTTON) != 0)
2335             {
2336               ProcessControlButton1Motion();
2337             }
2338             else if ((fwKeys & MK_MBUTTON) != 0
2339                  || ((fwKeys & MK_LBUTTON) != 0
2340                   && (fwKeys & MK_RBUTTON) != 0))
2341             {
2342               VT_ProcessControlButton2Motion();
2343             }
2344             else if ((fwKeys & MK_RBUTTON) != 0)
2345             {
2346               VT_ProcessControlButton3Motion();
2347             }
2348           }
2349           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2350           {
2351             VT_ProcessMotion();
2352           }
2353       }
2354       break;
2355
2356     default:
2357       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2358     }
2359     return 0L;
2360 }
2361
2362 //==============================================================================
2363 //function : ViewerMainLoop
2364 //purpose  : Get a Event on the view and dispatch it
2365 //==============================================================================
2366
2367
2368 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2369 {
2370   Ppick = (argc > 0)? 1 : 0;
2371   Pargc = argc;
2372   Pargv = argv;
2373
2374   if ( Ppick ) {
2375     MSG msg;
2376     msg.wParam = 1;
2377
2378     cout << "Start picking" << endl;
2379
2380     while ( Ppick == 1 ) {
2381       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2382       if (GetMessageW (&msg, NULL, 0, 0))
2383       {
2384         TranslateMessage (&msg);
2385         DispatchMessageW (&msg);
2386       }
2387     }
2388
2389     cout << "Picking done" << endl;
2390   }
2391
2392   return Ppick;
2393 }
2394
2395 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2396
2397 int min( int a, int b )
2398 {
2399   if( a<b )
2400     return a;
2401   else
2402     return b;
2403 }
2404
2405 int max( int a, int b )
2406 {
2407   if( a>b )
2408     return a;
2409   else
2410     return b;
2411 }
2412
2413 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2414
2415 {
2416   static XEvent aReport;
2417   Standard_Boolean pick = argc > 0;
2418   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2419   XNextEvent (aDisplay, &aReport);
2420
2421   // Handle event for the chosen display connection
2422   switch (aReport.type) {
2423       case ClientMessage:
2424         {
2425           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2426           {
2427             // Close the window
2428             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2429           }
2430         }
2431         return 0;
2432      case FocusIn:
2433       {
2434          // Activate inactive view
2435          Window aWindow = GetWindowHandle(VT_GetWindow());
2436          if(aWindow != aReport.xfocus.window)
2437          {
2438            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2439          }
2440       }
2441       break;
2442       case Expose:
2443         {
2444           VT_ProcessExpose();
2445         }
2446         break;
2447       case ConfigureNotify:
2448         {
2449           VT_ProcessConfigure();
2450         }
2451         break;
2452       case KeyPress:
2453         {
2454
2455           KeySym ks_ret ;
2456           char buf_ret[11] ;
2457           int ret_len ;
2458           XComposeStatus status_in_out;
2459
2460           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2461             (char *) buf_ret , 10 ,
2462             &ks_ret , &status_in_out ) ;
2463
2464
2465           buf_ret[ret_len] = '\0' ;
2466
2467           if (ret_len)
2468           {
2469             VT_ProcessKeyPress (buf_ret);
2470           }
2471         }
2472         break;
2473       case ButtonPress:
2474         {
2475           X_ButtonPress = aReport.xbutton.x;
2476           Y_ButtonPress = aReport.xbutton.y;
2477
2478           if (aReport.xbutton.button == Button1)
2479           {
2480             if (aReport.xbutton.state & ControlMask)
2481             {
2482               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2483             }
2484             else
2485             {
2486               IsDragged = Standard_True;
2487               DragFirst = Standard_True;
2488             }
2489           }
2490           else if (aReport.xbutton.button == Button3)
2491           {
2492             // Start rotation
2493             VT_ProcessButton3Press();
2494           }
2495         }
2496         break;
2497       case ButtonRelease:
2498         {
2499           if( IsDragged )
2500           {
2501             if( !DragFirst )
2502             {
2503               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2504               {
2505                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2506                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2507               }
2508             }
2509
2510             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2511             if( aContext.IsNull() )
2512             {
2513               cout << "The context is null. Please use vinit before createmesh" << endl;
2514               return 0;
2515             }
2516
2517             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2518             if( aReport.xbutton.button==1 )
2519               if( DragFirst )
2520                 if( ShiftPressed )
2521                 {
2522                   aContext->ShiftSelect (Standard_True);
2523                 }
2524                 else
2525                 {
2526                   aContext->Select (Standard_True);
2527                 }
2528               else
2529                 if( ShiftPressed )
2530                 {
2531                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2532                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2533                                         ViewerTest::CurrentView(), Standard_True);
2534                 }
2535                 else
2536                 {
2537                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2538                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2539                                    ViewerTest::CurrentView(), Standard_True);
2540                 }
2541             else
2542               VT_ProcessButton3Release();
2543
2544             IsDragged = Standard_False;
2545           }
2546           else
2547             VT_ProcessButton3Release();
2548         }
2549         break;
2550       case MotionNotify:
2551         {
2552           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2553           {
2554             break;
2555           }
2556           if( IsDragged )
2557           {
2558             if( !DragFirst )
2559             {
2560               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2561               {
2562                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2563               }
2564             }
2565
2566             X_Motion = aReport.xmotion.x;
2567             Y_Motion = aReport.xmotion.y;
2568             DragFirst = Standard_False;
2569
2570             Window aWindow = GetWindowHandle(VT_GetWindow());
2571             Window aRoot;
2572             int anX, anY;
2573             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2574             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2575             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2576             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2577             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2578           }
2579           else
2580           {
2581             X_Motion = aReport.xmotion.x;
2582             Y_Motion = aReport.xmotion.y;
2583
2584             // remove all the ButtonMotionMaskr
2585             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2586
2587             if ( aReport.xmotion.state & ControlMask ) {
2588               if ( aReport.xmotion.state & Button1Mask ) {
2589                 ProcessControlButton1Motion();
2590               }
2591               else if ( aReport.xmotion.state & Button2Mask ) {
2592                 VT_ProcessControlButton2Motion();
2593               }
2594               else if ( aReport.xmotion.state & Button3Mask ) {
2595                 VT_ProcessControlButton3Motion();
2596               }
2597             }
2598             else
2599             {
2600               VT_ProcessMotion();
2601             }
2602           }
2603         }
2604         break;
2605 }
2606 return pick;
2607 }
2608
2609 //==============================================================================
2610 //function : VProcessEvents
2611 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2612 //       event in the Viewer window
2613 //==============================================================================
2614
2615 static void VProcessEvents(ClientData,int)
2616 {
2617   NCollection_Vector<int> anEventNumbers;
2618   // Get number of messages from every display
2619   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2620        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2621   {
2622     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2623   }
2624     // Handle events for every display
2625   int anEventIter = 0;
2626   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2627        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2628   {
2629     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2630          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2631     {
2632       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2633       int anEventResult = ViewerMainLoop( 0, NULL);
2634       // If window is closed or context was not found finish current event processing loop
2635       if (!anEventResult)
2636         return;
2637     }
2638   }
2639
2640   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2641
2642 }
2643 #endif
2644
2645 //==============================================================================
2646 //function : OSWindowSetup
2647 //purpose  : Setup for the X11 window to be able to cath the event
2648 //==============================================================================
2649
2650
2651 static void OSWindowSetup()
2652 {
2653 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2654   // X11
2655
2656   Window  window   = VT_GetWindow()->XWindow();
2657   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2658   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2659   XSynchronize(aDisplay, 1);
2660
2661   // X11 : For keyboard on SUN
2662   XWMHints wmhints;
2663   wmhints.flags = InputHint;
2664   wmhints.input = 1;
2665
2666   XSetWMHints( aDisplay, window, &wmhints);
2667
2668   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2669     ButtonPressMask | ButtonReleaseMask |
2670     StructureNotifyMask |
2671     PointerMotionMask |
2672     Button1MotionMask | Button2MotionMask |
2673     Button3MotionMask | FocusChangeMask
2674     );
2675   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2676   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2677
2678   XSynchronize(aDisplay, 0);
2679
2680 #else
2681   // _WIN32
2682 #endif
2683
2684 }
2685
2686 //==============================================================================
2687 //function : VFit
2688 //purpose  :
2689 //==============================================================================
2690
2691 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2692 {
2693   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2694   if (aView.IsNull())
2695   {
2696     std::cout << "Error: no active viewer!\n";
2697     return 1;
2698   }
2699
2700   Standard_Boolean toFit = Standard_True;
2701   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2702   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2703   {
2704     TCollection_AsciiString anArg (theArgv[anArgIter]);
2705     anArg.LowerCase();
2706     if (anUpdateTool.parseRedrawMode (anArg))
2707     {
2708       continue;
2709     }
2710     else if (anArg == "-selected")
2711     {
2712       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2713       toFit = Standard_False;
2714     }
2715     else
2716     {
2717       std::cout << "Syntax error at '" << anArg << "'\n";
2718     }
2719   }
2720
2721   if (toFit)
2722   {
2723     aView->FitAll (0.01, Standard_False);
2724   }
2725   return 0;
2726 }
2727
2728 //=======================================================================
2729 //function : VFitArea
2730 //purpose  : Fit view to show area located between two points
2731 //         : given in world 2D or 3D coordinates.
2732 //=======================================================================
2733 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2734 {
2735   Handle(V3d_View) aView = ViewerTest::CurrentView();
2736   if (aView.IsNull())
2737   {
2738     std::cerr << theArgVec[0] << "Error: No active view.\n";
2739     return 1;
2740   }
2741
2742   // Parse arguments.
2743   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2744   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2745
2746   if (theArgNb == 5)
2747   {
2748     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2749     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2750     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2751     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2752   }
2753   else if (theArgNb == 7)
2754   {
2755     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2756     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2757     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2758     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2759     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2760     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2761   }
2762   else
2763   {
2764     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2765     theDI.PrintHelp(theArgVec[0]);
2766     return 1;
2767   }
2768
2769   // Convert model coordinates to view space
2770   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2771   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2772   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2773
2774   // Determine fit area
2775   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2776   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2777
2778   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2779
2780   if (aDiagonal < Precision::Confusion())
2781   {
2782     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2783     return 1;
2784   }
2785
2786   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2787   return 0;
2788 }
2789
2790 //==============================================================================
2791 //function : VZFit
2792 //purpose  : ZFitall, no DRAW arguments
2793 //Draw arg : No args
2794 //==============================================================================
2795 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2796 {
2797   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2798
2799   if (aCurrentView.IsNull())
2800   {
2801     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2802     return 1;
2803   }
2804
2805   if (theArgsNb == 1)
2806   {
2807     aCurrentView->ZFitAll();
2808     aCurrentView->Redraw();
2809     return 0;
2810   }
2811
2812   Standard_Real aScale = 1.0;
2813
2814   if (theArgsNb >= 2)
2815   {
2816     aScale = Draw::Atoi (theArgVec[1]);
2817   }
2818
2819   aCurrentView->ZFitAll (aScale);
2820   aCurrentView->Redraw();
2821
2822   return 0;
2823 }
2824
2825 //==============================================================================
2826 //function : VRepaint
2827 //purpose  :
2828 //==============================================================================
2829 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2830 {
2831   Handle(V3d_View) aView = ViewerTest::CurrentView();
2832   if (aView.IsNull())
2833   {
2834     std::cout << "Error: no active viewer!\n";
2835     return 1;
2836   }
2837
2838   Standard_Boolean isImmediateUpdate = Standard_False;
2839   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2840   {
2841     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2842     anArg.LowerCase();
2843     if (anArg == "-immediate")
2844     {
2845       isImmediateUpdate = Standard_True;
2846       if (anArgIter + 1 < theArgNb
2847        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2848       {
2849         ++anArgIter;
2850       }
2851     }
2852     else
2853     {
2854       std::cout << "Syntax error at '" << anArg << "'\n";
2855     }
2856   }
2857
2858   if (isImmediateUpdate)
2859   {
2860     aView->RedrawImmediate();
2861   }
2862   else
2863   {
2864     aView->Redraw();
2865   }
2866   return 0;
2867 }
2868
2869 //==============================================================================
2870 //function : VClear
2871 //purpose  : Remove all the object from the viewer
2872 //Draw arg : No args
2873 //==============================================================================
2874
2875 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2876 {
2877   Handle(V3d_View) V = ViewerTest::CurrentView();
2878   if(!V.IsNull())
2879     ViewerTest::Clear();
2880   return 0;
2881 }
2882
2883 //==============================================================================
2884 //function : VPick
2885 //purpose  :
2886 //==============================================================================
2887
2888 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2889 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2890
2891 if ( argc < 4 ) {
2892   di << argv[0] << "Invalid number of arguments\n";
2893   return 1;
2894 }
2895
2896 while (ViewerMainLoop( argc, argv)) {
2897 }
2898
2899 return 0;
2900 }
2901
2902 //==============================================================================
2903 //function : VSetBg
2904 //purpose  : Load image as background
2905 //==============================================================================
2906
2907 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2908 {
2909   if (argc < 2 || argc > 3)
2910   {
2911     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2912     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2913     return 1;
2914   }
2915
2916   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2917   if(AISContext.IsNull())
2918   {
2919     di << "use 'vinit' command before " << argv[0] << "\n";
2920     return 1;
2921   }
2922
2923   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2924   if (argc == 3)
2925   {
2926     const char* szType = argv[2];
2927     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2928     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2929     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2930     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2931     else
2932     {
2933       di << "Wrong fill type : " << szType << "\n";
2934       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2935       return 1;
2936     }
2937   }
2938
2939   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2940   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2941
2942   return 0;
2943 }
2944
2945 //==============================================================================
2946 //function : VSetBgMode
2947 //purpose  : Change background image fill type
2948 //==============================================================================
2949
2950 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2951 {
2952   if (argc != 2)
2953   {
2954     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2955     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2956     return 1;
2957   }
2958
2959   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2960   if(AISContext.IsNull())
2961   {
2962     di << "use 'vinit' command before " << argv[0] << "\n";
2963     return 1;
2964   }
2965   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2966   const char* szType = argv[1];
2967   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2968   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2969   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2970   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2971   else
2972   {
2973     di << "Wrong fill type : " << szType << "\n";
2974     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2975     return 1;
2976   }
2977   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2978   V3dView->SetBgImageStyle(aFillType, Standard_True);
2979   return 0;
2980 }
2981
2982 //==============================================================================
2983 //function : VSetGradientBg
2984 //purpose  : Mount gradient background
2985 //==============================================================================
2986 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2987 {
2988   if (argc != 8 )
2989   {
2990     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2991     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2992     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2993     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2994     return 1;
2995   }
2996
2997   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2998   if(AISContext.IsNull())
2999   {
3000     di << "use 'vinit' command before " << argv[0] << "\n";
3001     return 1;
3002   }
3003   if (argc == 8)
3004   {
3005
3006     Standard_Real R1 = Draw::Atof(argv[1])/255.;
3007     Standard_Real G1 = Draw::Atof(argv[2])/255.;
3008     Standard_Real B1 = Draw::Atof(argv[3])/255.;
3009     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
3010
3011     Standard_Real R2 = Draw::Atof(argv[4])/255.;
3012     Standard_Real G2 = Draw::Atof(argv[5])/255.;
3013     Standard_Real B2 = Draw::Atof(argv[6])/255.;
3014
3015     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
3016     int aType = Draw::Atoi(argv[7]);
3017     if( aType < 0 || aType > 8 )
3018     {
3019       di << "Wrong fill type \n";
3020       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3021       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3022       return 1;
3023     }
3024
3025     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3026
3027     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3028     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
3029   }
3030
3031   return 0;
3032 }
3033
3034 //==============================================================================
3035 //function : VSetGradientBgMode
3036 //purpose  : Change gradient background fill style
3037 //==============================================================================
3038 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3039 {
3040   if (argc != 2 )
3041   {
3042     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
3043     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3044     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3045     return 1;
3046   }
3047
3048   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3049   if(AISContext.IsNull())
3050   {
3051     di << "use 'vinit' command before " << argv[0] << "\n";
3052     return 1;
3053   }
3054   if (argc == 2)
3055   {
3056     int aType = Draw::Atoi(argv[1]);
3057     if( aType < 0 || aType > 8 )
3058     {
3059       di << "Wrong fill type \n";
3060       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3061       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3062       return 1;
3063     }
3064
3065     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3066
3067     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3068     V3dView->SetBgGradientStyle( aMethod, 1 );
3069   }
3070
3071   return 0;
3072 }
3073
3074 //==============================================================================
3075 //function : VSetColorBg
3076 //purpose  : Set color background
3077 //==============================================================================
3078 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3079 {
3080   if (argc != 4 )
3081   {
3082     di << "Usage : " << argv[0] << " R G B : Set color background\n";
3083     di << "R,G,B = [0..255]\n";
3084     return 1;
3085   }
3086
3087   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3088   if(AISContext.IsNull())
3089   {
3090     di << "use 'vinit' command before " << argv[0] << "\n";
3091     return 1;
3092   }
3093   if (argc == 4)
3094   {
3095
3096     Standard_Real R = Draw::Atof(argv[1])/255.;
3097     Standard_Real G = Draw::Atof(argv[2])/255.;
3098     Standard_Real B = Draw::Atof(argv[3])/255.;
3099     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
3100
3101     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3102     V3dView->SetBackgroundColor( aColor );
3103     V3dView->Update();
3104   }
3105
3106   return 0;
3107 }
3108
3109 //==============================================================================
3110 //function : VSetDefaultBg
3111 //purpose  : Set default viewer background fill color
3112 //==============================================================================
3113 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3114 {
3115   if (theArgNb != 4
3116    && theArgNb != 8)
3117   {
3118     std::cout << "Error: wrong syntax! See usage:\n";
3119     theDI.PrintHelp (theArgVec[0]);
3120     return 1;
3121   }
3122
3123   ViewerTest_DefaultBackground.FillMethod =
3124     theArgNb == 4 ? Aspect_GFM_NONE
3125                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
3126
3127   if (theArgNb == 4)
3128   {
3129     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
3130     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
3131     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
3132     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
3133   }
3134   else
3135   {
3136     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
3137     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
3138     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
3139     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
3140
3141     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
3142     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
3143     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
3144     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
3145   }
3146
3147   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
3148        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
3149   {
3150     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
3151     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
3152     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
3153                                          ViewerTest_DefaultBackground.GradientColor2,
3154                                          ViewerTest_DefaultBackground.FillMethod);
3155   }
3156
3157   return 0;
3158 }
3159
3160 //==============================================================================
3161 //function : VScale
3162 //purpose  : View Scaling
3163 //==============================================================================
3164
3165 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3166 {
3167   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3168   if ( V3dView.IsNull() ) return 1;
3169
3170   if ( argc != 4 ) {
3171     di << argv[0] << "Invalid number of arguments\n";
3172     return 1;
3173   }
3174   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3175   return 0;
3176 }
3177 //==============================================================================
3178 //function : VZBuffTrihedron
3179 //purpose  :
3180 //==============================================================================
3181
3182 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3183                             Standard_Integer  theArgNb,
3184                             const char**      theArgVec)
3185 {
3186   Handle(V3d_View) aView = ViewerTest::CurrentView();
3187   if (aView.IsNull())
3188   {
3189     std::cout << "Error: no active viewer!\n";
3190     return 1;
3191   }
3192
3193   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3194
3195   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3196   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3197   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3198   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3199   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3200   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3201   Standard_Real                 aScale        = 0.1;
3202   Standard_Real                 aSizeRatio    = 0.8;
3203   Standard_Real                 anArrowDiam   = 0.05;
3204   Standard_Integer              aNbFacets     = 12;
3205   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3206   {
3207     Standard_CString        anArg = theArgVec[anArgIter];
3208     TCollection_AsciiString aFlag (anArg);
3209     aFlag.LowerCase();
3210     if (anUpdateTool.parseRedrawMode (aFlag))
3211     {
3212       continue;
3213     }
3214     else if (aFlag == "-on")
3215     {
3216       continue;
3217     }
3218     else if (aFlag == "-off")
3219     {
3220       aView->TriedronErase();
3221       return 0;
3222     }
3223     else if (aFlag == "-pos"
3224           || aFlag == "-position"
3225           || aFlag == "-corner")
3226     {
3227       if (++anArgIter >= theArgNb)
3228       {
3229         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3230         return 1;
3231       }
3232
3233       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3234       aPosName.LowerCase();
3235       if (aPosName == "center")
3236       {
3237         aPosition = Aspect_TOTP_CENTER;
3238       }
3239       else if (aPosName == "left_lower"
3240             || aPosName == "lower_left"
3241             || aPosName == "leftlower"
3242             || aPosName == "lowerleft")
3243       {
3244         aPosition = Aspect_TOTP_LEFT_LOWER;
3245       }
3246       else if (aPosName == "left_upper"
3247             || aPosName == "upper_left"
3248             || aPosName == "leftupper"
3249             || aPosName == "upperleft")
3250       {
3251         aPosition = Aspect_TOTP_LEFT_UPPER;
3252       }
3253       else if (aPosName == "right_lower"
3254             || aPosName == "lower_right"
3255             || aPosName == "rightlower"
3256             || aPosName == "lowerright")
3257       {
3258         aPosition = Aspect_TOTP_RIGHT_LOWER;
3259       }
3260       else if (aPosName == "right_upper"
3261             || aPosName == "upper_right"
3262             || aPosName == "rightupper"
3263             || aPosName == "upperright")
3264       {
3265         aPosition = Aspect_TOTP_RIGHT_UPPER;
3266       }
3267       else
3268       {
3269         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3270         return 1;
3271       }
3272     }
3273     else if (aFlag == "-type")
3274     {
3275       if (++anArgIter >= theArgNb)
3276       {
3277         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3278         return 1;
3279       }
3280
3281       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3282       aTypeName.LowerCase();
3283       if (aTypeName == "wireframe"
3284        || aTypeName == "wire")
3285       {
3286         aVisType = V3d_WIREFRAME;
3287       }
3288       else if (aTypeName == "zbuffer"
3289             || aTypeName == "shaded")
3290       {
3291         aVisType = V3d_ZBUFFER;
3292       }
3293       else
3294       {
3295         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3296       }
3297     }
3298     else if (aFlag == "-scale")
3299     {
3300       if (++anArgIter >= theArgNb)
3301       {
3302         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3303         return 1;
3304       }
3305
3306       aScale = Draw::Atof (theArgVec[anArgIter]);
3307     }
3308     else if (aFlag == "-size"
3309           || aFlag == "-sizeratio")
3310     {
3311       if (++anArgIter >= theArgNb)
3312       {
3313         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3314         return 1;
3315       }
3316
3317       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3318     }
3319     else if (aFlag == "-arrowdiam"
3320           || aFlag == "-arrowdiameter")
3321     {
3322       if (++anArgIter >= theArgNb)
3323       {
3324         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3325         return 1;
3326       }
3327
3328       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3329     }
3330     else if (aFlag == "-nbfacets")
3331     {
3332       if (++anArgIter >= theArgNb)
3333       {
3334         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3335         return 1;
3336       }
3337
3338       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3339     }
3340     else if (aFlag == "-colorlabel"
3341           || aFlag == "-colorlabels")
3342     {
3343       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3344                                                            theArgVec + anArgIter + 1,
3345                                                            aLabelsColor);
3346       if (aNbParsed == 0)
3347       {
3348         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3349         return 1;
3350       }
3351       anArgIter += aNbParsed;
3352     }
3353     else if (aFlag == "-colorarrowx")
3354     {
3355       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3356                                                            theArgVec + anArgIter + 1,
3357                                                            anArrowColorX);
3358       if (aNbParsed == 0)
3359       {
3360         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3361         return 1;
3362       }
3363       anArgIter += aNbParsed;
3364     }
3365     else if (aFlag == "-colorarrowy")
3366     {
3367       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3368                                                            theArgVec + anArgIter + 1,
3369                                                            anArrowColorY);
3370       if (aNbParsed == 0)
3371       {
3372         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3373         return 1;
3374       }
3375       anArgIter += aNbParsed;
3376     }
3377     else if (aFlag == "-colorarrowz")
3378     {
3379       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3380                                                            theArgVec + anArgIter + 1,
3381                                                            anArrowColorZ);
3382       if (aNbParsed == 0)
3383       {
3384         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3385         return 1;
3386       }
3387       anArgIter += aNbParsed;
3388     }
3389     else
3390     {
3391       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3392       return 1;
3393     }
3394   }
3395
3396   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3397                                aSizeRatio, anArrowDiam, aNbFacets);
3398   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3399   aView->ZFitAll();
3400   return 0;
3401 }
3402
3403 //==============================================================================
3404 //function : VRotate
3405 //purpose  : Camera Rotating
3406 //==============================================================================
3407
3408 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3409 {
3410   Handle(V3d_View) aView = ViewerTest::CurrentView();
3411   if (aView.IsNull())
3412   {
3413     std::cout << "No active view!\n";
3414     return 1;
3415   }
3416
3417   Standard_Boolean hasFlags = Standard_False;
3418   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3419   {
3420     Standard_CString        anArg (theArgVec[anArgIter]);
3421     TCollection_AsciiString aFlag (anArg);
3422     aFlag.LowerCase();
3423     if (aFlag == "-mousestart"
3424      || aFlag == "-mousefrom")
3425     {
3426       hasFlags = Standard_True;
3427       if (anArgIter + 2 >= theArgNb)
3428       {
3429         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3430         return 1;
3431       }
3432
3433       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3434       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3435       aView->StartRotation (anX, anY);
3436     }
3437     else if (aFlag == "-mousemove")
3438     {
3439       hasFlags = Standard_True;
3440       if (anArgIter + 2 >= theArgNb)
3441       {
3442         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3443         return 1;
3444       }
3445
3446       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3447       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3448       aView->Rotation (anX, anY);
3449     }
3450     else if (theArgNb != 4
3451           && theArgNb != 7)
3452     {
3453       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3454       return 1;
3455     }
3456   }
3457
3458   if (hasFlags)
3459   {
3460     return 0;
3461   }
3462   else if (theArgNb == 4)
3463   {
3464     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3465     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3466     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3467     aView->Rotate (anAX, anAY, anAZ);
3468     return 0;
3469   }
3470   else if (theArgNb == 7)
3471   {
3472     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3473     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3474     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3475
3476     Standard_Real anX = Draw::Atof (theArgVec[4]);
3477     Standard_Real anY = Draw::Atof (theArgVec[5]);
3478     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3479
3480     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3481     return 0;
3482   }
3483
3484   std::cout << "Error: Invalid number of arguments\n";
3485   return 1;
3486 }
3487
3488 //==============================================================================
3489 //function : VZoom
3490 //purpose  : View zoom in / out (relative to current zoom)
3491 //==============================================================================
3492
3493 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3494   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3495   if ( V3dView.IsNull() ) {
3496     return 1;
3497   }
3498
3499   if ( argc == 2 ) {
3500     Standard_Real coef = Draw::Atof(argv[1]);
3501     if ( coef <= 0.0 ) {
3502       di << argv[1] << "Invalid value\n";
3503       return 1;
3504     }
3505     V3dView->SetZoom( Draw::Atof(argv[1]) );
3506     return 0;
3507   } else {
3508     di << argv[0] << " Invalid number of arguments\n";
3509     return 1;
3510   }
3511 }
3512
3513 //==============================================================================
3514 //function : VPan
3515 //purpose  : View panning (in pixels)
3516 //==============================================================================
3517
3518 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3519   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3520   if ( V3dView.IsNull() ) return 1;
3521
3522   if ( argc == 3 ) {
3523     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3524     return 0;
3525   } else {
3526     di << argv[0] << " Invalid number of arguments\n";
3527     return 1;
3528   }
3529 }
3530
3531 //==============================================================================
3532 //function : VPlace
3533 //purpose  : Place the point (in pixels) at the center of the window
3534 //==============================================================================
3535 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3536 {
3537   Handle(V3d_View) aView = ViewerTest::CurrentView();
3538   if (aView.IsNull())
3539   {
3540     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3541     return 1;
3542   }
3543
3544   if (theArgNb != 3)
3545   {
3546     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3547     return 1;
3548   }
3549
3550   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3551
3552   return 0;
3553 }
3554
3555 //==============================================================================
3556 //function : VExport
3557 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3558 //==============================================================================
3559
3560 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3561 {
3562   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3563   if (V3dView.IsNull())
3564     return 1;
3565
3566   if (argc == 1)
3567   {
3568     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3569     return 1;
3570   }
3571
3572   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3573   TCollection_AsciiString aFormatStr;
3574
3575   TCollection_AsciiString aFileName (argv[1]);
3576   Standard_Integer aLen = aFileName.Length();
3577
3578   if (argc > 2)
3579   {
3580     aFormatStr = TCollection_AsciiString (argv[2]);
3581   }
3582   else if (aLen >= 4)
3583   {
3584     if (aFileName.Value (aLen - 2) == '.')
3585     {
3586       aFormatStr = aFileName.ToCString() + aLen - 2;
3587     }
3588     else if (aFileName.Value (aLen - 3) == '.')
3589     {
3590       aFormatStr = aFileName.ToCString() + aLen - 3;
3591     }
3592     else
3593     {
3594       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3595       return 1;
3596     }
3597   }
3598   else
3599   {
3600     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3601     return 1;
3602   }
3603
3604   aFormatStr.UpperCase();
3605   if (aFormatStr == "PS")
3606     anExpFormat = Graphic3d_EF_PostScript;
3607   else if (aFormatStr == "EPS")
3608     anExpFormat = Graphic3d_EF_EnhPostScript;
3609   else if (aFormatStr == "TEX")
3610     anExpFormat = Graphic3d_EF_TEX;
3611   else if (aFormatStr == "PDF")
3612     anExpFormat = Graphic3d_EF_PDF;
3613   else if (aFormatStr == "SVG")
3614     anExpFormat = Graphic3d_EF_SVG;
3615   else if (aFormatStr == "PGF")
3616     anExpFormat = Graphic3d_EF_PGF;
3617   else if (aFormatStr == "EMF")
3618     anExpFormat = Graphic3d_EF_EMF;
3619   else
3620   {
3621     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3622     return 1;
3623   }
3624
3625   Standard_DISABLE_DEPRECATION_WARNINGS
3626   try
3627   {
3628     if (!V3dView->Export (argv[1], anExpFormat))
3629     {
3630       di << "Error: export of image to " << aFormatStr << " failed!\n";
3631     }
3632   }
3633   catch (Standard_Failure const& anException)
3634   {
3635     di << "Error: export of image to " << aFormatStr << " failed";
3636     di << " (exception: " << anException.GetMessageString() << ")";
3637   }
3638   Standard_ENABLE_DEPRECATION_WARNINGS
3639   return 0;
3640 }
3641
3642 static int VColorScale (Draw_Interpretor& theDI,
3643                         Standard_Integer  theArgNb,
3644                         const char**      theArgVec)
3645 {
3646   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3647   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3648   if (aContext.IsNull())
3649   {
3650     std::cout << "Error: no active view!\n";
3651     return 1;
3652   }
3653   if (theArgNb <= 1)
3654   {
3655     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3656     return 1;
3657   }
3658
3659   Handle(AIS_ColorScale) aColorScale;
3660   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3661   {
3662     // find existing object
3663     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3664     if (aColorScale.IsNull())
3665     {
3666       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3667       return 1;
3668     }
3669   }
3670
3671   if (theArgNb <= 2)
3672   {
3673     if (aColorScale.IsNull())
3674     {
3675       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3676       return 1;
3677     }
3678
3679     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3680           << "Min range: "            << aColorScale->GetMin() << "\n"
3681           << "Max range: "            << aColorScale->GetMax() << "\n"
3682           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3683           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3684           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3685           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3686           << "Label position: ";
3687     switch (aColorScale->GetLabelPosition())
3688     {
3689       case Aspect_TOCSP_NONE:
3690         theDI << "None\n";
3691         break;
3692       case Aspect_TOCSP_LEFT:
3693         theDI << "Left\n";
3694         break;
3695       case Aspect_TOCSP_RIGHT:
3696         theDI << "Right\n";
3697         break;
3698       case Aspect_TOCSP_CENTER:
3699         theDI << "Center\n";
3700         break;
3701     }
3702     return 0;
3703   }
3704
3705   if (aColorScale.IsNull())
3706   {
3707     aColorScale = new AIS_ColorScale();
3708     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3709     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3710   }
3711
3712   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3713   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3714   {
3715     Standard_CString        anArg = theArgVec[anArgIter];
3716     TCollection_AsciiString aFlag (anArg);
3717     aFlag.LowerCase();
3718     if (anUpdateTool.parseRedrawMode (aFlag))
3719     {
3720       continue;
3721     }
3722     else if (aFlag == "-range")
3723     {
3724       if (anArgIter + 3 >= theArgNb)
3725       {
3726         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3727         return 1;
3728       }
3729
3730       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3731       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3732       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3733       if (!aRangeMin.IsRealValue()
3734        || !aRangeMax.IsRealValue())
3735       {
3736         std::cout << "Error: the range values should be real!\n";
3737         return 1;
3738       }
3739       else if (!aNbIntervals.IsIntegerValue())
3740       {
3741         std::cout << "Error: the number of intervals should be integer!\n";
3742         return 1;
3743       }
3744
3745       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3746       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3747     }
3748     else if (aFlag == "-font")
3749     {
3750       if (anArgIter + 1 >= theArgNb)
3751       {
3752         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3753         return 1;
3754       }
3755       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3756       if (!aFontArg.IsIntegerValue())
3757       {
3758         std::cout << "Error: HeightFont value should be integer!\n";
3759         return 1;
3760       }
3761
3762       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3763       anArgIter += 1;
3764     }
3765     else if (aFlag == "-textpos")
3766     {
3767       if (anArgIter + 1 >= theArgNb)
3768       {
3769         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3770         return 1;
3771       }
3772
3773       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3774       aTextPosArg.LowerCase();
3775       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3776       if (aTextPosArg == "none")
3777       {
3778         aLabPosition = Aspect_TOCSP_NONE;
3779       }
3780       else if (aTextPosArg == "left")
3781       {
3782         aLabPosition = Aspect_TOCSP_LEFT;
3783       }
3784       else if (aTextPosArg == "right")
3785       {
3786         aLabPosition = Aspect_TOCSP_RIGHT;
3787       }
3788       else if (aTextPosArg == "center")
3789       {
3790         aLabPosition = Aspect_TOCSP_CENTER;
3791       }
3792       else
3793       {
3794         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3795         return 1;
3796       }
3797       aColorScale->SetLabelPosition (aLabPosition);
3798     }
3799     else if (aFlag == "-logarithmic"
3800           || aFlag == "-log")
3801     {
3802       if (anArgIter + 1 >= theArgNb)
3803       {
3804         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3805         return 1;
3806       }
3807
3808       Standard_Boolean IsLog;
3809       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3810       {
3811         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3812         return 1;
3813       }
3814       aColorScale->SetLogarithmic (IsLog);
3815     }
3816     else if (aFlag == "-huerange"
3817           || aFlag == "-hue")
3818     {
3819       if (anArgIter + 2 >= theArgNb)
3820       {
3821         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3822         return 1;
3823       }
3824
3825       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3826       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3827       aColorScale->SetHueRange (aHueMin, aHueMax);
3828     }
3829     else if (aFlag == "-colorrange")
3830     {
3831       Quantity_Color aColorMin, aColorMax;
3832       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3833                                                             theArgVec + (anArgIter + 1),
3834                                                             aColorMin);
3835       anArgIter += aNbParsed1;
3836       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3837                                                             theArgVec + (anArgIter + 1),
3838                                                             aColorMax);
3839       anArgIter += aNbParsed2;
3840       if (aNbParsed1 == 0
3841        || aNbParsed2 == 0)
3842       {
3843         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3844         return 1;
3845       }
3846
3847       aColorScale->SetColorRange (aColorMin, aColorMax);
3848     }
3849     else if (aFlag == "-reversed"
3850           || aFlag == "-inverted"
3851           || aFlag == "-topdown"
3852           || aFlag == "-bottomup")
3853     {
3854       Standard_Boolean toEnable = Standard_True;
3855       if (anArgIter + 1 < theArgNb
3856        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3857       {
3858         ++anArgIter;
3859       }
3860       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3861     }
3862     else if (aFlag == "-smooth"
3863           || aFlag == "-smoothtransition")
3864     {
3865       Standard_Boolean toEnable = Standard_True;
3866       if (anArgIter + 1 < theArgNb
3867        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3868       {
3869         ++anArgIter;
3870       }
3871       aColorScale->SetSmoothTransition (toEnable);
3872     }
3873     else if (aFlag == "-xy")
3874     {
3875       if (anArgIter + 2 >= theArgNb)
3876       {
3877         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3878         return 1;
3879       }
3880
3881       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3882       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3883       if (!anX.IsIntegerValue()
3884        || !anY.IsIntegerValue())
3885       {
3886         std::cout << "Error: coordinates should be integer values!\n";
3887         return 1;
3888       }
3889
3890       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3891     }
3892     else if (aFlag == "-width"
3893           || aFlag == "-w"
3894           || aFlag == "-breadth")
3895     {
3896       if (anArgIter + 1 >= theArgNb)
3897       {
3898         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3899         return 1;
3900       }
3901
3902       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3903       if (!aBreadth.IsIntegerValue())
3904       {
3905         std::cout << "Error: a width should be an integer value!\n";
3906         return 1;
3907       }
3908       aColorScale->SetBreadth (aBreadth.IntegerValue());
3909     }
3910     else if (aFlag == "-height"
3911           || aFlag == "-h")
3912     {
3913       if (anArgIter + 1 >= theArgNb)
3914       {
3915         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3916         return 1;
3917       }
3918
3919       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3920       if (!aHeight.IsIntegerValue())
3921       {
3922         std::cout << "Error: a width should be an integer value!\n";
3923         return 1;
3924       }
3925       aColorScale->SetHeight (aHeight.IntegerValue());
3926     }
3927     else if (aFlag == "-color")
3928     {
3929       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3930       {
3931         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3932         return 1;
3933       }
3934       else if (anArgIter + 2 >= theArgNb)
3935       {
3936         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3937         return 1;
3938       }
3939
3940       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3941       if (!anInd.IsIntegerValue())
3942       {
3943         std::cout << "Error: Index value should be integer!\n";
3944         return 1;
3945       }
3946       const Standard_Integer anIndex = anInd.IntegerValue();
3947       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3948       {
3949         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3950         return 1;
3951       }
3952
3953       Quantity_Color aColor;
3954       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3955                                                            theArgVec + (anArgIter + 1),
3956                                                            aColor);
3957       if (aNbParsed == 0)
3958       {
3959         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3960         return 1;
3961       }
3962       aColorScale->SetIntervalColor (aColor, anIndex);
3963       aColorScale->SetColorType (Aspect_TOCSD_USER);
3964       anArgIter += aNbParsed;
3965     }
3966     else if (aFlag == "-label")
3967     {
3968       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3969       {
3970         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3971         return 1;
3972       }
3973       else if (anArgIter + 2 >= theArgNb)
3974       {
3975         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3976         return 1;
3977       }
3978
3979       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3980       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
3981       {
3982         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
3983         return 1;
3984       }
3985
3986       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3987       aColorScale->SetLabel     (aText, anIndex);
3988       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3989       anArgIter += 2;
3990     }
3991     else if (aFlag == "-labelat"
3992           || aFlag == "-labat"
3993           || aFlag == "-labelatborder"
3994           || aFlag == "-labatborder"
3995           || aFlag == "-labelatcenter"
3996           || aFlag == "-labatcenter")
3997     {
3998       Standard_Boolean toEnable = Standard_True;
3999       if (aFlag == "-labelat"
4000        || aFlag == "-labat")
4001       {
4002         Standard_Integer aLabAtBorder = -1;
4003         if (++anArgIter >= theArgNb)
4004         {
4005           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4006           anAtBorder.LowerCase();
4007           if (anAtBorder == "border")
4008           {
4009             aLabAtBorder = 1;
4010           }
4011           else if (anAtBorder == "center")
4012           {
4013             aLabAtBorder = 0;
4014           }
4015         }
4016         if (aLabAtBorder == -1)
4017         {
4018           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4019           return 1;
4020         }
4021         toEnable = (aLabAtBorder == 1);
4022       }
4023       else if (anArgIter + 1 < theArgNb
4024             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4025       {
4026         ++anArgIter;
4027       }
4028       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4029                                   || aFlag == "-labatcenter"
4030                                    ? !toEnable
4031                                    :  toEnable);
4032     }
4033     else if (aFlag == "-colors")
4034     {
4035       Aspect_SequenceOfColor aSeq;
4036       for (;;)
4037       {
4038         Quantity_Color aColor;
4039         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4040                                                              theArgVec + (anArgIter + 1),
4041                                                              aColor);
4042         if (aNbParsed == 0)
4043         {
4044           break;
4045         }
4046         anArgIter += aNbParsed;
4047         aSeq.Append (aColor);
4048       }
4049       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4050       {
4051         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4052                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4053         return 1;
4054       }
4055
4056       aColorScale->SetColors    (aSeq);
4057       aColorScale->SetColorType (Aspect_TOCSD_USER);
4058     }
4059     else if (aFlag == "-labels"
4060           || aFlag == "-freelabels")
4061     {
4062       if (anArgIter + 1 >= theArgNb)
4063       {
4064         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4065         return 1;
4066       }
4067
4068       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4069                                  ? aColorScale->GetNumberOfIntervals() + 1
4070                                  : aColorScale->GetNumberOfIntervals();
4071       if (aFlag == "-freelabels")
4072       {
4073         ++anArgIter;
4074         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4075       }
4076       if (anArgIter + aNbLabels >= theArgNb)
4077       {
4078         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4079         return 1;
4080       }
4081
4082       TColStd_SequenceOfExtendedString aSeq;
4083       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4084       {
4085         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4086       }
4087       aColorScale->SetLabels (aSeq);
4088       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4089     }
4090     else if (aFlag == "-title")
4091     {
4092       if (anArgIter + 1 >= theArgNb)
4093       {
4094         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4095         return 1;
4096       }
4097
4098       Standard_Boolean isTwoArgs = Standard_False;
4099       if (anArgIter + 2 < theArgNb)
4100       {
4101         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4102         aSecondArg.LowerCase();
4103       Standard_DISABLE_DEPRECATION_WARNINGS
4104         if (aSecondArg == "none")
4105         {
4106           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4107           isTwoArgs = Standard_True;
4108         }
4109         else if (aSecondArg == "left")
4110         {
4111           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4112           isTwoArgs = Standard_True;
4113         }
4114         else if (aSecondArg == "right")
4115         {
4116           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4117           isTwoArgs = Standard_True;
4118         }
4119         else if (aSecondArg == "center")
4120         {
4121           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4122           isTwoArgs = Standard_True;
4123         }
4124       Standard_ENABLE_DEPRECATION_WARNINGS
4125       }
4126
4127       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4128       if (isTwoArgs)
4129       {
4130         anArgIter += 1;
4131       }
4132       anArgIter += 1;
4133     }
4134     else if (aFlag == "-demoversion"
4135           || aFlag == "-demo")
4136     {
4137       aColorScale->SetPosition (0, 0);
4138       aColorScale->SetTextHeight (16);
4139       aColorScale->SetRange (0.0, 100.0);
4140       aColorScale->SetNumberOfIntervals (10);
4141       aColorScale->SetBreadth (0);
4142       aColorScale->SetHeight  (0);
4143       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4144       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4145       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4146     }
4147     else if (aFlag == "-findcolor")
4148     {
4149       if (anArgIter + 1 >= theArgNb)
4150       {
4151         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4152         return 1;
4153       }
4154
4155       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4156
4157       if (!anArg1.IsRealValue())
4158       {
4159         std::cout << "Error: the value should be real!\n";
4160         return 1;
4161       }
4162
4163       Quantity_Color aColor;
4164       aColorScale->FindColor (anArg1.RealValue(), aColor);
4165       theDI << Quantity_Color::StringName (aColor.Name());
4166       return 0;
4167     }
4168     else
4169     {
4170       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4171       return 1;
4172     }
4173   }
4174
4175   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4176   aView->Window()->Size (aWinWidth, aWinHeight);
4177   if (aColorScale->GetBreadth() == 0)
4178   {
4179     aColorScale->SetBreadth (aWinWidth);
4180   }
4181   if (aColorScale->GetHeight() == 0)
4182   {
4183     aColorScale->SetHeight (aWinHeight);
4184   }
4185   aColorScale->SetToUpdate();
4186   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4187   return 0;
4188 }
4189
4190 //==============================================================================
4191 //function : VGraduatedTrihedron
4192 //purpose  : Displays or hides a graduated trihedron
4193 //==============================================================================
4194 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4195                                   Quantity_Color& theColor)
4196 {
4197   Quantity_NameOfColor aColorName;
4198   TCollection_AsciiString aVal = theValue;
4199   aVal.UpperCase();
4200   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4201   {
4202     return Standard_False;
4203   }
4204   theColor = Quantity_Color (aColorName);
4205   return Standard_True;
4206 }
4207
4208 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4209 {
4210   if (theArgNum < 2)
4211   {
4212     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4213               << theArgs[0] <<"' for more information.\n";
4214     return 1;  //TCL_ERROR
4215   }
4216
4217   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4218   TCollection_AsciiString aParseKey;
4219   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4220   {
4221     TCollection_AsciiString anArg (theArgs [anArgIt]);
4222
4223     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4224     {
4225       aParseKey = anArg;
4226       aParseKey.Remove (1);
4227       aParseKey.LowerCase();
4228       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4229       continue;
4230     }
4231
4232     if (aParseKey.IsEmpty())
4233     {
4234       continue;
4235     }
4236
4237     aMapOfArgs(aParseKey)->Append (anArg);
4238   }
4239
4240   // Check parameters
4241   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4242        aMapIt.More(); aMapIt.Next())
4243   {
4244     const TCollection_AsciiString& aKey = aMapIt.Key();
4245     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4246
4247     // Bool key, without arguments
4248     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4249         && anArgs->IsEmpty())
4250     {
4251       continue;
4252     }
4253
4254     // One argument
4255     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4256           && anArgs->Length() == 1)
4257     {
4258       continue;
4259     }
4260
4261     // On/off arguments
4262     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4263         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4264         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4265         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4266         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4267     {
4268       continue;
4269     }
4270
4271     // One string argument
4272     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4273           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4274           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4275     {
4276       continue;
4277     }
4278
4279     // One integer argument
4280     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4281           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4282           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4283           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4284          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4285     {
4286       continue;
4287     }
4288
4289     // One real argument
4290     if ( aKey.IsEqual ("arrowlength")
4291          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4292     {
4293       continue;
4294     }
4295
4296     // Two string arguments
4297     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4298          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4299     {
4300       continue;
4301     }
4302
4303     TCollection_AsciiString aLowerKey;
4304     aLowerKey  = "-";
4305     aLowerKey += aKey;
4306     aLowerKey.LowerCase();
4307     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4308     std::cout << "Type help for more information.\n";
4309     return 1;
4310   }
4311
4312   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4313   if (anAISContext.IsNull())
4314   {
4315     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4316     return 1;
4317   }
4318
4319   Standard_Boolean toDisplay = Standard_True;
4320   Quantity_Color aColor;
4321   Graphic3d_GraduatedTrihedron aTrihedronData;
4322   // Process parameters
4323   Handle(TColStd_HSequenceOfAsciiString) aValues;
4324   if (aMapOfArgs.Find ("off", aValues))
4325   {
4326     toDisplay = Standard_False;
4327   }
4328
4329   // AXES NAMES
4330   if (aMapOfArgs.Find ("xname", aValues))
4331   {
4332     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4333   }
4334   if (aMapOfArgs.Find ("yname", aValues))
4335   {
4336     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4337   }
4338   if (aMapOfArgs.Find ("zname", aValues))
4339   {
4340     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4341   }
4342   if (aMapOfArgs.Find ("xdrawname", aValues))
4343   {
4344     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4345   }
4346   if (aMapOfArgs.Find ("ydrawname", aValues))
4347   {
4348     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4349   }
4350   if (aMapOfArgs.Find ("zdrawname", aValues))
4351   {
4352     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4353   }
4354   if (aMapOfArgs.Find ("xnameoffset", aValues))
4355   {
4356     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4357   }
4358   if (aMapOfArgs.Find ("ynameoffset", aValues))
4359   {
4360     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4361   }
4362   if (aMapOfArgs.Find ("znameoffset", aValues))
4363   {
4364     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4365   }
4366
4367   // COLORS
4368   if (aMapOfArgs.Find ("xnamecolor", aValues))
4369   {
4370     if (!GetColor (aValues->Value(1), aColor))
4371     {
4372       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4373       return 1;
4374     }
4375     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4376   }
4377   if (aMapOfArgs.Find ("ynamecolor", aValues))
4378   {
4379     if (!GetColor (aValues->Value(1), aColor))
4380     {
4381       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4382       return 1;
4383     }
4384     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4385   }
4386   if (aMapOfArgs.Find ("znamecolor", aValues))
4387   {
4388     if (!GetColor (aValues->Value(1), aColor))
4389     {
4390       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4391       return 1;
4392     }
4393     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4394   }
4395   if (aMapOfArgs.Find ("xcolor", aValues))
4396   {
4397     if (!GetColor (aValues->Value(1), aColor))
4398     {
4399       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4400       return 1;
4401     }
4402     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4403   }
4404   if (aMapOfArgs.Find ("ycolor", aValues))
4405   {
4406     if (!GetColor (aValues->Value(1), aColor))
4407     {
4408       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4409       return 1;
4410     }
4411     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4412   }
4413   if (aMapOfArgs.Find ("zcolor", aValues))
4414   {
4415     if (!GetColor (aValues->Value(1), aColor))
4416     {
4417       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4418       return 1;
4419     }
4420     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4421   }
4422
4423   // TICKMARKS
4424   if (aMapOfArgs.Find ("xticks", aValues))
4425   {
4426     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4427   }
4428   if (aMapOfArgs.Find ("yticks", aValues))
4429   {
4430     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4431   }
4432   if (aMapOfArgs.Find ("zticks", aValues))
4433   {
4434     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4435   }
4436   if (aMapOfArgs.Find ("xticklength", aValues))
4437   {
4438     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4439   }
4440   if (aMapOfArgs.Find ("yticklength", aValues))
4441   {
4442     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4443   }
4444   if (aMapOfArgs.Find ("zticklength", aValues))
4445   {
4446     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4447   }
4448   if (aMapOfArgs.Find ("xdrawticks", aValues))
4449   {
4450     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4451   }
4452   if (aMapOfArgs.Find ("ydrawticks", aValues))
4453   {
4454     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4455   }
4456   if (aMapOfArgs.Find ("zdrawticks", aValues))
4457   {
4458     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4459   }
4460
4461   // VALUES
4462   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4463   {
4464     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4465   }
4466   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4467   {
4468     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4469   }
4470   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4471   {
4472     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4473   }
4474   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4475   {
4476     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4477   }
4478   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4479   {
4480     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4481   }
4482   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4483   {
4484     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4485   }
4486
4487   // ARROWS
4488   if (aMapOfArgs.Find ("arrowlength", aValues))
4489   {
4490     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4491   }
4492
4493   // FONTS
4494   if (aMapOfArgs.Find ("namefont", aValues))
4495   {
4496     aTrihedronData.SetNamesFont (aValues->Value(1));
4497   }
4498   if (aMapOfArgs.Find ("valuesfont", aValues))
4499   {
4500     aTrihedronData.SetValuesFont (aValues->Value(1));
4501   }
4502
4503   if (aMapOfArgs.Find ("drawgrid", aValues))
4504   {
4505     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4506   }
4507   if (aMapOfArgs.Find ("drawaxes", aValues))
4508   {
4509     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4510   }
4511
4512   // The final step: display of erase trihedron
4513   if (toDisplay)
4514   {
4515     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4516   }
4517   else
4518   {
4519     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4520   }
4521
4522   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4523   ViewerTest::CurrentView()->Redraw();
4524
4525   return 0;
4526 }
4527
4528 //==============================================================================
4529 //function : VTile
4530 //purpose  :
4531 //==============================================================================
4532 static int VTile (Draw_Interpretor& theDI,
4533                   Standard_Integer  theArgNb,
4534                   const char**      theArgVec)
4535 {
4536   Handle(V3d_View) aView = ViewerTest::CurrentView();
4537   if (aView.IsNull())
4538   {
4539     std::cerr << "Error: no active viewer.\n";
4540     return 1;
4541   }
4542
4543   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4544   if (theArgNb < 2)
4545   {
4546     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4547           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4548           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4549     return 0;
4550   }
4551
4552   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4553   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4554   {
4555     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4556     anArg.LowerCase();
4557     if (anArg == "-lowerleft"
4558      || anArg == "-upperleft")
4559     {
4560       if (anArgIter + 3 < theArgNb)
4561       {
4562         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4563         return 1;
4564       }
4565       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4566       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4567       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4568     }
4569     else if (anArg == "-total"
4570           || anArg == "-totalsize"
4571           || anArg == "-viewsize")
4572     {
4573       if (anArgIter + 3 < theArgNb)
4574       {
4575         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4576         return 1;
4577       }
4578       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4579       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4580       if (aTile.TotalSize.x() < 1
4581        || aTile.TotalSize.y() < 1)
4582       {
4583         std::cerr << "Error: total size is incorrect.\n";
4584         return 1;
4585       }
4586     }
4587     else if (anArg == "-tilesize")
4588     {
4589       if (anArgIter + 3 < theArgNb)
4590       {
4591         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4592         return 1;
4593       }
4594
4595       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4596       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4597       if (aTile.TileSize.x() < 1
4598        || aTile.TileSize.y() < 1)
4599       {
4600         std::cerr << "Error: tile size is incorrect.\n";
4601         return 1;
4602       }
4603     }
4604     else if (anArg == "-unset")
4605     {
4606       aView->Camera()->SetTile (Graphic3d_CameraTile());
4607       aView->Redraw();
4608       return 0;
4609     }
4610   }
4611
4612   if (aTile.TileSize.x() < 1
4613    || aTile.TileSize.y() < 1)
4614   {
4615     std::cerr << "Error: tile size is undefined.\n";
4616     return 1;
4617   }
4618   else if (aTile.TotalSize.x() < 1
4619         || aTile.TotalSize.y() < 1)
4620   {
4621     std::cerr << "Error: total size is undefined.\n";
4622     return 1;
4623   }
4624
4625   aView->Camera()->SetTile (aTile);
4626   aView->Redraw();
4627   return 0;
4628 }
4629
4630 //! Format ZLayer ID.
4631 inline const char* formZLayerId (const Standard_Integer theLayerId)
4632 {
4633   switch (theLayerId)
4634   {
4635     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4636     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4637     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4638     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4639     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4640     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4641   }
4642   return "";
4643 }
4644
4645 //! Print the ZLayer information.
4646 inline void printZLayerInfo (Draw_Interpretor& theDI,
4647                              const Graphic3d_ZLayerSettings& theLayer)
4648 {
4649   if (!theLayer.Name().IsEmpty())
4650   {
4651     theDI << "  Name: " << theLayer.Name() << "\n";
4652   }
4653   if (theLayer.IsImmediate())
4654   {
4655     theDI << "  Immediate: TRUE\n";
4656   }
4657   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4658   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
4659   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
4660   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4661   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4662   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4663   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4664   {
4665     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4666   }
4667 }
4668
4669 //==============================================================================
4670 //function : VZLayer
4671 //purpose  : Test z layer operations for v3d viewer
4672 //==============================================================================
4673 static int VZLayer (Draw_Interpretor& theDI,
4674                     Standard_Integer  theArgNb,
4675                     const char**      theArgVec)
4676 {
4677   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4678   if (aContextAIS.IsNull())
4679   {
4680     std::cout << "No active viewer!\n";
4681     return 1;
4682   }
4683
4684   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4685   if (theArgNb < 2)
4686   {
4687     TColStd_SequenceOfInteger aLayers;
4688     aViewer->GetAllZLayers (aLayers);
4689     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4690     {
4691       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4692       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4693       printZLayerInfo (theDI, aSettings);
4694     }
4695     return 1;
4696   }
4697
4698   Standard_Integer anArgIter = 1;
4699   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4700   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4701   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4702   {
4703     ++anArgIter;
4704   }
4705
4706   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4707   if (aFirstArg.IsIntegerValue())
4708   {
4709     ++anArgIter;
4710     aLayerId = aFirstArg.IntegerValue();
4711   }
4712   else
4713   {
4714     aFirstArg.LowerCase();
4715     if (aFirstArg == "default"
4716      || aFirstArg == "def")
4717     {
4718       aLayerId = Graphic3d_ZLayerId_Default;
4719       ++anArgIter;
4720     }
4721     else if (aFirstArg == "top")
4722     {
4723       aLayerId = Graphic3d_ZLayerId_Top;
4724       ++anArgIter;
4725     }
4726     else if (aFirstArg == "topmost")
4727     {
4728       aLayerId = Graphic3d_ZLayerId_Topmost;
4729       ++anArgIter;
4730     }
4731     else if (aFirstArg == "overlay"
4732           || aFirstArg == "toposd")
4733     {
4734       aLayerId = Graphic3d_ZLayerId_TopOSD;
4735       ++anArgIter;
4736     }
4737     else if (aFirstArg == "underlay"
4738           || aFirstArg == "botosd")
4739     {
4740       aLayerId = Graphic3d_ZLayerId_BotOSD;
4741       ++anArgIter;
4742     }
4743     else
4744     {
4745       TColStd_SequenceOfInteger aLayers;
4746       aViewer->GetAllZLayers (aLayers);
4747       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4748       {
4749         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4750         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4751         {
4752           aLayerId = aLayeriter.Value();
4753           ++anArgIter;
4754           break;
4755         }
4756       }
4757     }
4758   }
4759
4760   for (; anArgIter < theArgNb; ++anArgIter)
4761   {
4762     // perform operation
4763     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4764     anArg.LowerCase();
4765     if (anUpdateTool.parseRedrawMode (anArg))
4766     {
4767       //
4768     }
4769     else if (anArg == "-add"
4770           || anArg == "add")
4771     {
4772       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4773       if (!aViewer->AddZLayer (aLayerId))
4774       {
4775         std::cout << "Error: can not add a new z layer!\n";
4776         return 0;
4777       }
4778
4779       theDI << aLayerId;
4780     }
4781     else if (anArg == "-del"
4782           || anArg == "-delete"
4783           || anArg == "del")
4784     {
4785       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4786       {
4787         if (++anArgIter >= theArgNb)
4788         {
4789           std::cout << "Syntax error: id of z layer to remove is missing\n";
4790           return 1;
4791         }
4792
4793         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4794       }
4795
4796       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4797        || aLayerId == Graphic3d_ZLayerId_Default
4798        || aLayerId == Graphic3d_ZLayerId_Top
4799        || aLayerId == Graphic3d_ZLayerId_Topmost
4800        || aLayerId == Graphic3d_ZLayerId_TopOSD
4801        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4802       {
4803         std::cout << "Syntax error: standard Z layer can not be removed\n";
4804         return 1;
4805       }
4806
4807       // move all object displayed in removing layer to default layer
4808       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4809            anObjIter.More(); anObjIter.Next())
4810       {
4811         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4812         if (aPrs.IsNull()
4813          || aPrs->ZLayer() != aLayerId)
4814         {
4815           continue;
4816         }
4817         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4818       }
4819
4820       if (!aViewer->RemoveZLayer (aLayerId))
4821       {
4822         std::cout << "Z layer can not be removed!\n";
4823       }
4824       else
4825       {
4826         theDI << aLayerId << " ";
4827       }
4828     }
4829     else if (anArg == "-get"
4830           || anArg == "get")
4831     {
4832       TColStd_SequenceOfInteger aLayers;
4833       aViewer->GetAllZLayers (aLayers);
4834       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4835       {
4836         theDI << aLayeriter.Value() << " ";
4837       }
4838
4839       theDI << "\n";
4840     }
4841     else if (anArg == "-name")
4842     {
4843       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4844       {
4845         std::cout << "Syntax error: id of Z layer is missing\n";
4846         return 1;
4847       }
4848
4849       if (++anArgIter >= theArgNb)
4850       {
4851         std::cout << "Syntax error: name is missing\n";
4852         return 1;
4853       }
4854
4855       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4856       aSettings.SetName (theArgVec[anArgIter]);
4857       aViewer->SetZLayerSettings (aLayerId, aSettings);
4858     }
4859     else if (anArg == "-origin")
4860     {
4861       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4862       {
4863         std::cout << "Syntax error: id of Z layer is missing\n";
4864         return 1;
4865       }
4866
4867       if (anArgIter + 2 >= theArgNb)
4868       {
4869         std::cout << "Syntax error: origin coordinates are missing\n";
4870         return 1;
4871       }
4872
4873       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4874       gp_XYZ anOrigin;
4875       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4876       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4877       anOrigin.SetZ (0.0);
4878       if (anArgIter + 3 < theArgNb)
4879       {
4880         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4881         anArgIter += 3;
4882       }
4883       else
4884       {
4885         anArgIter += 2;
4886       }
4887       aSettings.SetOrigin (anOrigin);
4888       aViewer->SetZLayerSettings (aLayerId, aSettings);
4889     }
4890     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4891           && anArgIter + 1 < theArgNb
4892           && (anArg == "-cullingdistance"
4893            || anArg == "-cullingdist"
4894            || anArg == "-culldistance"
4895            || anArg == "-culldist"
4896            || anArg == "-distcull"
4897            || anArg == "-distculling"
4898            || anArg == "-distanceculling"))
4899     {
4900       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4901       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
4902       aSettings.SetCullingDistance (aDist);
4903       aViewer->SetZLayerSettings (aLayerId, aSettings);
4904     }
4905     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4906           && anArgIter + 1 < theArgNb
4907           && (anArg == "-cullingsize"
4908            || anArg == "-cullsize"
4909            || anArg == "-sizecull"
4910            || anArg == "-sizeculling"))
4911     {
4912       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4913       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
4914       aSettings.SetCullingSize (aSize);
4915       aViewer->SetZLayerSettings (aLayerId, aSettings);
4916     }
4917     else if (anArg == "-settings"
4918           || anArg == "settings")
4919     {
4920       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4921       {
4922         if (++anArgIter >= theArgNb)
4923         {
4924           std::cout << "Syntax error: id of Z layer is missing\n";
4925           return 1;
4926         }
4927
4928         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4929       }
4930
4931       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4932       printZLayerInfo (theDI, aSettings);
4933     }
4934     else if (anArg == "-enable"
4935           || anArg == "enable"
4936           || anArg == "-disable"
4937           || anArg == "disable")
4938     {
4939       const Standard_Boolean toEnable = anArg == "-enable"
4940                                      || anArg == "enable";
4941       if (++anArgIter >= theArgNb)
4942       {
4943         std::cout << "Syntax error: option name is missing\n";
4944         return 1;
4945       }
4946
4947       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4948       aSubOp.LowerCase();
4949       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4950       {
4951         if (++anArgIter >= theArgNb)
4952         {
4953           std::cout << "Syntax error: id of Z layer is missing\n";
4954           return 1;
4955         }
4956
4957         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4958       }
4959
4960       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4961       if (aSubOp == "depthtest"
4962        || aSubOp == "test")
4963       {
4964         aSettings.SetEnableDepthTest (toEnable);
4965       }
4966       else if (aSubOp == "depthwrite"
4967             || aSubOp == "write")
4968       {
4969         aSettings.SetEnableDepthWrite (toEnable);
4970       }
4971       else if (aSubOp == "depthclear"
4972             || aSubOp == "clear")
4973       {
4974         aSettings.SetClearDepth (toEnable);
4975       }
4976       else if (aSubOp == "depthoffset"
4977             || aSubOp == "offset")
4978       {
4979         Graphic3d_PolygonOffset aParams;
4980         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4981         if (toEnable)
4982         {
4983           if (anArgIter + 2 >= theArgNb)
4984           {
4985             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4986             return 1;
4987           }
4988
4989           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4990           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4991         }
4992         aSettings.SetPolygonOffset (aParams);
4993       }
4994       else if (aSubOp == "positiveoffset"
4995             || aSubOp == "poffset")
4996       {
4997         if (toEnable)
4998         {
4999           aSettings.SetDepthOffsetPositive();
5000         }
5001         else
5002         {
5003           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5004         }
5005       }
5006       else if (aSubOp == "negativeoffset"
5007             || aSubOp == "noffset")
5008       {
5009         if (toEnable)
5010         {
5011           aSettings.SetDepthOffsetNegative();
5012         }
5013         else
5014         {
5015           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5016         }
5017       }
5018       else if (aSubOp == "textureenv")
5019       {
5020         aSettings.SetEnvironmentTexture (toEnable);
5021       }
5022
5023       aViewer->SetZLayerSettings (aLayerId, aSettings);
5024     }
5025     else
5026     {
5027       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5028       return 1;
5029     }
5030   }
5031
5032   return 0;
5033 }
5034
5035 // The interactive presentation of 2d layer item
5036 // for "vlayerline" command it provides a presentation of
5037 // line with user-defined linewidth, linetype and transparency.
5038 class V3d_LineItem : public AIS_InteractiveObject
5039 {
5040 public:
5041   // CASCADE RTTI
5042   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5043
5044   // constructor
5045   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5046                                Standard_Real X2, Standard_Real Y2,
5047                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5048                                Standard_Real theWidth    = 0.5,
5049                                Standard_Real theTransp   = 1.0);
5050
5051   private:
5052
5053   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5054                 const Handle(Prs3d_Presentation)& thePresentation,
5055                 const Standard_Integer theMode) Standard_OVERRIDE;
5056
5057   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5058                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5059   {}
5060
5061 private:
5062
5063   Standard_Real       myX1, myY1, myX2, myY2;
5064   Aspect_TypeOfLine   myType;
5065   Standard_Real       myWidth;
5066 };
5067
5068 // default constructor for line item
5069 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5070                            Standard_Real X2, Standard_Real Y2,
5071                            Aspect_TypeOfLine theType,
5072                            Standard_Real theWidth,
5073                            Standard_Real theTransp) :
5074   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5075   myType(theType), myWidth(theWidth)
5076 {
5077   SetTransparency (1-theTransp);
5078 }
5079
5080 // render line
5081 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5082                             const Handle(Prs3d_Presentation)& thePresentation,
5083                             const Standard_Integer /*theMode*/)
5084 {
5085   thePresentation->Clear();
5086   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5087   Standard_Integer aWidth, aHeight;
5088   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5089   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5090   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5091   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5092   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5093   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5094   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5095   aGroup->AddPrimitiveArray (aPrim);
5096 }
5097
5098 //=============================================================================
5099 //function : VLayerLine
5100 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5101 //         : linewidth, transparency coefficient
5102 //============================================================================
5103 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5104 {
5105   // get the active view
5106   Handle(V3d_View) aView = ViewerTest::CurrentView();
5107   if (aView.IsNull())
5108   {
5109     di << "Call vinit before!\n";
5110     return 1;
5111   }
5112   else if (argc < 5)
5113   {
5114     di << "Use: " << argv[0];
5115     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5116     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5117     di << "              0 - solid  \n";
5118     di << "              1 - dashed \n";
5119     di << "              2 - dot    \n";
5120     di << "              3 - dashdot\n";
5121     di << " transparency : { 0.0 - 1.0 } \n";
5122     di << "                  0.0 - transparent\n";
5123     di << "                  1.0 - visible    \n";
5124     return 1;
5125   }
5126
5127   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5128   // get the input params
5129   Standard_Real X1 = Draw::Atof(argv[1]);
5130   Standard_Real Y1 = Draw::Atof(argv[2]);
5131   Standard_Real X2 = Draw::Atof(argv[3]);
5132   Standard_Real Y2 = Draw::Atof(argv[4]);
5133
5134   Standard_Real aWidth = 0.5;
5135   Standard_Real aTransparency = 1.0;
5136
5137   // has width
5138   if (argc > 5)
5139     aWidth = Draw::Atof(argv[5]);
5140
5141   // select appropriate line type
5142   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5143   if (argc > 6
5144   && !ViewerTest::ParseLineType (argv[6], aLineType))
5145   {
5146     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5147     return 1;
5148   }
5149
5150   // has transparency
5151   if (argc > 7)
5152   {
5153     aTransparency = Draw::Atof(argv[7]);
5154     if (aTransparency < 0 || aTransparency > 1.0)
5155       aTransparency = 1.0;
5156   }
5157
5158   static Handle (V3d_LineItem) aLine;
5159   if (!aLine.IsNull())
5160   {
5161     aContext->Erase (aLine, Standard_False);
5162   }
5163   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5164                             aLineType, aWidth,
5165                             aTransparency);
5166
5167   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5168   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5169   aLine->SetToUpdate();
5170   aContext->Display (aLine, Standard_True);
5171
5172   return 0;
5173 }
5174
5175
5176 //==============================================================================
5177 //function : VGrid
5178 //purpose  :
5179 //==============================================================================
5180
5181 static int VGrid (Draw_Interpretor& /*theDI*/,
5182                   Standard_Integer  theArgNb,
5183                   const char**      theArgVec)
5184 {
5185   // get the active view
5186   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5187   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5188   if (aView.IsNull() || aViewer.IsNull())
5189   {
5190     std::cerr << "No active view. Please call vinit.\n";
5191     return 1;
5192   }
5193
5194   Aspect_GridType     aType = aViewer->GridType();
5195   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5196   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5197   Standard_Integer anIter = 1;
5198   for (; anIter < theArgNb; ++anIter)
5199   {
5200     const char* aValue = theArgVec[anIter];
5201     if (anUpdateTool.parseRedrawMode (aValue))
5202     {
5203       continue;
5204     }
5205     else if (*aValue == 'r')
5206     {
5207       aType = Aspect_GT_Rectangular;
5208     }
5209     else if (*aValue == 'c')
5210     {
5211       aType = Aspect_GT_Circular;
5212     }
5213     else if (*aValue == 'l')
5214     {
5215       aMode = Aspect_GDM_Lines;
5216     }
5217     else if (*aValue == 'p')
5218     {
5219       aMode = Aspect_GDM_Points;
5220     }
5221     else if (strcmp (aValue, "off" ) == 0)
5222     {
5223       aViewer->DeactivateGrid();
5224       return 0;
5225     }
5226     else
5227     {
5228       break;
5229     }
5230   }
5231
5232   Standard_Integer aTail = (theArgNb - anIter);
5233   if (aTail == 0)
5234   {
5235     aViewer->ActivateGrid (aType, aMode);
5236     return 0;
5237   }
5238   else if (aTail != 2 && aTail != 5)
5239   {
5240     std::cerr << "Incorrect arguments number! Usage:\n"
5241               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5242     return 1;
5243   }
5244
5245   Standard_Real anOriginX, anOriginY, aRotAngle;
5246   if (aType == Aspect_GT_Rectangular)
5247   {
5248     Standard_Real aRStepX, aRStepY;
5249     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5250
5251     anOriginX = Draw::Atof (theArgVec[anIter++]);
5252     anOriginY = Draw::Atof (theArgVec[anIter++]);
5253     if (aTail == 5)
5254     {
5255       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5256       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5257       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5258     }
5259     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5260     aViewer->ActivateGrid (aType, aMode);
5261   }
5262   else if (aType == Aspect_GT_Circular)
5263   {
5264     Standard_Real aRadiusStep;
5265     Standard_Integer aDivisionNumber;
5266     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5267
5268     anOriginX = Draw::Atof (theArgVec[anIter++]);
5269     anOriginY = Draw::Atof (theArgVec[anIter++]);
5270     if (aTail == 5)
5271     {
5272       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5273       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5274       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5275     }
5276
5277     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5278     aViewer->ActivateGrid (aType, aMode);
5279   }
5280
5281   return 0;
5282 }
5283
5284 //==============================================================================
5285 //function : VPriviledgedPlane
5286 //purpose  :
5287 //==============================================================================
5288
5289 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5290                               Standard_Integer  theArgNb,
5291                               const char**      theArgVec)
5292 {
5293   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5294   {
5295     std::cerr << "Error: wrong number of arguments! See usage:\n";
5296     theDI.PrintHelp (theArgVec[0]);
5297     return 1;
5298   }
5299
5300   // get the active viewer
5301   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5302   if (aViewer.IsNull())
5303   {
5304     std::cerr << "Error: no active viewer. Please call vinit.\n";
5305     return 1;
5306   }
5307
5308   if (theArgNb == 1)
5309   {
5310     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5311     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5312     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5313     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5314     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5315           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5316           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5317     return 0;
5318   }
5319
5320   Standard_Integer anArgIdx = 1;
5321   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5322   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5323   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5324   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5325   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5326   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5327
5328   gp_Ax3 aPriviledgedPlane;
5329   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5330   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5331   if (theArgNb > 7)
5332   {
5333     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5334     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5335     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5336     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5337     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5338   }
5339   else
5340   {
5341     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5342   }
5343
5344   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5345
5346   return 0;
5347 }
5348
5349 //==============================================================================
5350 //function : VConvert
5351 //purpose  :
5352 //==============================================================================
5353
5354 static int VConvert (Draw_Interpretor& theDI,
5355                      Standard_Integer  theArgNb,
5356                      const char**      theArgVec)
5357 {
5358   // get the active view
5359   Handle(V3d_View) aView = ViewerTest::CurrentView();
5360   if (aView.IsNull())
5361   {
5362     std::cerr << "Error: no active view. Please call vinit.\n";
5363     return 1;
5364   }
5365
5366   enum { Model, Ray, View, Window, Grid } aMode = Model;
5367
5368   // access coordinate arguments
5369   TColStd_SequenceOfReal aCoord;
5370   Standard_Integer anArgIdx = 1;
5371   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5372   {
5373     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5374     if (!anArg.IsRealValue())
5375     {
5376       break;
5377     }
5378     aCoord.Append (anArg.RealValue());
5379   }
5380
5381   // non-numeric argument too early
5382   if (aCoord.IsEmpty())
5383   {
5384     std::cerr << "Error: wrong number of arguments! See usage:\n";
5385     theDI.PrintHelp (theArgVec[0]);
5386     return 1;
5387   }
5388
5389   // collect all other arguments and options
5390   for (; anArgIdx < theArgNb; ++anArgIdx)
5391   {
5392     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5393     anArg.LowerCase();
5394     if      (anArg == "window") aMode = Window;
5395     else if (anArg == "view")   aMode = View;
5396     else if (anArg == "grid")   aMode = Grid;
5397     else if (anArg == "ray")    aMode = Ray;
5398     else
5399     {
5400       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5401       theDI.PrintHelp (theArgVec[0]);
5402       return 1;
5403     }
5404   }
5405
5406   // complete input checks
5407   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5408       (aCoord.Length() == 2 && theArgNb > 4) ||
5409       (aCoord.Length() == 3 && theArgNb > 5))
5410   {
5411     std::cerr << "Error: wrong number of arguments! See usage:\n";
5412     theDI.PrintHelp (theArgVec[0]);
5413     return 1;
5414   }
5415
5416   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5417   Standard_Integer aXYp[2] = {0, 0};
5418
5419   // convert one-dimensional coordinate
5420   if (aCoord.Length() == 1)
5421   {
5422     switch (aMode)
5423     {
5424       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5425       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5426       default:
5427         std::cerr << "Error: wrong arguments! See usage:\n";
5428         theDI.PrintHelp (theArgVec[0]);
5429         return 1;
5430     }
5431   }
5432
5433   // convert 2D coordinates from projection or view reference space
5434   if (aCoord.Length() == 2)
5435   {
5436     switch (aMode)
5437     {
5438       case Model :
5439         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5440         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5441         return 0;
5442
5443       case View :
5444         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5445         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5446         return 0;
5447
5448       case Window :
5449         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5450         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5451         return 0;
5452
5453       case Grid :
5454         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5455         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5456         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5457         return 0;
5458
5459       case Ray :
5460         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5461                                 (Standard_Integer) aCoord (2),
5462                                 aXYZ[0], aXYZ[1], aXYZ[2],
5463                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5464         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5465         return 0;
5466
5467       default:
5468         std::cerr << "Error: wrong arguments! See usage:\n";
5469         theDI.PrintHelp (theArgVec[0]);
5470         return 1;
5471     }
5472   }
5473
5474   // convert 3D coordinates from view reference space
5475   else if (aCoord.Length() == 3)
5476   {
5477     switch (aMode)
5478     {
5479       case Window :
5480         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5481         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5482         return 0;
5483
5484       case Grid :
5485         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5486         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5487         return 0;
5488
5489       default:
5490         std::cerr << "Error: wrong arguments! See usage:\n";
5491         theDI.PrintHelp (theArgVec[0]);
5492         return 1;
5493     }
5494   }
5495
5496   return 0;
5497 }
5498
5499 //==============================================================================
5500 //function : VFps
5501 //purpose  :
5502 //==============================================================================
5503
5504 static int VFps (Draw_Interpretor& theDI,
5505                  Standard_Integer  theArgNb,
5506                  const char**      theArgVec)
5507 {
5508   // get the active view
5509   Handle(V3d_View) aView = ViewerTest::CurrentView();
5510   if (aView.IsNull())
5511   {
5512     std::cerr << "No active view. Please call vinit.\n";
5513     return 1;
5514   }
5515
5516   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5517   if (aFramesNb <= 0)
5518   {
5519     std::cerr << "Incorrect arguments!\n";
5520     return 1;
5521   }
5522
5523   // the time is meaningless for first call
5524   // due to async OpenGl rendering
5525   aView->Redraw();
5526
5527   // redraw view in loop to estimate average values
5528   OSD_Timer aTimer;
5529   aTimer.Start();
5530   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5531   {
5532     aView->Redraw();
5533   }
5534   aTimer.Stop();
5535   Standard_Real aCpu;
5536   const Standard_Real aTime = aTimer.ElapsedTime();
5537   aTimer.OSD_Chronometer::Show (aCpu);
5538
5539   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5540   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5541
5542   // return statistics
5543   theDI << "FPS: " << aFpsAver << "\n"
5544         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5545
5546   // compute additional statistics in ray-tracing mode
5547   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5548
5549   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5550   {
5551     Standard_Integer aSizeX;
5552     Standard_Integer aSizeY;
5553
5554     aView->Window()->Size (aSizeX, aSizeY);
5555
5556     // 1 shadow ray and 1 secondary ray pew each bounce
5557     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5558
5559     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5560   }
5561
5562   return 0;
5563 }
5564
5565 //==============================================================================
5566 //function : VGlDebug
5567 //purpose  :
5568 //==============================================================================
5569
5570 static int VGlDebug (Draw_Interpretor& theDI,
5571                      Standard_Integer  theArgNb,
5572                      const char**      theArgVec)
5573 {
5574   Handle(OpenGl_GraphicDriver) aDriver;
5575   Handle(V3d_View) aView = ViewerTest::CurrentView();
5576   if (!aView.IsNull())
5577   {
5578     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5579   }
5580   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5581   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5582
5583   if (theArgNb < 2)
5584   {
5585     TCollection_AsciiString aDebActive, aSyncActive;
5586     if (aCaps == NULL)
5587     {
5588       aCaps = aDefCaps;
5589     }
5590     else
5591     {
5592       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5593                                                                   "GL_ARB_debug_output");
5594       aDebActive = isActive ? " (active)" : " (inactive)";
5595       if (isActive)
5596       {
5597         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5598         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5599       }
5600     }
5601
5602     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5603           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5604           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5605           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5606     return 0;
5607   }
5608
5609   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5610   {
5611     Standard_CString        anArg     = theArgVec[anArgIter];
5612     TCollection_AsciiString anArgCase (anArg);
5613     anArgCase.LowerCase();
5614     Standard_Boolean toEnableDebug = Standard_True;
5615     if (anArgCase == "-glsl"
5616      || anArgCase == "-glslwarn"
5617      || anArgCase == "-glslwarns"
5618      || anArgCase == "-glslwarnings")
5619     {
5620       Standard_Boolean toShowWarns = Standard_True;
5621       if (++anArgIter < theArgNb
5622       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5623       {
5624         --anArgIter;
5625       }
5626       aDefCaps->glslWarnings = toShowWarns;
5627       if (aCaps != NULL)
5628       {
5629         aCaps->glslWarnings = toShowWarns;
5630       }
5631     }
5632     else if (anArgCase == "-extra"
5633           || anArgCase == "-extramsg"
5634           || anArgCase == "-extramessages")
5635     {
5636       Standard_Boolean toShow = Standard_True;
5637       if (++anArgIter < theArgNb
5638       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5639       {
5640         --anArgIter;
5641       }
5642       aDefCaps->suppressExtraMsg = !toShow;
5643       if (aCaps != NULL)
5644       {
5645         aCaps->suppressExtraMsg = !toShow;
5646       }
5647     }
5648     else if (anArgCase == "-noextra"
5649           || anArgCase == "-noextramsg"
5650           || anArgCase == "-noextramessages")
5651     {
5652       Standard_Boolean toSuppress = Standard_True;
5653       if (++anArgIter < theArgNb
5654       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5655       {
5656         --anArgIter;
5657       }
5658       aDefCaps->suppressExtraMsg = toSuppress;
5659       if (aCaps != NULL)
5660       {
5661         aCaps->suppressExtraMsg = toSuppress;
5662       }
5663     }
5664     else if (anArgCase == "-sync")
5665     {
5666       Standard_Boolean toSync = Standard_True;
5667       if (++anArgIter < theArgNb
5668       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5669       {
5670         --anArgIter;
5671       }
5672       aDefCaps->contextSyncDebug = toSync;
5673       if (toSync)
5674       {
5675         aDefCaps->contextDebug = Standard_True;
5676       }
5677     }
5678     else if (anArgCase == "-debug")
5679     {
5680       if (++anArgIter < theArgNb
5681       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5682       {
5683         --anArgIter;
5684       }
5685       aDefCaps->contextDebug = toEnableDebug;
5686     }
5687     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5688           && (anArgIter + 1 == theArgNb))
5689     {
5690       // simple alias to turn on almost everything
5691       aDefCaps->contextDebug     = toEnableDebug;
5692       aDefCaps->contextSyncDebug = toEnableDebug;
5693       aDefCaps->glslWarnings     = toEnableDebug;
5694     }
5695     else
5696     {
5697       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5698       return 1;
5699     }
5700   }
5701
5702   return 0;
5703 }
5704
5705 //==============================================================================
5706 //function : VVbo
5707 //purpose  :
5708 //==============================================================================
5709
5710 static int VVbo (Draw_Interpretor& theDI,
5711                  Standard_Integer  theArgNb,
5712                  const char**      theArgVec)
5713 {
5714   const Standard_Boolean toSet    = (theArgNb > 1);
5715   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5716   if (toSet)
5717   {
5718     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5719   }
5720
5721   // get the context
5722   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5723   if (aContextAIS.IsNull())
5724   {
5725     if (!toSet)
5726     {
5727       std::cerr << "No active view!\n";
5728     }
5729     return 1;
5730   }
5731   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5732   if (!aDriver.IsNull())
5733   {
5734     if (!toSet)
5735     {
5736       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5737     }
5738     else
5739     {
5740       aDriver->ChangeOptions().vboDisable = toUseVbo;
5741     }
5742   }
5743
5744   return 0;
5745 }
5746
5747 //==============================================================================
5748 //function : VCaps
5749 //purpose  :
5750 //==============================================================================
5751
5752 static int VCaps (Draw_Interpretor& theDI,
5753                   Standard_Integer  theArgNb,
5754                   const char**      theArgVec)
5755 {
5756   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5757   Handle(OpenGl_GraphicDriver)   aDriver;
5758   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5759   if (!aContext.IsNull())
5760   {
5761     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5762     aCaps   = &aDriver->ChangeOptions();
5763   }
5764
5765   if (theArgNb < 2)
5766   {
5767     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5768     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5769     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5770     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5771     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5772     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5773     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5774     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5775     return 0;
5776   }
5777
5778   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5779   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5780   {
5781     Standard_CString        anArg     = theArgVec[anArgIter];
5782     TCollection_AsciiString anArgCase (anArg);
5783     anArgCase.LowerCase();
5784     if (anUpdateTool.parseRedrawMode (anArg))
5785     {
5786       continue;
5787     }
5788     else if (anArgCase == "-vsync"
5789           || anArgCase == "-swapinterval")
5790     {
5791       Standard_Boolean toEnable = Standard_True;
5792       if (++anArgIter < theArgNb
5793       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5794       {
5795         --anArgIter;
5796       }
5797       aCaps->swapInterval = toEnable;
5798     }
5799     else if (anArgCase == "-ffp")
5800     {
5801       Standard_Boolean toEnable = Standard_True;
5802       if (++anArgIter < theArgNb
5803       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5804       {
5805         --anArgIter;
5806       }
5807       aCaps->ffpEnable = toEnable;
5808     }
5809     else if (anArgCase == "-vbo")
5810     {
5811       Standard_Boolean toEnable = Standard_True;
5812       if (++anArgIter < theArgNb
5813       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5814       {
5815         --anArgIter;
5816       }
5817       aCaps->vboDisable = !toEnable;
5818     }
5819     else if (anArgCase == "-sprite"
5820           || anArgCase == "-sprites")
5821     {
5822       Standard_Boolean toEnable = Standard_True;
5823       if (++anArgIter < theArgNb
5824       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5825       {
5826         --anArgIter;
5827       }
5828       aCaps->pntSpritesDisable = !toEnable;
5829     }
5830     else if (anArgCase == "-softmode")
5831     {
5832       Standard_Boolean toEnable = Standard_True;
5833       if (++anArgIter < theArgNb
5834       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5835       {
5836         --anArgIter;
5837       }
5838       aCaps->contextNoAccel = toEnable;
5839     }
5840     else if (anArgCase == "-winbuffer"
5841           || anArgCase == "-windowbuffer"
5842           || anArgCase == "-usewinbuffer"
5843           || anArgCase == "-usewindowbuffer"
5844           || anArgCase == "-usesystembuffer")
5845     {
5846       Standard_Boolean toEnable = Standard_True;
5847       if (++anArgIter < theArgNb
5848       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5849       {
5850         --anArgIter;
5851       }
5852       aCaps->useSystemBuffer = toEnable;
5853     }
5854     else if (anArgCase == "-accel"
5855           || anArgCase == "-acceleration")
5856     {
5857       Standard_Boolean toEnable = Standard_True;
5858       if (++anArgIter < theArgNb
5859       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5860       {
5861         --anArgIter;
5862       }
5863       aCaps->contextNoAccel = !toEnable;
5864     }
5865     else if (anArgCase == "-compat"
5866           || anArgCase == "-compatprofile"
5867           || anArgCase == "-compatible"
5868           || anArgCase == "-compatibleprofile")
5869     {
5870       Standard_Boolean toEnable = Standard_True;
5871       if (++anArgIter < theArgNb
5872       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5873       {
5874         --anArgIter;
5875       }
5876       aCaps->contextCompatible = toEnable;
5877       if (!aCaps->contextCompatible)
5878       {
5879         aCaps->ffpEnable = Standard_False;
5880       }
5881     }
5882     else if (anArgCase == "-core"
5883           || anArgCase == "-coreprofile")
5884     {
5885       Standard_Boolean toEnable = Standard_True;
5886       if (++anArgIter < theArgNb
5887       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5888       {
5889         --anArgIter;
5890       }
5891       aCaps->contextCompatible = !toEnable;
5892       if (!aCaps->contextCompatible)
5893       {
5894         aCaps->ffpEnable = Standard_False;
5895       }
5896     }
5897     else if (anArgCase == "-stereo"
5898           || anArgCase == "-quadbuffer")
5899     {
5900       Standard_Boolean toEnable = Standard_True;
5901       if (++anArgIter < theArgNb
5902       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5903       {
5904         --anArgIter;
5905       }
5906       aCaps->contextStereo = toEnable;
5907     }
5908     else
5909     {
5910       std::cout << "Error: unknown argument '" << anArg << "'\n";
5911       return 1;
5912     }
5913   }
5914   if (aCaps != &ViewerTest_myDefaultCaps)
5915   {
5916     ViewerTest_myDefaultCaps = *aCaps;
5917   }
5918   return 0;
5919 }
5920
5921 //==============================================================================
5922 //function : VMemGpu
5923 //purpose  :
5924 //==============================================================================
5925
5926 static int VMemGpu (Draw_Interpretor& theDI,
5927                     Standard_Integer  theArgNb,
5928                     const char**      theArgVec)
5929 {
5930   // get the context
5931   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5932   if (aContextAIS.IsNull())
5933   {
5934     std::cerr << "No active view. Please call vinit.\n";
5935     return 1;
5936   }
5937
5938   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5939   if (aDriver.IsNull())
5940   {
5941     std::cerr << "Graphic driver not available.\n";
5942     return 1;
5943   }
5944
5945   Standard_Size aFreeBytes = 0;
5946   TCollection_AsciiString anInfo;
5947   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5948   {
5949     std::cerr << "Information not available.\n";
5950     return 1;
5951   }
5952
5953   if (theArgNb > 1 && *theArgVec[1] == 'f')
5954   {
5955     theDI << Standard_Real (aFreeBytes);
5956   }
5957   else
5958   {
5959     theDI << anInfo;
5960   }
5961
5962   return 0;
5963 }
5964
5965 // ==============================================================================
5966 // function : VReadPixel
5967 // purpose  :
5968 // ==============================================================================
5969 static int VReadPixel (Draw_Interpretor& theDI,
5970                        Standard_Integer  theArgNb,
5971                        const char**      theArgVec)
5972 {
5973   // get the active view
5974   Handle(V3d_View) aView = ViewerTest::CurrentView();
5975   if (aView.IsNull())
5976   {
5977     std::cerr << "No active view. Please call vinit.\n";
5978     return 1;
5979   }
5980   else if (theArgNb < 3)
5981   {
5982     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5983     return 1;
5984   }
5985
5986   Image_Format         aFormat     = Image_Format_RGBA;
5987   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
5988
5989   Standard_Integer aWidth, aHeight;
5990   aView->Window()->Size (aWidth, aHeight);
5991   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5992   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5993   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5994   {
5995     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5996     return 1;
5997   }
5998
5999   Standard_Boolean toShowName = Standard_False;
6000   Standard_Boolean toShowHls  = Standard_False;
6001   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6002   {
6003     TCollection_AsciiString aParam (theArgVec[anIter]);
6004     aParam.LowerCase();
6005     if (aParam == "rgb")
6006     {
6007       aFormat     = Image_Format_RGB;
6008       aBufferType = Graphic3d_BT_RGB;
6009     }
6010     else if (aParam == "hls")
6011     {
6012       aFormat     = Image_Format_RGB;
6013       aBufferType = Graphic3d_BT_RGB;
6014       toShowHls   = Standard_True;
6015     }
6016     else if (aParam == "rgbf")
6017     {
6018       aFormat     = Image_Format_RGBF;
6019       aBufferType = Graphic3d_BT_RGB;
6020     }
6021     else if (aParam == "rgba")
6022     {
6023       aFormat     = Image_Format_RGBA;
6024       aBufferType = Graphic3d_BT_RGBA;
6025     }
6026     else if (aParam == "rgbaf")
6027     {
6028       aFormat     = Image_Format_RGBAF;
6029       aBufferType = Graphic3d_BT_RGBA;
6030     }
6031     else if (aParam == "depth")
6032     {
6033       aFormat     = Image_Format_GrayF;
6034       aBufferType = Graphic3d_BT_Depth;
6035     }
6036     else if (aParam == "name")
6037     {
6038       toShowName = Standard_True;
6039     }
6040   }
6041
6042   Image_PixMap anImage;
6043   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6044   {
6045     std::cerr << "Image allocation failed\n";
6046     return 1;
6047   }
6048   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6049   {
6050     std::cerr << "Image dump failed\n";
6051     return 1;
6052   }
6053
6054   // redirect possible warning messages that could have been added by ToPixMap
6055   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6056   // contaminate result of the command
6057   Standard_CString aWarnLog = theDI.Result();
6058   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6059   {
6060     std::cout << aWarnLog << std::endl;
6061   }
6062   theDI.Reset();
6063
6064   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6065   if (toShowName)
6066   {
6067     if (aBufferType == Graphic3d_BT_RGBA)
6068     {
6069       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6070     }
6071     else
6072     {
6073       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6074     }
6075   }
6076   else
6077   {
6078     switch (aBufferType)
6079     {
6080       default:
6081       case Graphic3d_BT_RGB:
6082       {
6083         if (toShowHls)
6084         {
6085           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6086         }
6087         else
6088         {
6089           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6090         }
6091         break;
6092       }
6093       case Graphic3d_BT_RGBA:
6094       {
6095         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6096         break;
6097       }
6098       case Graphic3d_BT_Depth:
6099       {
6100         theDI << aColor.GetRGB().Red();
6101         break;
6102       }
6103     }
6104   }
6105
6106   return 0;
6107 }
6108
6109 //! Auxiliary presentation for an image plane.
6110 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6111 {
6112 public:
6113   //! Main constructor.
6114   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6115                        const Standard_Real theWidth,
6116                        const Standard_Real theHeight,
6117                        const TCollection_AsciiString& theLabel)
6118   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6119   {
6120     SetDisplayMode (0);
6121     SetHilightMode (1);
6122     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6123     {
6124       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6125       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6126       Graphic3d_MaterialAspect aMat;
6127       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6128       aMat.SetAmbient  (1.0);
6129       aMat.SetDiffuse  (1.0);
6130       aMat.SetSpecular (1.0);
6131       aMat.SetEmissive (1.0);
6132       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6133       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6134       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6135       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6136       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6137       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6138       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6139       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6140       aFillAspect->SetFrontMaterial (aMat);
6141       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6142       aFillAspect->SetTextureMapOn();
6143     }
6144     {
6145       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6146       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6147       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6148       myDrawer->SetTextAspect (aTextAspect);
6149     }
6150     {
6151       const gp_Dir aNorm (0.0, 0.0, 1.0);
6152       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6153       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6154       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6155       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6156       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6157       myTris->AddEdge (1);
6158       myTris->AddEdge (2);
6159       myTris->AddEdge (3);
6160       myTris->AddEdge (3);
6161       myTris->AddEdge (2);
6162       myTris->AddEdge (4);
6163
6164       myRect = new Graphic3d_ArrayOfPolylines (4);
6165       myRect->AddVertex (myTris->Vertice (1));
6166       myRect->AddVertex (myTris->Vertice (3));
6167       myRect->AddVertex (myTris->Vertice (4));
6168       myRect->AddVertex (myTris->Vertice (2));
6169     }
6170   }
6171
6172   //! Returns TRUE for accepted display modes.
6173   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6174
6175   //! Compute presentation.
6176   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6177   {
6178     switch (theMode)
6179     {
6180       case 0:
6181       {
6182         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6183         aGroup->AddPrimitiveArray (myTris);
6184         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6185         aGroup->AddPrimitiveArray (myRect);
6186         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6187         return;
6188       }
6189       case 1:
6190       {
6191         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6192         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6193         aGroup->AddPrimitiveArray (myRect);
6194         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6195         return;
6196       }
6197     }
6198   }
6199
6200   //! Compute selection.
6201   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6202   {
6203     if (theMode == 0)
6204     {
6205       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6206       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6207       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6208       theSel->Add (aSensitive);
6209     }
6210   }
6211
6212 private:
6213   Handle(Graphic3d_ArrayOfTriangles) myTris;
6214   Handle(Graphic3d_ArrayOfPolylines) myRect;
6215   TCollection_AsciiString myLabel;
6216   Standard_Real myWidth;
6217   Standard_Real myHeight;
6218 };
6219
6220 //==============================================================================
6221 //function : VDiffImage
6222 //purpose  : The draw-command compares two images.
6223 //==============================================================================
6224
6225 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6226 {
6227   if (theArgNb < 3)
6228   {
6229     std::cout << "Syntax error: not enough arguments.\n";
6230     return 1;
6231   }
6232
6233   Standard_Integer anArgIter = 1;
6234   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6235   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6236   TCollection_AsciiString aDiffImagePath;
6237   Standard_Real    aTolColor        = -1.0;
6238   Standard_Integer toBlackWhite     = -1;
6239   Standard_Integer isBorderFilterOn = -1;
6240   Standard_Boolean isOldSyntax = Standard_False;
6241   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6242   for (; anArgIter < theArgNb; ++anArgIter)
6243   {
6244     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6245     anArg.LowerCase();
6246     if (anArgIter + 1 < theArgNb
6247      && (anArg == "-toleranceofcolor"
6248       || anArg == "-tolerancecolor"
6249       || anArg == "-tolerance"
6250       || anArg == "-toler"))
6251     {
6252       aTolColor = Atof (theArgVec[++anArgIter]);
6253       if (aTolColor < 0.0 || aTolColor > 1.0)
6254       {
6255         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6256         return 1;
6257       }
6258     }
6259     else if (anArg == "-blackwhite")
6260     {
6261       Standard_Boolean toEnable = Standard_True;
6262       if (anArgIter + 1 < theArgNb
6263        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6264       {
6265         ++anArgIter;
6266       }
6267       toBlackWhite = toEnable ? 1 : 0;
6268     }
6269     else if (anArg == "-borderfilter")
6270     {
6271       Standard_Boolean toEnable = Standard_True;
6272       if (anArgIter + 1 < theArgNb
6273        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6274       {
6275         ++anArgIter;
6276       }
6277       isBorderFilterOn = toEnable ? 1 : 0;
6278     }
6279     else if (anArg == "-exitonclose")
6280     {
6281       Draw_ToExitOnCloseView = true;
6282       if (anArgIter + 1 < theArgNb
6283        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6284       {
6285         ++anArgIter;
6286       }
6287     }
6288     else if (anArg == "-closeonescape"
6289           || anArg == "-closeonesc")
6290     {
6291       Draw_ToCloseViewOnEsc = true;
6292       if (anArgIter + 1 < theArgNb
6293        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6294       {
6295         ++anArgIter;
6296       }
6297     }
6298     else if (anArgIter + 3 < theArgNb
6299           && anArg == "-display")
6300     {
6301       aViewName   = theArgVec[++anArgIter];
6302       aPrsNameRef = theArgVec[++anArgIter];
6303       aPrsNameNew = theArgVec[++anArgIter];
6304       if (anArgIter + 1 < theArgNb
6305       && *theArgVec[anArgIter + 1] != '-')
6306       {
6307         aPrsNameDiff = theArgVec[++anArgIter];
6308       }
6309     }
6310     else if (aTolColor < 0.0
6311           && anArg.IsRealValue())
6312     {
6313       isOldSyntax = Standard_True;
6314       aTolColor = anArg.RealValue();
6315       if (aTolColor < 0.0 || aTolColor > 1.0)
6316       {
6317         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6318         return 1;
6319       }
6320     }
6321     else if (isOldSyntax
6322           && toBlackWhite == -1
6323           && (anArg == "0" || anArg == "1"))
6324     {
6325       toBlackWhite = anArg == "1" ? 1 : 0;
6326     }
6327     else if (isOldSyntax
6328           && isBorderFilterOn == -1
6329           && (anArg == "0" || anArg == "1"))
6330     {
6331       isBorderFilterOn = anArg == "1" ? 1 : 0;
6332     }
6333     else if (aDiffImagePath.IsEmpty())
6334     {
6335       aDiffImagePath = theArgVec[anArgIter];
6336     }
6337     else
6338     {
6339       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6340       return 1;
6341     }
6342   }
6343
6344   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6345   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6346   if (!anImgRef->Load (anImgPathRef))
6347   {
6348     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6349     return 1;
6350   }
6351   if (!anImgNew->Load (anImgPathNew))
6352   {
6353     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6354     return 1;
6355   }
6356
6357   // compare the images
6358   Image_Diff aComparer;
6359   Standard_Integer aDiffColorsNb = -1;
6360   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6361   {
6362     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6363     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6364     aDiffColorsNb = aComparer.Compare();
6365     theDI << aDiffColorsNb << "\n";
6366   }
6367
6368   // save image of difference
6369   Handle(Image_AlienPixMap) aDiff;
6370   if (aDiffColorsNb > 0
6371   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6372   {
6373     aDiff = new Image_AlienPixMap();
6374     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6375     {
6376       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6377       return 1;
6378     }
6379     aComparer.SaveDiffImage (*aDiff);
6380     if (!aDiffImagePath.IsEmpty()
6381      && !aDiff->Save (aDiffImagePath))
6382     {
6383       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6384       return 1;
6385     }
6386   }
6387
6388   if (aViewName.IsEmpty())
6389   {
6390     return 0;
6391   }
6392
6393   ViewerTest_Names aViewNames (aViewName);
6394   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6395   {
6396     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6397     theDI.Eval (aCommand.ToCString());
6398   }
6399
6400   Standard_Integer aPxLeft = 0;
6401   Standard_Integer aPxTop  = 0;
6402   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6403   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6404                               ? int(anImgRef->SizeY() * 2)
6405                               : int(anImgRef->SizeY());
6406   TCollection_AsciiString aDisplayName;
6407   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop,
6408                                                             aWinSizeX, aWinSizeY,
6409                                                             aViewName.ToCString(),
6410                                                             aDisplayName.ToCString());
6411
6412   Standard_Real aRatio = anImgRef->Ratio();
6413   Standard_Real aSizeX = 1.0;
6414   Standard_Real aSizeY = aSizeX / aRatio;
6415   {
6416     OSD_Path aPath (anImgPathRef);
6417     TCollection_AsciiString aLabelRef;
6418     if (!aPath.Name().IsEmpty())
6419     {
6420       aLabelRef = aPath.Name() + aPath.Extension();
6421     }
6422     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6423
6424     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6425     gp_Trsf aTrsfRef;
6426     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6427     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6428     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6429   }
6430   {
6431     OSD_Path aPath (anImgPathNew);
6432     TCollection_AsciiString aLabelNew;
6433     if (!aPath.Name().IsEmpty())
6434     {
6435       aLabelNew = aPath.Name() + aPath.Extension();
6436     }
6437     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6438
6439     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6440     gp_Trsf aTrsfRef;
6441     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6442     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6443     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6444   }
6445   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6446   if (!aDiff.IsNull())
6447   {
6448     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6449     gp_Trsf aTrsfDiff;
6450     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6451     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6452   }
6453   if (!aPrsNameDiff.IsEmpty())
6454   {
6455     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6456   }
6457   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6458   ViewerTest::CurrentView()->FitAll();
6459   return 0;
6460 }
6461
6462 //=======================================================================
6463 //function : VSelect
6464 //purpose  : Emulates different types of selection by mouse:
6465 //           1) single click selection
6466 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6467 //           3) selection with polygon having corners at
6468 //           pixel positions (x1,y1),...,(xn,yn)
6469 //           4) any of these selections with shift button pressed
6470 //=======================================================================
6471 static Standard_Integer VSelect (Draw_Interpretor& di,
6472                                  Standard_Integer argc,
6473                                  const char ** argv)
6474 {
6475   if(argc < 3)
6476   {
6477     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6478     return 1;
6479   }
6480
6481   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6482   if(myAIScontext.IsNull())
6483   {
6484     di << "use 'vinit' command before " << argv[0] << "\n";
6485     return 1;
6486   }
6487
6488   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6489   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6490   TCollection_AsciiString anArg;
6491   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6492   anArg.LowerCase();
6493   if (anArg == "-allowoverlap")
6494   {
6495     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6496       : argc == 7;
6497     if (!isValidated)
6498     {
6499       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6500       return 1;
6501     }
6502
6503     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6504     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6505     aCoordsNb -= 2;
6506   }
6507
6508   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6509   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6510   if(aCoordsNb == 2)
6511   {
6512     if(isShiftSelection)
6513       aCurrentEventManager->ShiftSelect();
6514     else
6515       aCurrentEventManager->Select();
6516   }
6517   else if(aCoordsNb == 4)
6518   {
6519     if(isShiftSelection)
6520       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6521     else
6522       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6523   }
6524   else
6525   {
6526     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6527
6528     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6529       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6530
6531     if(isShiftSelection)
6532       aCurrentEventManager->ShiftSelect(aPolyline);
6533     else
6534       aCurrentEventManager->Select(aPolyline);
6535   }
6536   return 0;
6537 }
6538
6539 //=======================================================================
6540 //function : VMoveTo
6541 //purpose  : Emulates cursor movement to defined pixel position
6542 //=======================================================================
6543 static Standard_Integer VMoveTo (Draw_Interpretor& di,
6544                                 Standard_Integer argc,
6545                                 const char ** argv)
6546 {
6547   if(argc != 3)
6548   {
6549     di << "Usage : " << argv[0] << " x y\n";
6550     return 1;
6551   }
6552
6553   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6554   if(aContext.IsNull())
6555   {
6556     di << "use 'vinit' command before " << argv[0] << "\n";
6557     return 1;
6558   }
6559   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6560   return 0;
6561 }
6562
6563 namespace
6564 {
6565   //! Global map storing all animations registered in ViewerTest.
6566   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6567
6568   //! The animation calling the Draw Harness command.
6569   class ViewerTest_AnimationProc : public AIS_Animation
6570   {
6571   public:
6572
6573     //! Main constructor.
6574     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6575                               Draw_Interpretor* theDI,
6576                               const TCollection_AsciiString& theCommand)
6577     : AIS_Animation (theAnimationName),
6578       myDrawInter(theDI),
6579       myCommand  (theCommand)
6580     {
6581       //
6582     }
6583
6584   protected:
6585
6586     //! Evaluate the command.
6587     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6588     {
6589       TCollection_AsciiString aCmd = myCommand;
6590       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6591       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6592       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6593       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6594       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6595       myDrawInter->Eval (aCmd.ToCString());
6596     }
6597
6598     //! Find the keyword in the command and replace it with value.
6599     //! @return the position of the keyword to pass value
6600     void replace (TCollection_AsciiString&       theCmd,
6601                   const TCollection_AsciiString& theKey,
6602                   const TCollection_AsciiString& theVal)
6603     {
6604       TCollection_AsciiString aCmd (theCmd);
6605       aCmd.LowerCase();
6606       const Standard_Integer aPos = aCmd.Search (theKey);
6607       if (aPos == -1)
6608       {
6609         return;
6610       }
6611
6612       TCollection_AsciiString aPart1, aPart2;
6613       Standard_Integer aPart1To = aPos - 1;
6614       if (aPart1To >= 1
6615        && aPart1To <= theCmd.Length())
6616       {
6617         aPart1 = theCmd.SubString (1, aPart1To);
6618       }
6619
6620       Standard_Integer aPart2From = aPos + theKey.Length();
6621       if (aPart2From >= 1
6622        && aPart2From <= theCmd.Length())
6623       {
6624         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6625       }
6626
6627       theCmd = aPart1 + theVal + aPart2;
6628     }
6629
6630   protected:
6631
6632     Draw_Interpretor*       myDrawInter;
6633     TCollection_AsciiString myCommand;
6634
6635   };
6636
6637   //! Replace the animation with the new one.
6638   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6639                                 Handle(AIS_Animation)&       theAnimation,
6640                                 const Handle(AIS_Animation)& theAnimationNew)
6641   {
6642     theAnimationNew->CopyFrom (theAnimation);
6643     if (!theParentAnimation.IsNull())
6644     {
6645       theParentAnimation->Replace (theAnimation, theAnimationNew);
6646     }
6647     else
6648     {
6649       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6650       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6651     }
6652     theAnimation = theAnimationNew;
6653   }
6654
6655   //! Parse the point.
6656   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6657   {
6658     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6659     if (!anXYZ[0].IsRealValue()
6660      || !anXYZ[1].IsRealValue()
6661      || !anXYZ[2].IsRealValue())
6662     {
6663       return Standard_False;
6664     }
6665
6666     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6667     return Standard_True;
6668   }
6669
6670   //! Parse the quaternion.
6671   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6672   {
6673     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6674     if (!anXYZW[0].IsRealValue()
6675      || !anXYZW[1].IsRealValue()
6676      || !anXYZW[2].IsRealValue()
6677      || !anXYZW[3].IsRealValue())
6678     {
6679       return Standard_False;
6680     }
6681
6682     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6683     return Standard_True;
6684   }
6685
6686   //! Auxiliary class for flipping image upside-down.
6687   class ImageFlipper
6688   {
6689   public:
6690
6691     //! Empty constructor.
6692     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6693
6694     //! Perform flipping.
6695     Standard_Boolean FlipY (Image_PixMap& theImage)
6696     {
6697       if (theImage.IsEmpty()
6698        || theImage.SizeX() == 0
6699        || theImage.SizeY() == 0)
6700       {
6701         return Standard_False;
6702       }
6703
6704       const Standard_Size aRowSize = theImage.SizeRowBytes();
6705       if (myTmp.Size() < aRowSize
6706       && !myTmp.Allocate (aRowSize))
6707       {
6708         return Standard_False;
6709       }
6710
6711       // for odd height middle row should be left as is
6712       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6713       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6714       {
6715         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6716         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6717         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
6718         memcpy (aTop,               aBot,         aRowSize);
6719         memcpy (aBot,               myTmp.Data(), aRowSize);
6720       }
6721       return Standard_True;
6722     }
6723
6724   private:
6725     NCollection_Buffer myTmp;
6726   };
6727
6728 }
6729
6730 //=================================================================================================
6731 //function : VViewParams
6732 //purpose  : Gets or sets AIS View characteristics
6733 //=================================================================================================
6734 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6735 {
6736   Handle(V3d_View) aView = ViewerTest::CurrentView();
6737   if (aView.IsNull())
6738   {
6739     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6740     return 1;
6741   }
6742
6743   Standard_Boolean toSetProj     = Standard_False;
6744   Standard_Boolean toSetUp       = Standard_False;
6745   Standard_Boolean toSetAt       = Standard_False;
6746   Standard_Boolean toSetEye      = Standard_False;
6747   Standard_Boolean toSetScale    = Standard_False;
6748   Standard_Boolean toSetSize     = Standard_False;
6749   Standard_Boolean toSetCenter2d = Standard_False;
6750   Standard_Real    aViewScale = aView->Scale();
6751   Standard_Real    aViewSize  = 1.0;
6752   Graphic3d_Vec2i  aCenter2d;
6753   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6754   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6755   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6756   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6757   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6758   if (theArgsNb == 1)
6759   {
6760     // print all of the available view parameters
6761     char aText[4096];
6762     Sprintf (aText,
6763              "Scale: %g\n"
6764              "Proj:  %12g %12g %12g\n"
6765              "Up:    %12g %12g %12g\n"
6766              "At:    %12g %12g %12g\n"
6767              "Eye:   %12g %12g %12g\n",
6768               aViewScale,
6769               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6770               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6771               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6772               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6773     theDi << aText;
6774     return 0;
6775   }
6776
6777   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6778   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6779   {
6780     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6781     anArg.LowerCase();
6782     if (anUpdateTool.parseRedrawMode (anArg))
6783     {
6784       continue;
6785     }
6786     else if (anArg == "-cmd"
6787           || anArg == "-command"
6788           || anArg == "-args")
6789     {
6790       char aText[4096];
6791       Sprintf (aText,
6792                "-scale %g "
6793                "-proj %g %g %g "
6794                "-up %g %g %g "
6795                "-at %g %g %g\n",
6796                 aViewScale,
6797                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6798                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6799                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6800       theDi << aText;
6801     }
6802     else if (anArg == "-scale"
6803           || anArg == "-size")
6804     {
6805       if (anArgIter + 1 < theArgsNb
6806        && *theArgVec[anArgIter + 1] != '-')
6807       {
6808         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6809         if (aValueArg.IsRealValue())
6810         {
6811           ++anArgIter;
6812           if (anArg == "-scale")
6813           {
6814             toSetScale = Standard_True;
6815             aViewScale = aValueArg.RealValue();
6816           }
6817           else if (anArg == "-size")
6818           {
6819             toSetSize = Standard_True;
6820             aViewSize = aValueArg.RealValue();
6821           }
6822           continue;
6823         }
6824       }
6825       if (anArg == "-scale")
6826       {
6827         theDi << "Scale: " << aView->Scale() << "\n";
6828       }
6829       else if (anArg == "-size")
6830       {
6831         Graphic3d_Vec2d aSizeXY;
6832         aView->Size (aSizeXY.x(), aSizeXY.y());
6833         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6834       }
6835     }
6836     else if (anArg == "-eye"
6837           || anArg == "-at"
6838           || anArg == "-up"
6839           || anArg == "-proj")
6840     {
6841       if (anArgIter + 3 < theArgsNb)
6842       {
6843         gp_XYZ anXYZ;
6844         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6845         {
6846           anArgIter += 3;
6847           if (anArg == "-eye")
6848           {
6849             toSetEye = Standard_True;
6850             aViewEye = anXYZ;
6851           }
6852           else if (anArg == "-at")
6853           {
6854             toSetAt = Standard_True;
6855             aViewAt = anXYZ;
6856           }
6857           else if (anArg == "-up")
6858           {
6859             toSetUp = Standard_True;
6860             aViewUp = anXYZ;
6861           }
6862           else if (anArg == "-proj")
6863           {
6864             toSetProj = Standard_True;
6865             aViewProj = anXYZ;
6866           }
6867           continue;
6868         }
6869       }
6870
6871       if (anArg == "-eye")
6872       {
6873         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6874       }
6875       else if (anArg == "-at")
6876       {
6877         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6878       }
6879       else if (anArg == "-up")
6880       {
6881         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6882       }
6883       else if (anArg == "-proj")
6884       {
6885         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6886       }
6887     }
6888     else if (anArg == "-center")
6889     {
6890       if (anArgIter + 2 < theArgsNb)
6891       {
6892         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6893         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6894         if (anX.IsIntegerValue()
6895          && anY.IsIntegerValue())
6896         {
6897           toSetCenter2d = Standard_True;
6898           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6899         }
6900       }
6901     }
6902     else
6903     {
6904       std::cout << "Syntax error at '" << anArg << "'\n";
6905       return 1;
6906     }
6907   }
6908
6909   // change view parameters in proper order
6910   if (toSetScale)
6911   {
6912     aView->SetScale (aViewScale);
6913   }
6914   if (toSetSize)
6915   {
6916     aView->SetSize (aViewSize);
6917   }
6918   if (toSetEye)
6919   {
6920     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6921   }
6922   if (toSetAt)
6923   {
6924     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6925   }
6926   if (toSetProj)
6927   {
6928     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6929   }
6930   if (toSetUp)
6931   {
6932     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6933   }
6934   if (toSetCenter2d)
6935   {
6936     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6937   }
6938
6939   return 0;
6940 }
6941
6942 //==============================================================================
6943 //function : VAnimation
6944 //purpose  :
6945 //==============================================================================
6946 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6947                                     Standard_Integer  theArgNb,
6948                                     const char**      theArgVec)
6949 {
6950   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6951   if (theArgNb < 2)
6952   {
6953     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6954          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6955     {
6956       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6957     }
6958     return 0;
6959   }
6960   if (aCtx.IsNull())
6961   {
6962     std::cout << "Error: no active view\n";
6963     return 1;
6964   }
6965
6966   Standard_Integer anArgIter = 1;
6967   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6968   if (aNameArg.IsEmpty())
6969   {
6970     std::cout << "Syntax error: animation name is not defined.\n";
6971     return 1;
6972   }
6973
6974   TCollection_AsciiString aNameArgLower = aNameArg;
6975   aNameArgLower.LowerCase();
6976   if (aNameArgLower == "-reset"
6977    || aNameArgLower == "-clear")
6978   {
6979     ViewerTest_AnimationTimelineMap.Clear();
6980     return 0;
6981   }
6982   else if (aNameArg.Value (1) == '-')
6983   {
6984     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6985     return 1;
6986   }
6987
6988   const char* aNameSplitter = "/";
6989   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6990   if (aSplitPos == -1)
6991   {
6992     aNameSplitter = ".";
6993     aSplitPos = aNameArg.Search (aNameSplitter);
6994   }
6995
6996   // find existing or create a new animation by specified name within syntax "parent.child".
6997   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6998   for (; !aNameArg.IsEmpty();)
6999   {
7000     TCollection_AsciiString aNameParent;
7001     if (aSplitPos != -1)
7002     {
7003       if (aSplitPos == aNameArg.Length())
7004       {
7005         std::cout << "Syntax error: animation name is not defined.\n";
7006         return 1;
7007       }
7008
7009       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7010       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7011
7012       aSplitPos = aNameArg.Search (aNameSplitter);
7013     }
7014     else
7015     {
7016       aNameParent = aNameArg;
7017       aNameArg.Clear();
7018     }
7019
7020     if (anAnimation.IsNull())
7021     {
7022       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7023       {
7024         anAnimation = new AIS_Animation (aNameParent);
7025         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7026       }
7027       aRootAnimation = anAnimation;
7028     }
7029     else
7030     {
7031       aParentAnimation = anAnimation;
7032       anAnimation = aParentAnimation->Find (aNameParent);
7033       if (anAnimation.IsNull())
7034       {
7035         anAnimation = new AIS_Animation (aNameParent);
7036         aParentAnimation->Add (anAnimation);
7037       }
7038     }
7039   }
7040
7041   if (anArgIter >= theArgNb)
7042   {
7043     // just print the list of children
7044     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7045     {
7046       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7047     }
7048     return 0;
7049   }
7050
7051   // animation parameters
7052   Standard_Boolean toPlay = Standard_False;
7053   Standard_Real aPlaySpeed     = 1.0;
7054   Standard_Real aPlayStartTime = anAnimation->StartPts();
7055   Standard_Real aPlayDuration  = anAnimation->Duration();
7056   Standard_Boolean isFreeCamera = Standard_False;
7057   Standard_Boolean isLockLoop   = Standard_False;
7058
7059   // video recording parameters
7060   TCollection_AsciiString aRecFile;
7061   Image_VideoParams aRecParams;
7062
7063   Handle(V3d_View) aView = ViewerTest::CurrentView();
7064   for (; anArgIter < theArgNb; ++anArgIter)
7065   {
7066     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7067     anArg.LowerCase();
7068     // general options
7069     if (anArg == "-reset"
7070      || anArg == "-clear")
7071     {
7072       anAnimation->Clear();
7073     }
7074     else if (anArg == "-remove"
7075           || anArg == "-del"
7076           || anArg == "-delete")
7077     {
7078       if (!aParentAnimation.IsNull())
7079       {
7080         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7081       }
7082       else
7083       {
7084         aParentAnimation->Remove (anAnimation);
7085       }
7086     }
7087     // playback options
7088     else if (anArg == "-play")
7089     {
7090       toPlay = Standard_True;
7091       if (++anArgIter < theArgNb)
7092       {
7093         if (*theArgVec[anArgIter] == '-')
7094         {
7095           --anArgIter;
7096           continue;
7097         }
7098         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7099
7100         if (++anArgIter < theArgNb)
7101         {
7102           if (*theArgVec[anArgIter] == '-')
7103           {
7104             --anArgIter;
7105             continue;
7106           }
7107           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7108         }
7109       }
7110     }
7111     else if (anArg == "-resume")
7112     {
7113       toPlay = Standard_True;
7114       aPlayStartTime = anAnimation->ElapsedTime();
7115       if (++anArgIter < theArgNb)
7116       {
7117         if (*theArgVec[anArgIter] == '-')
7118         {
7119           --anArgIter;
7120           continue;
7121         }
7122
7123         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7124       }
7125     }
7126     else if (anArg == "-playspeed"
7127           || anArg == "-speed")
7128     {
7129       if (++anArgIter >= theArgNb)
7130       {
7131         std::cout << "Syntax error at " << anArg << ".\n";
7132         return 1;
7133       }
7134       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7135     }
7136     else if (anArg == "-lock"
7137           || anArg == "-lockloop"
7138           || anArg == "-playlockloop")
7139     {
7140       isLockLoop = Standard_True;
7141     }
7142     else if (anArg == "-freecamera"
7143           || anArg == "-playfreecamera"
7144           || anArg == "-freelook")
7145     {
7146       isFreeCamera = Standard_True;
7147     }
7148     // video recodring options
7149     else if (anArg == "-rec"
7150           || anArg == "-record")
7151     {
7152       if (++anArgIter >= theArgNb)
7153       {
7154         std::cout << "Syntax error at " << anArg << ".\n";
7155         return 1;
7156       }
7157
7158       aRecFile = theArgVec[anArgIter];
7159       if (aRecParams.FpsNum <= 0)
7160       {
7161         aRecParams.FpsNum = 24;
7162       }
7163
7164       if (anArgIter + 2 < theArgNb
7165       && *theArgVec[anArgIter + 1] != '-'
7166       && *theArgVec[anArgIter + 2] != '-')
7167       {
7168         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7169         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7170         if (aWidthArg .IsIntegerValue()
7171          && aHeightArg.IsIntegerValue())
7172         {
7173           aRecParams.Width  = aWidthArg .IntegerValue();
7174           aRecParams.Height = aHeightArg.IntegerValue();
7175           anArgIter += 2;
7176         }
7177       }
7178     }
7179     else if (anArg == "-fps")
7180     {
7181       if (++anArgIter >= theArgNb)
7182       {
7183         std::cout << "Syntax error at " << anArg << ".\n";
7184         return 1;
7185       }
7186
7187       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7188       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7189       if (aSplitIndex == 0)
7190       {
7191         aRecParams.FpsNum = aFpsArg.IntegerValue();
7192       }
7193       else
7194       {
7195         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7196         aFpsArg.Split (aFpsArg.Length() - 1);
7197         const TCollection_AsciiString aNumStr = aFpsArg;
7198         aRecParams.FpsNum = aNumStr.IntegerValue();
7199         aRecParams.FpsDen = aDenStr.IntegerValue();
7200         if (aRecParams.FpsDen < 1)
7201         {
7202           std::cout << "Syntax error at " << anArg << ".\n";
7203           return 1;
7204         }
7205       }
7206     }
7207     else if (anArg == "-format")
7208     {
7209       if (++anArgIter >= theArgNb)
7210       {
7211         std::cout << "Syntax error at " << anArg << ".\n";
7212         return 1;
7213       }
7214       aRecParams.Format = theArgVec[anArgIter];
7215     }
7216     else if (anArg == "-pix_fmt"
7217           || anArg == "-pixfmt"
7218           || anArg == "-pixelformat")
7219     {
7220       if (++anArgIter >= theArgNb)
7221       {
7222         std::cout << "Syntax error at " << anArg << ".\n";
7223         return 1;
7224       }
7225       aRecParams.PixelFormat = theArgVec[anArgIter];
7226     }
7227     else if (anArg == "-codec"
7228           || anArg == "-vcodec"
7229           || anArg == "-videocodec")
7230     {
7231       if (++anArgIter >= theArgNb)
7232       {
7233         std::cout << "Syntax error at " << anArg << ".\n";
7234         return 1;
7235       }
7236       aRecParams.VideoCodec = theArgVec[anArgIter];
7237     }
7238     else if (anArg == "-crf"
7239           || anArg == "-preset"
7240           || anArg == "-qp")
7241     {
7242       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7243       if (++anArgIter >= theArgNb)
7244       {
7245         std::cout << "Syntax error at " << anArg << ".\n";
7246         return 1;
7247       }
7248
7249       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7250     }
7251     // animation definition options
7252     else if (anArg == "-start"
7253           || anArg == "-starttime"
7254           || anArg == "-startpts")
7255     {
7256       if (++anArgIter >= theArgNb)
7257       {
7258         std::cout << "Syntax error at " << anArg << ".\n";
7259         return 1;
7260       }
7261
7262       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7263       aRootAnimation->UpdateTotalDuration();
7264     }
7265     else if (anArg == "-end"
7266           || anArg == "-endtime"
7267           || anArg == "-endpts")
7268     {
7269       if (++anArgIter >= theArgNb)
7270       {
7271         std::cout << "Syntax error at " << anArg << ".\n";
7272         return 1;
7273       }
7274
7275       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7276       aRootAnimation->UpdateTotalDuration();
7277     }
7278     else if (anArg == "-dur"
7279           || anArg == "-duration")
7280     {
7281       if (++anArgIter >= theArgNb)
7282       {
7283         std::cout << "Syntax error at " << anArg << ".\n";
7284         return 1;
7285       }
7286
7287       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7288       aRootAnimation->UpdateTotalDuration();
7289     }
7290     else if (anArg == "-command"
7291           || anArg == "-cmd"
7292           || anArg == "-invoke"
7293           || anArg == "-eval"
7294           || anArg == "-proc")
7295     {
7296       if (++anArgIter >= theArgNb)
7297       {
7298         std::cout << "Syntax error at " << anArg << ".\n";
7299         return 1;
7300       }
7301
7302       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7303       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7304     }
7305     else if (anArg == "-objecttrsf"
7306           || anArg == "-objectransformation"
7307           || anArg == "-objtransformation"
7308           || anArg == "-objtrsf"
7309           || anArg == "-object"
7310           || anArg == "-obj")
7311     {
7312       if (++anArgIter >= theArgNb)
7313       {
7314         std::cout << "Syntax error at " << anArg << ".\n";
7315         return 1;
7316       }
7317
7318       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7319       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7320       if (!aMapOfAIS.IsBound2 (anObjName))
7321       {
7322         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7323         return 1;
7324       }
7325
7326       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
7327       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7328       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7329       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7330       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7331       Standard_Boolean isTrsfSet = Standard_False;
7332       Standard_Integer aTrsfArgIter = anArgIter + 1;
7333       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7334       {
7335         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7336         aTrsfArg.LowerCase();
7337         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7338         if (aTrsfArg.StartsWith ("-rotation")
7339          || aTrsfArg.StartsWith ("-rot"))
7340         {
7341           isTrsfSet = Standard_True;
7342           if (aTrsfArgIter + 4 >= theArgNb
7343           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7344           {
7345             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7346             return 1;
7347           }
7348           aTrsfArgIter += 4;
7349         }
7350         else if (aTrsfArg.StartsWith ("-location")
7351               || aTrsfArg.StartsWith ("-loc"))
7352         {
7353           isTrsfSet = Standard_True;
7354           if (aTrsfArgIter + 3 >= theArgNb
7355           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7356           {
7357             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7358             return 1;
7359           }
7360           aTrsfArgIter += 3;
7361         }
7362         else if (aTrsfArg.StartsWith ("-scale"))
7363         {
7364           isTrsfSet = Standard_True;
7365           if (++aTrsfArgIter >= theArgNb)
7366           {
7367             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7368             return 1;
7369           }
7370
7371           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7372           if (!aScaleStr.IsRealValue())
7373           {
7374             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7375             return 1;
7376           }
7377           aScales[anIndex] = aScaleStr.RealValue();
7378         }
7379         else
7380         {
7381           anArgIter = aTrsfArgIter - 1;
7382           break;
7383         }
7384       }
7385       if (!isTrsfSet)
7386       {
7387         std::cout << "Syntax error at " << anArg << ".\n";
7388         return 1;
7389       }
7390       else if (aTrsfArgIter >= theArgNb)
7391       {
7392         anArgIter = theArgNb;
7393       }
7394
7395       aTrsfs[0].SetRotation        (aRotQuats[0]);
7396       aTrsfs[1].SetRotation        (aRotQuats[1]);
7397       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7398       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7399       aTrsfs[0].SetScaleFactor     (aScales[0]);
7400       aTrsfs[1].SetScaleFactor     (aScales[1]);
7401
7402       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7403       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7404     }
7405     else if (anArg == "-viewtrsf"
7406           || anArg == "-view")
7407     {
7408       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7409       if (aCamAnimation.IsNull())
7410       {
7411         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7412         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7413       }
7414
7415       Handle(Graphic3d_Camera) aCams[2] =
7416       {
7417         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7418         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7419       };
7420
7421       Standard_Boolean isTrsfSet = Standard_False;
7422       Standard_Integer aViewArgIter = anArgIter + 1;
7423       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7424       {
7425         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7426         aViewArg.LowerCase();
7427         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7428         if (aViewArg.StartsWith ("-scale"))
7429         {
7430           isTrsfSet = Standard_True;
7431           if (++aViewArgIter >= theArgNb)
7432           {
7433             std::cout << "Syntax error at " << anArg << ".\n";
7434             return 1;
7435           }
7436
7437           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7438           if (!aScaleStr.IsRealValue())
7439           {
7440             std::cout << "Syntax error at " << aViewArg << ".\n";
7441             return 1;
7442           }
7443           Standard_Real aScale = aScaleStr.RealValue();
7444           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7445           aCams[anIndex]->SetScale (aScale);
7446         }
7447         else if (aViewArg.StartsWith ("-eye")
7448               || aViewArg.StartsWith ("-center")
7449               || aViewArg.StartsWith ("-at")
7450               || aViewArg.StartsWith ("-up"))
7451         {
7452           isTrsfSet = Standard_True;
7453           gp_XYZ anXYZ;
7454           if (aViewArgIter + 3 >= theArgNb
7455           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7456           {
7457             std::cout << "Syntax error at " << aViewArg << ".\n";
7458             return 1;
7459           }
7460           aViewArgIter += 3;
7461
7462           if (aViewArg.StartsWith ("-eye"))
7463           {
7464             aCams[anIndex]->SetEye (anXYZ);
7465           }
7466           else if (aViewArg.StartsWith ("-center")
7467                 || aViewArg.StartsWith ("-at"))
7468           {
7469             aCams[anIndex]->SetCenter (anXYZ);
7470           }
7471           else if (aViewArg.StartsWith ("-up"))
7472           {
7473             aCams[anIndex]->SetUp (anXYZ);
7474           }
7475         }
7476         else
7477         {
7478           anArgIter = aViewArgIter - 1;
7479           break;
7480         }
7481       }
7482       if (!isTrsfSet)
7483       {
7484         std::cout << "Syntax error at " << anArg << ".\n";
7485         return 1;
7486       }
7487       else if (aViewArgIter >= theArgNb)
7488       {
7489         anArgIter = theArgNb;
7490       }
7491
7492       aCamAnimation->SetCameraStart(aCams[0]);
7493       aCamAnimation->SetCameraEnd  (aCams[1]);
7494     }
7495     else
7496     {
7497       std::cout << "Syntax error at " << anArg << ".\n";
7498       return 1;
7499     }
7500   }
7501
7502   if (!toPlay && aRecFile.IsEmpty())
7503   {
7504     return 0;
7505   }
7506
7507   // Start animation timeline and process frame updating.
7508   TheIsAnimating = Standard_True;
7509   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7510   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7511   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7512   if (isFreeCamera)
7513   {
7514     aView->Camera()->Copy (aCameraBack);
7515   }
7516
7517   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7518   if (aRecParams.FpsNum <= 0)
7519   {
7520     while (!anAnimation->IsStopped())
7521     {
7522       aCameraBack->Copy (aView->Camera());
7523       const Standard_Real aPts = anAnimation->UpdateTimer();
7524       if (isFreeCamera)
7525       {
7526         aView->Camera()->Copy (aCameraBack);
7527       }
7528
7529       if (aPts >= anUpperPts)
7530       {
7531         anAnimation->Pause();
7532         break;
7533       }
7534
7535       if (aView->IsInvalidated())
7536       {
7537         aView->Redraw();
7538       }
7539       else
7540       {
7541         aView->RedrawImmediate();
7542       }
7543
7544       if (!isLockLoop)
7545       {
7546         // handle user events
7547         theDI.Eval ("after 1 set waiter 1");
7548         theDI.Eval ("vwait waiter");
7549       }
7550       if (!TheIsAnimating)
7551       {
7552         anAnimation->Pause();
7553         theDI << aPts;
7554         break;
7555       }
7556     }
7557
7558     if (aView->IsInvalidated())
7559     {
7560       aView->Redraw();
7561     }
7562     else
7563     {
7564       aView->RedrawImmediate();
7565     }
7566   }
7567   else
7568   {
7569     OSD_Timer aPerfTimer;
7570     aPerfTimer.Start();
7571
7572     Handle(Image_VideoRecorder) aRecorder;
7573     ImageFlipper aFlipper;
7574     Handle(Draw_ProgressIndicator) aProgress;
7575     if (!aRecFile.IsEmpty())
7576     {
7577       if (aRecParams.Width  <= 0
7578        || aRecParams.Height <= 0)
7579       {
7580         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7581       }
7582
7583       aRecorder = new Image_VideoRecorder();
7584       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7585       {
7586         std::cout << "Error: failed to open video file for recording\n";
7587         return 0;
7588       }
7589
7590       aProgress = new Draw_ProgressIndicator (theDI, 1);
7591     }
7592
7593     // Manage frame-rated animation here
7594     Standard_Real aPts = aPlayStartTime;
7595     int64_t aNbFrames = 0;
7596     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7597     Standard_Integer aSecondsProgress = 0;
7598     for (; aPts <= anUpperPts && aPSentry.More();)
7599     {
7600       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
7601       aPts = aPlayStartTime + aRecPts;
7602       ++aNbFrames;
7603       if (!anAnimation->Update (aPts))
7604       {
7605         break;
7606       }
7607
7608       if (!aRecorder.IsNull())
7609       {
7610         V3d_ImageDumpOptions aDumpParams;
7611         aDumpParams.Width          = aRecParams.Width;
7612         aDumpParams.Height         = aRecParams.Height;
7613         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
7614         aDumpParams.StereoOptions  = V3d_SDO_MONO;
7615         aDumpParams.ToAdjustAspect = Standard_True;
7616         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
7617         {
7618           std::cout << "Error: view dump is failed!\n";
7619           return 0;
7620         }
7621         aFlipper.FlipY (aRecorder->ChangeFrame());
7622         if (!aRecorder->PushFrame())
7623         {
7624           return 0;
7625         }
7626       }
7627       else
7628       {
7629         aView->Redraw();
7630       }
7631
7632       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7633       {
7634         aPSentry.Next();
7635         ++aSecondsProgress;
7636       }
7637     }
7638
7639     aPerfTimer.Stop();
7640     anAnimation->Stop();
7641     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7642     theDI << "Average FPS: " << aRecFps << "\n"
7643           << "Nb. Frames: "  << Standard_Real(aNbFrames);
7644
7645     aView->Redraw();
7646   }
7647
7648   aView->SetImmediateUpdate (wasImmediateUpdate);
7649   TheIsAnimating = Standard_False;
7650   return 0;
7651 }
7652
7653
7654 //=======================================================================
7655 //function : VChangeSelected
7656 //purpose  : Adds the shape to selection or remove one from it
7657 //=======================================================================
7658 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7659                                 Standard_Integer argc,
7660                                 const char ** argv)
7661 {
7662   if(argc != 2)
7663   {
7664     di<<"Usage : " << argv[0] << " shape \n";
7665     return 1;
7666   }
7667   //get AIS_Shape:
7668   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7669   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
7670   TCollection_AsciiString aName(argv[1]);
7671   Handle(AIS_InteractiveObject) anAISObject;
7672
7673   if(!aMap.IsBound2(aName))
7674   {
7675     di<<"Use 'vdisplay' before";
7676     return 1;
7677   }
7678   else
7679   {
7680     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
7681     if(anAISObject.IsNull()){
7682       di<<"No interactive object \n";
7683       return 1;
7684     }
7685
7686     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
7687   }
7688   return 0;
7689 }
7690
7691 //=======================================================================
7692 //function : VNbSelected
7693 //purpose  : Returns number of selected objects
7694 //=======================================================================
7695 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7696                                 Standard_Integer argc,
7697                                 const char ** argv)
7698 {
7699   if(argc != 1)
7700   {
7701     di << "Usage : " << argv[0] << "\n";
7702     return 1;
7703   }
7704   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7705   if(aContext.IsNull())
7706   {
7707     di << "use 'vinit' command before " << argv[0] << "\n";
7708     return 1;
7709   }
7710   di << aContext->NbSelected() << "\n";
7711   return 0;
7712 }
7713
7714 //=======================================================================
7715 //function : VPurgeDisplay
7716 //purpose  : Switches altialiasing on or off
7717 //=======================================================================
7718 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7719                                 Standard_Integer argc,
7720                                 const char ** argv)
7721 {
7722   if (argc > 1)
7723   {
7724     di << "Usage : " << argv[0] << "\n";
7725     return 1;
7726   }
7727   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7728   if (aContext.IsNull())
7729   {
7730     di << "use 'vinit' command before " << argv[0] << "\n";
7731     return 1;
7732   }
7733
7734   di << aContext->PurgeDisplay() << "\n";
7735   return 0;
7736 }
7737
7738 //=======================================================================
7739 //function : VSetViewSize
7740 //purpose  :
7741 //=======================================================================
7742 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7743                                 Standard_Integer argc,
7744                                 const char ** argv)
7745 {
7746   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7747   if(aContext.IsNull())
7748   {
7749     di << "use 'vinit' command before " << argv[0] << "\n";
7750     return 1;
7751   }
7752   if(argc != 2)
7753   {
7754     di<<"Usage : " << argv[0] << " Size\n";
7755     return 1;
7756   }
7757   Standard_Real aSize = Draw::Atof (argv[1]);
7758   if (aSize <= 0.)
7759   {
7760     di<<"Bad Size value  : " << aSize << "\n";
7761     return 1;
7762   }
7763
7764   Handle(V3d_View) aView = ViewerTest::CurrentView();
7765   aView->SetSize(aSize);
7766   return 0;
7767 }
7768
7769 //=======================================================================
7770 //function : VMoveView
7771 //purpose  :
7772 //=======================================================================
7773 static Standard_Integer VMoveView (Draw_Interpretor& di,
7774                                 Standard_Integer argc,
7775                                 const char ** argv)
7776 {
7777   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7778   if(aContext.IsNull())
7779   {
7780     di << "use 'vinit' command before " << argv[0] << "\n";
7781     return 1;
7782   }
7783   if(argc < 4 || argc > 5)
7784   {
7785     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7786     return 1;
7787   }
7788   Standard_Real Dx = Draw::Atof (argv[1]);
7789   Standard_Real Dy = Draw::Atof (argv[2]);
7790   Standard_Real Dz = Draw::Atof (argv[3]);
7791   Standard_Boolean aStart = Standard_True;
7792   if (argc == 5)
7793   {
7794       aStart = (Draw::Atoi (argv[4]) > 0);
7795   }
7796
7797   Handle(V3d_View) aView = ViewerTest::CurrentView();
7798   aView->Move(Dx,Dy,Dz,aStart);
7799   return 0;
7800 }
7801
7802 //=======================================================================
7803 //function : VTranslateView
7804 //purpose  :
7805 //=======================================================================
7806 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7807                                 Standard_Integer argc,
7808                                 const char ** argv)
7809 {
7810   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7811   if(aContext.IsNull())
7812   {
7813     di << "use 'vinit' command before " << argv[0] << "\n";
7814     return 1;
7815   }
7816   if(argc < 4 || argc > 5)
7817   {
7818     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7819     return 1;
7820   }
7821   Standard_Real Dx = Draw::Atof (argv[1]);
7822   Standard_Real Dy = Draw::Atof (argv[2]);
7823   Standard_Real Dz = Draw::Atof (argv[3]);
7824   Standard_Boolean aStart = Standard_True;
7825   if (argc == 5)
7826   {
7827       aStart = (Draw::Atoi (argv[4]) > 0);
7828   }
7829
7830   Handle(V3d_View) aView = ViewerTest::CurrentView();
7831   aView->Translate(Dx,Dy,Dz,aStart);
7832   return 0;
7833 }
7834
7835 //=======================================================================
7836 //function : VTurnView
7837 //purpose  :
7838 //=======================================================================
7839 static Standard_Integer VTurnView (Draw_Interpretor& di,
7840                                 Standard_Integer argc,
7841                                 const char ** argv)
7842 {
7843   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7844   if(aContext.IsNull()) {
7845     di << "use 'vinit' command before " << argv[0] << "\n";
7846     return 1;
7847   }
7848   if(argc < 4 || argc > 5){
7849     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7850     return 1;
7851   }
7852   Standard_Real Ax = Draw::Atof (argv[1]);
7853   Standard_Real Ay = Draw::Atof (argv[2]);
7854   Standard_Real Az = Draw::Atof (argv[3]);
7855   Standard_Boolean aStart = Standard_True;
7856   if (argc == 5)
7857   {
7858       aStart = (Draw::Atoi (argv[4]) > 0);
7859   }
7860
7861   Handle(V3d_View) aView = ViewerTest::CurrentView();
7862   aView->Turn(Ax,Ay,Az,aStart);
7863   return 0;
7864 }
7865
7866 //==============================================================================
7867 //function : VTextureEnv
7868 //purpose  : ENables or disables environment mapping
7869 //==============================================================================
7870 class OCC_TextureEnv : public Graphic3d_TextureEnv
7871 {
7872 public:
7873   OCC_TextureEnv(const Standard_CString FileName);
7874   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7875   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7876                             const Standard_Boolean theModulateFlag,
7877                             const Graphic3d_TypeOfTextureFilter theFilter,
7878                             const Standard_ShortReal theXScale,
7879                             const Standard_ShortReal theYScale,
7880                             const Standard_ShortReal theXShift,
7881                             const Standard_ShortReal theYShift,
7882                             const Standard_ShortReal theAngle);
7883   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7884 };
7885 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7886
7887 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7888   : Graphic3d_TextureEnv(theFileName)
7889 {
7890 }
7891
7892 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7893   : Graphic3d_TextureEnv(theTexId)
7894 {
7895 }
7896
7897 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7898                                           const Standard_Boolean theModulateFlag,
7899                                           const Graphic3d_TypeOfTextureFilter theFilter,
7900                                           const Standard_ShortReal theXScale,
7901                                           const Standard_ShortReal theYScale,
7902                                           const Standard_ShortReal theXShift,
7903                                           const Standard_ShortReal theYShift,
7904                                           const Standard_ShortReal theAngle)
7905 {
7906   myParams->SetRepeat     (theRepeatFlag);
7907   myParams->SetModulate   (theModulateFlag);
7908   myParams->SetFilter     (theFilter);
7909   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7910   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7911   myParams->SetRotation   (theAngle);
7912 }
7913
7914 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7915 {
7916   // get the active view
7917   Handle(V3d_View) aView = ViewerTest::CurrentView();
7918   if (aView.IsNull())
7919   {
7920     std::cerr << "No active view. Please call vinit.\n";
7921     return 1;
7922   }
7923
7924   // Checking the input arguments
7925   Standard_Boolean anEnableFlag = Standard_False;
7926   Standard_Boolean isOk         = theArgNb >= 2;
7927   if (isOk)
7928   {
7929     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7930     anEnableFlag = anEnableOpt.IsEqual("on");
7931     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7932   }
7933   if (anEnableFlag)
7934   {
7935     isOk = (theArgNb == 3 || theArgNb == 11);
7936     if (isOk)
7937     {
7938       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7939       isOk = (!aTextureOpt.IsIntegerValue() ||
7940              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7941
7942       if (isOk && theArgNb == 11)
7943       {
7944         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7945                                 aModulateOpt(theArgVec[4]),
7946                                 aFilterOpt  (theArgVec[5]),
7947                                 aSScaleOpt  (theArgVec[6]),
7948                                 aTScaleOpt  (theArgVec[7]),
7949                                 aSTransOpt  (theArgVec[8]),
7950                                 aTTransOpt  (theArgVec[9]),
7951                                 anAngleOpt  (theArgVec[10]);
7952         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7953                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7954                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7955                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7956                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7957                 anAngleOpt.IsRealValue());
7958       }
7959     }
7960   }
7961
7962   if (!isOk)
7963   {
7964     std::cerr << "Usage :" << std::endl;
7965     std::cerr << theArgVec[0] << " off" << std::endl;
7966     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;
7967     return 1;
7968   }
7969
7970   if (anEnableFlag)
7971   {
7972     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7973     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7974                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7975                                      new OCC_TextureEnv(theArgVec[2]);
7976
7977     if (theArgNb == 11)
7978     {
7979       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7980       aTexEnv->SetTextureParameters(
7981         aRepeatOpt.  IsEqual("repeat"),
7982         aModulateOpt.IsEqual("modulate"),
7983         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7984                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7985                                                                            Graphic3d_TOTF_TRILINEAR,
7986         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7987         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7988         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7989         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7990         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7991         );
7992     }
7993     aView->SetTextureEnv(aTexEnv);
7994   }
7995   else // Disabling environment mapping
7996   {
7997     Handle(Graphic3d_TextureEnv) aTexture;
7998     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7999   }
8000
8001   aView->Redraw();
8002   return 0;
8003 }
8004
8005 namespace
8006 {
8007   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8008
8009   //! Remove registered clipping plane from all views and objects.
8010   static void removePlane (MapOfPlanes& theRegPlanes,
8011                            const TCollection_AsciiString& theName)
8012   {
8013     Handle(Graphic3d_ClipPlane) aClipPlane;
8014     if (!theRegPlanes.Find (theName, aClipPlane))
8015     {
8016       std::cout << "Warning: no such plane.\n";
8017       return;
8018     }
8019
8020     theRegPlanes.UnBind (theName);
8021     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8022          anIObjIt.More(); anIObjIt.Next())
8023     {
8024       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
8025       aPrs->RemoveClipPlane (aClipPlane);
8026     }
8027
8028     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8029          aViewIt.More(); aViewIt.Next())
8030     {
8031       const Handle(V3d_View)& aView = aViewIt.Key2();
8032       aView->RemoveClipPlane(aClipPlane);
8033     }
8034
8035     ViewerTest::RedrawAllViews();
8036   }
8037 }
8038
8039 //===============================================================================================
8040 //function : VClipPlane
8041 //purpose  :
8042 //===============================================================================================
8043 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8044 {
8045   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8046   static MapOfPlanes aRegPlanes;
8047
8048   if (theArgsNb < 2)
8049   {
8050     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8051     {
8052       theDi << aPlaneIter.Key() << " ";
8053     }
8054     return 0;
8055   }
8056
8057   TCollection_AsciiString aCommand (theArgVec[1]);
8058   aCommand.LowerCase();
8059   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8060   if (anActiveView.IsNull())
8061   {
8062     std::cout << "Error: no active view.\n";
8063     return 1;
8064   }
8065
8066   // print maximum number of planes for current viewer
8067   if (aCommand == "-maxplanes"
8068    || aCommand == "maxplanes")
8069   {
8070     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8071           << " plane slots provided by driver.\n";
8072     return 0;
8073   }
8074
8075   // create / delete plane instance
8076   if (aCommand == "-create"
8077    || aCommand == "create"
8078    || aCommand == "-delete"
8079    || aCommand == "delete"
8080    || aCommand == "-clone"
8081    || aCommand == "clone")
8082   {
8083     if (theArgsNb < 3)
8084     {
8085       std::cout << "Syntax error: plane name is required.\n";
8086       return 1;
8087     }
8088
8089     Standard_Boolean toCreate = aCommand == "-create"
8090                              || aCommand == "create";
8091     Standard_Boolean toClone  = aCommand == "-clone"
8092                              || aCommand == "clone";
8093     Standard_Boolean toDelete = aCommand == "-delete"
8094                              || aCommand == "delete";
8095     TCollection_AsciiString aPlane (theArgVec[2]);
8096
8097     if (toCreate)
8098     {
8099       if (aRegPlanes.IsBound (aPlane))
8100       {
8101         std::cout << "Warning: existing plane has been overridden.\n";
8102         toDelete = true;
8103       }
8104       else
8105       {
8106         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8107         return 0;
8108       }
8109     }
8110     else if (toClone) // toClone
8111     {
8112       if (!aRegPlanes.IsBound (aPlane))
8113       {
8114         std::cout << "Error: no such plane.\n";
8115         return 1;
8116       }
8117       else if (theArgsNb < 4)
8118       {
8119         std::cout << "Syntax error: enter name for new plane.\n";
8120         return 1;
8121       }
8122
8123       TCollection_AsciiString aClone (theArgVec[3]);
8124       if (aRegPlanes.IsBound (aClone))
8125       {
8126         std::cout << "Error: plane name is in use.\n";
8127         return 1;
8128       }
8129
8130       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8131
8132       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8133       return 0;
8134     }
8135
8136     if (toDelete)
8137     {
8138       if (aPlane == "ALL"
8139        || aPlane == "all"
8140        || aPlane == "*")
8141       {
8142         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8143         {
8144           aPlane = aPlaneIter.Key();
8145           removePlane (aRegPlanes, aPlane);
8146           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8147         }
8148       }
8149       else
8150       {
8151         removePlane (aRegPlanes, aPlane);
8152       }
8153     }
8154
8155     if (toCreate)
8156     {
8157       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8158     }
8159     return 0;
8160   }
8161
8162   // set / unset plane command
8163   if (aCommand == "set"
8164    || aCommand == "unset")
8165   {
8166     if (theArgsNb < 5)
8167     {
8168       std::cout << "Syntax error: need more arguments.\n";
8169       return 1;
8170     }
8171
8172     // redirect to new syntax
8173     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8174     anArgVec.SetValue (1, theArgVec[0]);
8175     anArgVec.SetValue (2, theArgVec[2]);
8176     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8177     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8178     {
8179       anArgVec.SetValue (anIt, theArgVec[anIt]);
8180     }
8181
8182     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8183   }
8184
8185   // change plane command
8186   TCollection_AsciiString aPlaneName;
8187   Handle(Graphic3d_ClipPlane) aClipPlane;
8188   Standard_Integer anArgIter = 0;
8189   if (aCommand == "-change"
8190    || aCommand == "change")
8191   {
8192     // old syntax support
8193     if (theArgsNb < 3)
8194     {
8195       std::cout << "Syntax error: need more arguments.\n";
8196       return 1;
8197     }
8198
8199     anArgIter  = 3;
8200     aPlaneName = theArgVec[2];
8201     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8202     {
8203       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8204       return 1;
8205     }
8206   }
8207   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8208   {
8209     anArgIter  = 2;
8210     aPlaneName = theArgVec[1];
8211   }
8212   else
8213   {
8214     anArgIter  = 2;
8215     aPlaneName = theArgVec[1];
8216     aClipPlane = new Graphic3d_ClipPlane();
8217     aRegPlanes.Bind (aPlaneName, aClipPlane);
8218     theDi << "Created new plane " << aPlaneName << ".\n";
8219   }
8220
8221   if (theArgsNb - anArgIter < 1)
8222   {
8223     std::cout << "Syntax error: need more arguments.\n";
8224     return 1;
8225   }
8226
8227   for (; anArgIter < theArgsNb; ++anArgIter)
8228   {
8229     const char**     aChangeArgs   = theArgVec + anArgIter;
8230     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8231     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8232     aChangeArg.LowerCase();
8233
8234     Standard_Boolean toEnable = Standard_True;
8235     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8236     {
8237       aClipPlane->SetOn (toEnable);
8238     }
8239     else if (aChangeArg == "-equation"
8240           || aChangeArg == "equation")
8241     {
8242       if (aNbChangeArgs < 5)
8243       {
8244         std::cout << "Syntax error: need more arguments.\n";
8245         return 1;
8246       }
8247
8248       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
8249       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
8250       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
8251       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
8252       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8253       anArgIter += 4;
8254     }
8255     else if (aChangeArg == "-capping"
8256           || aChangeArg == "capping")
8257     {
8258       if (aNbChangeArgs < 2)
8259       {
8260         std::cout << "Syntax error: need more arguments.\n";
8261         return 1;
8262       }
8263
8264       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8265       {
8266         aClipPlane->SetCapping (toEnable);
8267         anArgIter += 1;
8268       }
8269       else
8270       {
8271         // just skip otherwise (old syntax)
8272       }
8273     }
8274     else if (aChangeArg == "-useobjectmaterial"
8275           || aChangeArg == "-useobjectmat"
8276           || aChangeArg == "-useobjmat"
8277           || aChangeArg == "-useobjmaterial")
8278     {
8279       if (aNbChangeArgs < 2)
8280       {
8281         std::cout << "Syntax error: need more arguments.\n";
8282         return 1;
8283       }
8284
8285       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8286       {
8287         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8288         anArgIter += 1;
8289       }
8290     }
8291     else if (aChangeArg == "-useobjecttexture"
8292           || aChangeArg == "-useobjecttex"
8293           || aChangeArg == "-useobjtexture"
8294           || aChangeArg == "-useobjtex")
8295     {
8296       if (aNbChangeArgs < 2)
8297       {
8298         std::cout << "Syntax error: need more arguments.\n";
8299         return 1;
8300       }
8301
8302       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8303       {
8304         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8305         anArgIter += 1;
8306       }
8307     }
8308     else if (aChangeArg == "-useobjectshader"
8309           || aChangeArg == "-useobjshader")
8310     {
8311       if (aNbChangeArgs < 2)
8312       {
8313         std::cout << "Syntax error: need more arguments.\n";
8314         return 1;
8315       }
8316
8317       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8318       {
8319         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8320         anArgIter += 1;
8321       }
8322     }
8323     else if (aChangeArg == "-color"
8324           || aChangeArg == "color")
8325     {
8326       Quantity_Color aColor;
8327       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8328                                                            aChangeArgs + 1,
8329                                                            aColor);
8330       if (aNbParsed == 0)
8331       {
8332         std::cout << "Syntax error: need more arguments.\n";
8333         return 1;
8334       }
8335
8336       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8337       aMat.SetAmbientColor (aColor);
8338       aMat.SetDiffuseColor (aColor);
8339       aClipPlane->SetCappingMaterial (aMat);
8340       anArgIter += aNbParsed;
8341     }
8342     else if (aChangeArg == "-texname"
8343           || aChangeArg == "texname")
8344     {
8345       if (aNbChangeArgs < 2)
8346       {
8347         std::cout << "Syntax error: need more arguments.\n";
8348         return 1;
8349       }
8350
8351       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8352       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8353       if (!aTexture->IsDone())
8354       {
8355         aClipPlane->SetCappingTexture (NULL);
8356       }
8357       else
8358       {
8359         aTexture->EnableModulate();
8360         aTexture->EnableRepeat();
8361         aClipPlane->SetCappingTexture (aTexture);
8362       }
8363       anArgIter += 1;
8364     }
8365     else if (aChangeArg == "-texscale"
8366           || aChangeArg == "texscale")
8367     {
8368       if (aClipPlane->CappingTexture().IsNull())
8369       {
8370         std::cout << "Error: no texture is set.\n";
8371         return 1;
8372       }
8373
8374       if (aNbChangeArgs < 3)
8375       {
8376         std::cout << "Syntax error: need more arguments.\n";
8377         return 1;
8378       }
8379
8380       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8381       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8382       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8383       anArgIter += 2;
8384     }
8385     else if (aChangeArg == "-texorigin"
8386           || aChangeArg == "texorigin") // texture origin
8387     {
8388       if (aClipPlane->CappingTexture().IsNull())
8389       {
8390         std::cout << "Error: no texture is set.\n";
8391         return 1;
8392       }
8393
8394       if (aNbChangeArgs < 3)
8395       {
8396         std::cout << "Syntax error: need more arguments.\n";
8397         return 1;
8398       }
8399
8400       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8401       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8402
8403       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8404       anArgIter += 2;
8405     }
8406     else if (aChangeArg == "-texrotate"
8407           || aChangeArg == "texrotate") // texture rotation
8408     {
8409       if (aClipPlane->CappingTexture().IsNull())
8410       {
8411         std::cout << "Error: no texture is set.\n";
8412         return 1;
8413       }
8414
8415       if (aNbChangeArgs < 2)
8416       {
8417         std::cout << "Syntax error: need more arguments.\n";
8418         return 1;
8419       }
8420
8421       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8422       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8423       anArgIter += 1;
8424     }
8425     else if (aChangeArg == "-hatch"
8426           || aChangeArg == "hatch")
8427     {
8428       if (aNbChangeArgs < 2)
8429       {
8430         std::cout << "Syntax error: need more arguments.\n";
8431         return 1;
8432       }
8433
8434       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8435       aHatchStr.LowerCase();
8436       if (aHatchStr == "on")
8437       {
8438         aClipPlane->SetCappingHatchOn();
8439       }
8440       else if (aHatchStr == "off")
8441       {
8442         aClipPlane->SetCappingHatchOff();
8443       }
8444       else
8445       {
8446         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8447       }
8448       anArgIter += 1;
8449     }
8450     else if (aChangeArg == "-delete"
8451           || aChangeArg == "delete")
8452     {
8453       removePlane (aRegPlanes, aPlaneName);
8454       return 0;
8455     }
8456     else if (aChangeArg == "-set"
8457           || aChangeArg == "-unset")
8458     {
8459       // set / unset plane command
8460       Standard_Boolean toSet = aChangeArg == "-set";
8461       Standard_Integer anIt = 1;
8462       for (; anIt < aNbChangeArgs; ++anIt)
8463       {
8464         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8465         if (anEntityName.IsEmpty()
8466          || anEntityName.Value (1) == '-')
8467         {
8468           break;
8469         }
8470         else if (ViewerTest_myViews.IsBound1 (anEntityName))
8471         {
8472           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8473           if (toSet)
8474           {
8475             aView->AddClipPlane (aClipPlane);
8476           }
8477           else
8478           {
8479             aView->RemoveClipPlane (aClipPlane);
8480           }
8481           continue;
8482         }
8483         else if (GetMapOfAIS().IsBound2 (anEntityName))
8484         {
8485           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
8486           if (toSet)
8487           {
8488             aIObj->AddClipPlane (aClipPlane);
8489           }
8490           else
8491           {
8492             aIObj->RemoveClipPlane (aClipPlane);
8493           }
8494         }
8495         else
8496         {
8497           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
8498           return 1;
8499         }
8500       }
8501
8502       if (anIt == 1)
8503       {
8504         // apply to active view
8505         if (toSet)
8506         {
8507           anActiveView->AddClipPlane (aClipPlane);
8508         }
8509         else
8510         {
8511           anActiveView->RemoveClipPlane (aClipPlane);
8512         }
8513       }
8514       else
8515       {
8516         anArgIter = anArgIter + anIt - 1;
8517       }
8518     }
8519     else
8520     {
8521       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8522       return 1;
8523     }
8524   }
8525
8526   ViewerTest::RedrawAllViews();
8527   return 0;
8528 }
8529
8530 //===============================================================================================
8531 //function : VZRange
8532 //purpose  :
8533 //===============================================================================================
8534 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8535 {
8536   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8537
8538   if (aCurrentView.IsNull())
8539   {
8540     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8541     return 1;
8542   }
8543
8544   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
8545
8546   if (theArgsNb < 2)
8547   {
8548     theDi << "ZNear: " << aCamera->ZNear() << "\n";
8549     theDi << "ZFar: " << aCamera->ZFar() << "\n";
8550     return 0;
8551   }
8552
8553   if (theArgsNb == 3)
8554   {
8555     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8556     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
8557
8558     if (aNewZNear >= aNewZFar)
8559     {
8560       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
8561       return 1;
8562     }
8563
8564     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8565     {
8566       std::cout << theArgVec[0] << ": invalid arguments: ";
8567       std::cout << "znear, zfar should be positive for perspective camera.\n";
8568       return 1;
8569     }
8570
8571     aCamera->SetZRange (aNewZNear, aNewZFar);
8572   }
8573   else
8574   {
8575     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8576     return 1;
8577   }
8578
8579   aCurrentView->Redraw();
8580
8581   return 0;
8582 }
8583
8584 //===============================================================================================
8585 //function : VAutoZFit
8586 //purpose  :
8587 //===============================================================================================
8588 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8589 {
8590   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8591
8592   if (aCurrentView.IsNull())
8593   {
8594     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8595     return 1;
8596   }
8597
8598   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
8599
8600   if (theArgsNb > 3)
8601   {
8602     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8603     return 1;
8604   }
8605
8606   if (theArgsNb < 2)
8607   {
8608     theDi << "Auto z-fit mode: \n"
8609           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
8610           << "Scale: " << aScale << "\n";
8611     return 0;
8612   }
8613
8614   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
8615
8616   if (theArgsNb >= 3)
8617   {
8618     aScale = Draw::Atoi (theArgVec[2]);
8619   }
8620
8621   aCurrentView->SetAutoZFitMode (isOn, aScale);
8622   aCurrentView->AutoZFit();
8623   aCurrentView->Redraw();
8624
8625   return 0;
8626 }
8627
8628 //! Auxiliary function to print projection type
8629 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
8630 {
8631   switch (theProjType)
8632   {
8633     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
8634     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
8635     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
8636     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
8637     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
8638   }
8639   return "UNKNOWN";
8640 }
8641
8642 //===============================================================================================
8643 //function : VCamera
8644 //purpose  :
8645 //===============================================================================================
8646 static int VCamera (Draw_Interpretor& theDI,
8647                     Standard_Integer  theArgsNb,
8648                     const char**      theArgVec)
8649 {
8650   Handle(V3d_View) aView = ViewerTest::CurrentView();
8651   if (aView.IsNull())
8652   {
8653     std::cout << "Error: no active view.\n";
8654     return 1;
8655   }
8656
8657   Handle(Graphic3d_Camera) aCamera = aView->Camera();
8658   if (theArgsNb < 2)
8659   {
8660     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
8661     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
8662     theDI << "Distance:   " << aCamera->Distance() << "\n";
8663     theDI << "IOD:        " << aCamera->IOD() << "\n";
8664     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
8665     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
8666     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
8667     return 0;
8668   }
8669
8670   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8671   {
8672     Standard_CString        anArg = theArgVec[anArgIter];
8673     TCollection_AsciiString anArgCase (anArg);
8674     anArgCase.LowerCase();
8675     if (anArgCase == "-proj"
8676      || anArgCase == "-projection"
8677      || anArgCase == "-projtype"
8678      || anArgCase == "-projectiontype")
8679     {
8680       theDI << projTypeName (aCamera->ProjectionType()) << " ";
8681     }
8682     else if (anArgCase == "-ortho"
8683           || anArgCase == "-orthographic")
8684     {
8685       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8686     }
8687     else if (anArgCase == "-persp"
8688           || anArgCase == "-perspective"
8689           || anArgCase == "-perspmono"
8690           || anArgCase == "-perspectivemono"
8691           || anArgCase == "-mono")
8692     {
8693       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8694     }
8695     else if (anArgCase == "-stereo"
8696           || anArgCase == "-stereoscopic"
8697           || anArgCase == "-perspstereo"
8698           || anArgCase == "-perspectivestereo")
8699     {
8700       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8701     }
8702     else if (anArgCase == "-left"
8703           || anArgCase == "-lefteye"
8704           || anArgCase == "-monoleft"
8705           || anArgCase == "-monolefteye"
8706           || anArgCase == "-perpsleft"
8707           || anArgCase == "-perpslefteye")
8708     {
8709       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8710     }
8711     else if (anArgCase == "-right"
8712           || anArgCase == "-righteye"
8713           || anArgCase == "-monoright"
8714           || anArgCase == "-monorighteye"
8715           || anArgCase == "-perpsright")
8716     {
8717       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8718     }
8719     else if (anArgCase == "-dist"
8720           || anArgCase == "-distance")
8721     {
8722       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8723       if (anArgValue != NULL
8724       && *anArgValue != '-')
8725       {
8726         ++anArgIter;
8727         aCamera->SetDistance (Draw::Atof (anArgValue));
8728         continue;
8729       }
8730       theDI << aCamera->Distance() << " ";
8731     }
8732     else if (anArgCase == "-iod")
8733     {
8734       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8735       if (anArgValue != NULL
8736       && *anArgValue != '-')
8737       {
8738         ++anArgIter;
8739         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8740         continue;
8741       }
8742       theDI << aCamera->IOD() << " ";
8743     }
8744     else if (anArgCase == "-iodtype")
8745     {
8746       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8747       TCollection_AsciiString anValueCase (anArgValue);
8748       anValueCase.LowerCase();
8749       if (anValueCase == "abs"
8750        || anValueCase == "absolute")
8751       {
8752         ++anArgIter;
8753         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8754         continue;
8755       }
8756       else if (anValueCase == "rel"
8757             || anValueCase == "relative")
8758       {
8759         ++anArgIter;
8760         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8761         continue;
8762       }
8763       else if (*anArgValue != '-')
8764       {
8765         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8766         return 1;
8767       }
8768       switch (aCamera->GetIODType())
8769       {
8770         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8771         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8772       }
8773     }
8774     else if (anArgCase == "-zfocus")
8775     {
8776       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8777       if (anArgValue != NULL
8778       && *anArgValue != '-')
8779       {
8780         ++anArgIter;
8781         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8782         continue;
8783       }
8784       theDI << aCamera->ZFocus() << " ";
8785     }
8786     else if (anArgCase == "-zfocustype")
8787     {
8788       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8789       TCollection_AsciiString anValueCase (anArgValue);
8790       anValueCase.LowerCase();
8791       if (anValueCase == "abs"
8792        || anValueCase == "absolute")
8793       {
8794         ++anArgIter;
8795         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8796         continue;
8797       }
8798       else if (anValueCase == "rel"
8799             || anValueCase == "relative")
8800       {
8801         ++anArgIter;
8802         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8803         continue;
8804       }
8805       else if (*anArgValue != '-')
8806       {
8807         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8808         return 1;
8809       }
8810       switch (aCamera->ZFocusType())
8811       {
8812         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8813         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8814       }
8815     }
8816     else if (anArgCase == "-fov"
8817           || anArgCase == "-fovy")
8818     {
8819       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8820       if (anArgValue != NULL
8821       && *anArgValue != '-')
8822       {
8823         ++anArgIter;
8824         aCamera->SetFOVy (Draw::Atof (anArgValue));
8825         continue;
8826       }
8827       theDI << aCamera->FOVy() << " ";
8828     }
8829     else
8830     {
8831       std::cout << "Error: unknown argument '" << anArg << "'\n";
8832       return 1;
8833     }
8834   }
8835
8836   aView->AutoZFit();
8837   aView->Redraw();
8838
8839   return 0;
8840 }
8841
8842 //! Parse stereo output mode
8843 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8844                                          Graphic3d_StereoMode& theMode)
8845 {
8846   TCollection_AsciiString aFlag (theArg);
8847   aFlag.LowerCase();
8848   if (aFlag == "quadbuffer")
8849   {
8850     theMode = Graphic3d_StereoMode_QuadBuffer;
8851   }
8852   else if (aFlag == "anaglyph")
8853   {
8854     theMode = Graphic3d_StereoMode_Anaglyph;
8855   }
8856   else if (aFlag == "row"
8857         || aFlag == "rowinterlaced")
8858   {
8859     theMode = Graphic3d_StereoMode_RowInterlaced;
8860   }
8861   else if (aFlag == "col"
8862         || aFlag == "colinterlaced"
8863         || aFlag == "columninterlaced")
8864   {
8865     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8866   }
8867   else if (aFlag == "chess"
8868         || aFlag == "chessboard")
8869   {
8870     theMode = Graphic3d_StereoMode_ChessBoard;
8871   }
8872   else if (aFlag == "sbs"
8873         || aFlag == "sidebyside")
8874   {
8875     theMode = Graphic3d_StereoMode_SideBySide;
8876   }
8877   else if (aFlag == "ou"
8878         || aFlag == "overunder")
8879   {
8880     theMode = Graphic3d_StereoMode_OverUnder;
8881   }
8882   else if (aFlag == "pageflip"
8883         || aFlag == "softpageflip")
8884   {
8885     theMode = Graphic3d_StereoMode_SoftPageFlip;
8886   }
8887   else
8888   {
8889     return Standard_False;
8890   }
8891   return Standard_True;
8892 }
8893
8894 //! Parse anaglyph filter
8895 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8896                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8897 {
8898   TCollection_AsciiString aFlag (theArg);
8899   aFlag.LowerCase();
8900   if (aFlag == "redcyansimple")
8901   {
8902     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8903   }
8904   else if (aFlag == "redcyan"
8905         || aFlag == "redcyanoptimized")
8906   {
8907     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8908   }
8909   else if (aFlag == "yellowbluesimple")
8910   {
8911     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8912   }
8913   else if (aFlag == "yellowblue"
8914         || aFlag == "yellowblueoptimized")
8915   {
8916     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8917   }
8918   else if (aFlag == "greenmagenta"
8919         || aFlag == "greenmagentasimple")
8920   {
8921     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8922   }
8923   else
8924   {
8925     return Standard_False;
8926   }
8927   return Standard_True;
8928 }
8929
8930 //==============================================================================
8931 //function : VStereo
8932 //purpose  :
8933 //==============================================================================
8934
8935 static int VStereo (Draw_Interpretor& theDI,
8936                     Standard_Integer  theArgNb,
8937                     const char**      theArgVec)
8938 {
8939   Handle(V3d_View) aView = ViewerTest::CurrentView();
8940   if (theArgNb < 2)
8941   {
8942     if (aView.IsNull())
8943     {
8944       std::cout << "Error: no active viewer!\n";
8945       return 0;
8946     }
8947
8948     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8949     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8950     if (isActive)
8951     {
8952       TCollection_AsciiString aMode;
8953       switch (aView->RenderingParams().StereoMode)
8954       {
8955         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8956         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8957         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8958         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8959         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8960         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8961         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8962         case Graphic3d_StereoMode_Anaglyph  :
8963           aMode = "anaglyph";
8964           switch (aView->RenderingParams().AnaglyphFilter)
8965           {
8966             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8967             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8968             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8969             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8970             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8971             default: break;
8972           }
8973         default: break;
8974       }
8975       theDI << "Mode " << aMode << "\n";
8976     }
8977     return 0;
8978   }
8979
8980   Handle(Graphic3d_Camera) aCamera;
8981   Graphic3d_RenderingParams*   aParams   = NULL;
8982   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8983   if (!aView.IsNull())
8984   {
8985     aParams   = &aView->ChangeRenderingParams();
8986     aMode     = aParams->StereoMode;
8987     aCamera   = aView->Camera();
8988   }
8989
8990   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8991   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8992   {
8993     Standard_CString        anArg = theArgVec[anArgIter];
8994     TCollection_AsciiString aFlag (anArg);
8995     aFlag.LowerCase();
8996     if (anUpdateTool.parseRedrawMode (aFlag))
8997     {
8998       continue;
8999     }
9000     else if (aFlag == "0"
9001           || aFlag == "off")
9002     {
9003       if (++anArgIter < theArgNb)
9004       {
9005         std::cout << "Error: wrong number of arguments!\n";
9006         return 1;
9007       }
9008
9009       if (!aCamera.IsNull()
9010        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
9011       {
9012         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9013       }
9014       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
9015       return 0;
9016     }
9017     else if (aFlag == "1"
9018           || aFlag == "on")
9019     {
9020       if (++anArgIter < theArgNb)
9021       {
9022         std::cout << "Error: wrong number of arguments!\n";
9023         return 1;
9024       }
9025
9026       if (!aCamera.IsNull())
9027       {
9028         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9029       }
9030       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9031       return 0;
9032     }
9033     else if (aFlag == "-reverse"
9034           || aFlag == "-reversed"
9035           || aFlag == "-swap")
9036     {
9037       Standard_Boolean toEnable = Standard_True;
9038       if (++anArgIter < theArgNb
9039       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9040       {
9041         --anArgIter;
9042       }
9043       aParams->ToReverseStereo = toEnable;
9044     }
9045     else if (aFlag == "-noreverse"
9046           || aFlag == "-noswap")
9047     {
9048       Standard_Boolean toDisable = Standard_True;
9049       if (++anArgIter < theArgNb
9050       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9051       {
9052         --anArgIter;
9053       }
9054       aParams->ToReverseStereo = !toDisable;
9055     }
9056     else if (aFlag == "-mode"
9057           || aFlag == "-stereomode")
9058     {
9059       if (++anArgIter >= theArgNb
9060       || !parseStereoMode (theArgVec[anArgIter], aMode))
9061       {
9062         std::cout << "Error: syntax error at '" << anArg << "'\n";
9063         return 1;
9064       }
9065
9066       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9067       {
9068         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9069       }
9070     }
9071     else if (aFlag == "-anaglyph"
9072           || aFlag == "-anaglyphfilter")
9073     {
9074       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9075       if (++anArgIter >= theArgNb
9076       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9077       {
9078         std::cout << "Error: syntax error at '" << anArg << "'\n";
9079         return 1;
9080       }
9081
9082       aMode = Graphic3d_StereoMode_Anaglyph;
9083       aParams->AnaglyphFilter = aFilter;
9084     }
9085     else if (parseStereoMode (anArg, aMode)) // short syntax
9086     {
9087       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9088       {
9089         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9090       }
9091     }
9092     else
9093     {
9094       std::cout << "Error: syntax error at '" << anArg << "'\n";
9095       return 1;
9096     }
9097   }
9098
9099   if (!aView.IsNull())
9100   {
9101     aParams->StereoMode = aMode;
9102     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9103   }
9104   return 0;
9105 }
9106
9107 //===============================================================================================
9108 //function : VDefaults
9109 //purpose  :
9110 //===============================================================================================
9111 static int VDefaults (Draw_Interpretor& theDi,
9112                       Standard_Integer  theArgsNb,
9113                       const char**      theArgVec)
9114 {
9115   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9116   if (aCtx.IsNull())
9117   {
9118     std::cerr << "No active viewer!\n";
9119     return 1;
9120   }
9121
9122   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9123   if (theArgsNb < 2)
9124   {
9125     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9126     {
9127       theDi << "DeflType:           relative\n"
9128             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9129     }
9130     else
9131     {
9132       theDi << "DeflType:           absolute\n"
9133             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9134     }
9135     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9136     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9137     return 0;
9138   }
9139
9140   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9141   {
9142     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9143     anArg.UpperCase();
9144     if (anArg == "-ABSDEFL"
9145      || anArg == "-ABSOLUTEDEFLECTION"
9146      || anArg == "-DEFL"
9147      || anArg == "-DEFLECTION")
9148     {
9149       if (++anArgIter >= theArgsNb)
9150       {
9151         std::cout << "Error: wrong syntax at " << anArg << "\n";
9152         return 1;
9153       }
9154       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9155       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9156     }
9157     else if (anArg == "-RELDEFL"
9158           || anArg == "-RELATIVEDEFLECTION"
9159           || anArg == "-DEVCOEFF"
9160           || anArg == "-DEVIATIONCOEFF"
9161           || anArg == "-DEVIATIONCOEFFICIENT")
9162     {
9163       if (++anArgIter >= theArgsNb)
9164       {
9165         std::cout << "Error: wrong syntax at " << anArg << "\n";
9166         return 1;
9167       }
9168       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9169       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9170     }
9171     else if (anArg == "-ANGDEFL"
9172           || anArg == "-ANGULARDEFL"
9173           || anArg == "-ANGULARDEFLECTION")
9174     {
9175       if (++anArgIter >= theArgsNb)
9176       {
9177         std::cout << "Error: wrong syntax at " << anArg << "\n";
9178         return 1;
9179       }
9180       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9181       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9182     }
9183     else if (anArg == "-AUTOTR"
9184           || anArg == "-AUTOTRIANG"
9185           || anArg == "-AUTOTRIANGULATION")
9186     {
9187       if (++anArgIter >= theArgsNb)
9188       {
9189         std::cout << "Error: wrong syntax at " << anArg << "\n";
9190         return 1;
9191       }
9192       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9193       aValue.LowerCase();
9194       if (aValue == "on"
9195        || aValue == "1")
9196       {
9197         aDefParams->SetAutoTriangulation (Standard_True);
9198       }
9199       else if (aValue == "off"
9200             || aValue == "0")
9201       {
9202         aDefParams->SetAutoTriangulation (Standard_False);
9203       }
9204     }
9205     else
9206     {
9207       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9208     }
9209   }
9210
9211   return 0;
9212 }
9213
9214 //! Auxiliary method
9215 inline void addLight (const Handle(V3d_Light)& theLightNew,
9216                       const Standard_Boolean   theIsGlobal)
9217 {
9218   if (theLightNew.IsNull())
9219   {
9220     return;
9221   }
9222
9223   if (theIsGlobal)
9224   {
9225     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
9226   }
9227   else
9228   {
9229     ViewerTest::CurrentView()->SetLightOn (theLightNew);
9230   }
9231 }
9232
9233 //! Auxiliary method
9234 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9235 {
9236   TCollection_AsciiString anArgNextCase (theArgNext);
9237   anArgNextCase.UpperCase();
9238   if (anArgNextCase.Length() > 5
9239    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9240   {
9241     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9242   }
9243   else
9244   {
9245     return theArgNext.IntegerValue();
9246   }
9247 }
9248
9249 //===============================================================================================
9250 //function : VLight
9251 //purpose  :
9252 //===============================================================================================
9253 static int VLight (Draw_Interpretor& theDi,
9254                    Standard_Integer  theArgsNb,
9255                    const char**      theArgVec)
9256 {
9257   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9258   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9259   if (aView.IsNull()
9260    || aViewer.IsNull())
9261   {
9262     std::cerr << "No active viewer!\n";
9263     return 1;
9264   }
9265
9266   Standard_Real anXYZ[3]   = {};
9267   Standard_Real anAtten[2] = {};
9268   if (theArgsNb < 2)
9269   {
9270     // print lights info
9271     Standard_Integer aLightId = 0;
9272     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9273     {
9274       Handle(V3d_Light) aLight = aLightIter.Value();
9275       const Quantity_Color aColor = aLight->Color();
9276       theDi << "Light" << aLightId << "\n";
9277       switch (aLight->Type())
9278       {
9279         case V3d_AMBIENT:
9280         {
9281           theDi << "  Type:       Ambient\n";
9282           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9283           break;
9284         }
9285         case V3d_DIRECTIONAL:
9286         {
9287           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
9288           theDi << "  Type:       Directional\n";
9289           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9290           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9291           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9292           if (!aLightDir.IsNull())
9293           {
9294             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9295             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9296             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9297             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9298           }
9299           break;
9300         }
9301         case V3d_POSITIONAL:
9302         {
9303           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
9304           theDi << "  Type:       Positional\n";
9305           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9306           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9307           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9308           if (!aLightPos.IsNull())
9309           {
9310             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9311             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9312             aLightPos->Attenuation (anAtten[0], anAtten[1]);
9313             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9314           }
9315           break;
9316         }
9317         case V3d_SPOT:
9318         {
9319           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
9320           theDi << "  Type:       Spot\n";
9321           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9322           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9323           if (!aLightSpot.IsNull())
9324           {
9325             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9326             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9327             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9328             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9329             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9330             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9331             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
9332             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
9333           }
9334           break;
9335         }
9336         default:
9337         {
9338           theDi << "  Type:       UNKNOWN\n";
9339           break;
9340         }
9341       }
9342       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
9343     }
9344   }
9345
9346   Handle(V3d_Light) aLightNew;
9347   Handle(V3d_Light) aLightOld;
9348   Standard_Boolean  isGlobal = Standard_True;
9349   Standard_Boolean  toCreate = Standard_False;
9350   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9351   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9352   {
9353     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9354     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
9355     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
9356     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
9357     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
9358
9359     TCollection_AsciiString aName, aValue;
9360     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9361     TCollection_AsciiString anArgCase (anArg);
9362     anArgCase.UpperCase();
9363     if (anUpdateTool.parseRedrawMode (anArg))
9364     {
9365       continue;
9366     }
9367
9368     if (anArgCase.IsEqual ("NEW")
9369      || anArgCase.IsEqual ("ADD")
9370      || anArgCase.IsEqual ("CREATE"))
9371     {
9372       toCreate = Standard_True;
9373     }
9374     else if (anArgCase.IsEqual ("GLOB")
9375           || anArgCase.IsEqual ("GLOBAL"))
9376     {
9377       isGlobal = Standard_True;
9378     }
9379     else if (anArgCase.IsEqual ("LOC")
9380           || anArgCase.IsEqual ("LOCAL"))
9381     {
9382       isGlobal = Standard_False;
9383     }
9384     else if (anArgCase.IsEqual ("DEF")
9385           || anArgCase.IsEqual ("DEFAULTS"))
9386     {
9387       toCreate = Standard_False;
9388       aViewer->SetDefaultLights();
9389     }
9390     else if (anArgCase.IsEqual ("CLR")
9391           || anArgCase.IsEqual ("CLEAR"))
9392     {
9393       toCreate = Standard_False;
9394       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
9395       {
9396         Handle(V3d_Light) aLight = aLightIter.Value();
9397         aViewer->DelLight (aLight);
9398         aLightIter = aView->ActiveLightIterator();
9399       }
9400     }
9401     else if (anArgCase.IsEqual ("AMB")
9402           || anArgCase.IsEqual ("AMBIENT")
9403           || anArgCase.IsEqual ("AMBLIGHT"))
9404     {
9405       addLight (aLightNew, isGlobal);
9406       if (!toCreate)
9407       {
9408         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9409         return 1;
9410       }
9411       toCreate  = Standard_False;
9412       aLightNew = new V3d_AmbientLight (aViewer);
9413     }
9414     else if (anArgCase.IsEqual ("DIRECTIONAL")
9415           || anArgCase.IsEqual ("DIRLIGHT"))
9416     {
9417       addLight (aLightNew, isGlobal);
9418       if (!toCreate)
9419       {
9420         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9421         return 1;
9422       }
9423       toCreate  = Standard_False;
9424       aLightNew = new V3d_DirectionalLight (aViewer);
9425     }
9426     else if (anArgCase.IsEqual ("SPOT")
9427           || anArgCase.IsEqual ("SPOTLIGHT"))
9428     {
9429       addLight (aLightNew, isGlobal);
9430       if (!toCreate)
9431       {
9432         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9433         return 1;
9434       }
9435       toCreate  = Standard_False;
9436       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
9437     }
9438     else if (anArgCase.IsEqual ("POSLIGHT")
9439           || anArgCase.IsEqual ("POSITIONAL"))
9440     {
9441       addLight (aLightNew, isGlobal);
9442       if (!toCreate)
9443       {
9444         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9445         return 1;
9446       }
9447       toCreate  = Standard_False;
9448       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
9449     }
9450     else if (anArgCase.IsEqual ("CHANGE"))
9451     {
9452       addLight (aLightNew, isGlobal);
9453       aLightNew.Nullify();
9454       if (++anArgIt >= theArgsNb)
9455       {
9456         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9457         return 1;
9458       }
9459
9460       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
9461       Standard_Integer aLightIt = 0;
9462       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9463       {
9464         if (aLightIt == aLightId)
9465         {
9466           aLightOld = aLightIter.Value();
9467           break;
9468         }
9469       }
9470
9471       if (aLightOld.IsNull())
9472       {
9473         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
9474         return 1;
9475       }
9476     }
9477     else if (anArgCase.IsEqual ("DEL")
9478           || anArgCase.IsEqual ("DELETE"))
9479     {
9480       Handle(V3d_Light) aLightDel;
9481       if (++anArgIt >= theArgsNb)
9482       {
9483         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9484         return 1;
9485       }
9486
9487       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9488       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
9489       Standard_Integer aLightIt = 0;
9490       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9491       {
9492         aLightDel = aLightIter.Value();
9493         if (aLightIt == aLightDelId)
9494         {
9495           break;
9496         }
9497       }
9498       if (!aLightDel.IsNull())
9499       {
9500         aViewer->DelLight (aLightDel);
9501       }
9502     }
9503     else if (anArgCase.IsEqual ("COLOR")
9504           || anArgCase.IsEqual ("COLOUR"))
9505     {
9506       if (++anArgIt >= theArgsNb)
9507       {
9508         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9509         return 1;
9510       }
9511
9512       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9513       anArgNext.UpperCase();
9514       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
9515       if (!aLightCurr.IsNull())
9516       {
9517         aLightCurr->SetColor (aColor);
9518       }
9519     }
9520     else if (anArgCase.IsEqual ("POS")
9521           || anArgCase.IsEqual ("POSITION"))
9522     {
9523       if ((anArgIt + 3) >= theArgsNb)
9524       {
9525         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9526         return 1;
9527       }
9528
9529       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9530       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9531       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9532       if (!aLightDir.IsNull())
9533       {
9534         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9535       }
9536       else if (!aLightPos.IsNull())
9537       {
9538         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9539       }
9540       else if (!aLightSpot.IsNull())
9541       {
9542         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9543       }
9544       else
9545       {
9546         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9547         return 1;
9548       }
9549     }
9550     else if (anArgCase.IsEqual ("DIR")
9551           || anArgCase.IsEqual ("DIRECTION"))
9552     {
9553       if ((anArgIt + 3) >= theArgsNb)
9554       {
9555         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9556         return 1;
9557       }
9558
9559       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9560       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9561       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9562       if (!aLightDir.IsNull())
9563       {
9564         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9565       }
9566       else if (!aLightSpot.IsNull())
9567       {
9568         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9569       }
9570       else
9571       {
9572         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9573         return 1;
9574       }
9575     }
9576     else if (anArgCase.IsEqual ("SM")
9577           || anArgCase.IsEqual ("SMOOTHNESS"))
9578     {
9579       if (++anArgIt >= theArgsNb)
9580       {
9581         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9582         return 1;
9583       }
9584
9585       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
9586
9587       if (fabs (aSmoothness) < Precision::Confusion())
9588       {
9589         aLightCurr->SetIntensity (1.f);
9590       }
9591       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
9592       {
9593         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
9594       }
9595       else
9596       {
9597         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
9598         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
9599       }
9600
9601       if (!aLightPos.IsNull())
9602       {
9603         aLightPos->SetSmoothRadius (aSmoothness);
9604       }
9605       else if (!aLightDir.IsNull())
9606       {
9607         aLightDir->SetSmoothAngle (aSmoothness);
9608       }
9609     }
9610     else if (anArgCase.IsEqual ("INT")
9611           || anArgCase.IsEqual ("INTENSITY"))
9612     {
9613       if (++anArgIt >= theArgsNb)
9614       {
9615         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9616         return 1;
9617       }
9618
9619       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
9620
9621       if (!aLightCurr.IsNull())
9622       {
9623         aLightCurr->SetIntensity (aIntensity);
9624       }
9625     }
9626     else if (anArgCase.IsEqual ("ANG")
9627           || anArgCase.IsEqual ("ANGLE"))
9628     {
9629       if (++anArgIt >= theArgsNb)
9630       {
9631         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9632         return 1;
9633       }
9634
9635       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
9636
9637       if (!aLightSpot.IsNull())
9638       {
9639         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
9640       }
9641     }
9642     else if (anArgCase.IsEqual ("CONSTATTEN")
9643           || anArgCase.IsEqual ("CONSTATTENUATION"))
9644     {
9645       if (++anArgIt >= theArgsNb)
9646       {
9647         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9648         return 1;
9649       }
9650
9651       if (!aLightPos.IsNull())
9652       {
9653         aLightPos->Attenuation (anAtten[0], anAtten[1]);
9654         anAtten[0] = Atof (theArgVec[anArgIt]);
9655         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
9656       }
9657       else if (!aLightSpot.IsNull())
9658       {
9659         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9660         anAtten[0] = Atof (theArgVec[anArgIt]);
9661         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
9662       }
9663       else
9664       {
9665         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9666         return 1;
9667       }
9668     }
9669     else if (anArgCase.IsEqual ("LINATTEN")
9670           || anArgCase.IsEqual ("LINEARATTEN")
9671           || anArgCase.IsEqual ("LINEARATTENUATION"))
9672     {
9673       if (++anArgIt >= theArgsNb)
9674       {
9675         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9676         return 1;
9677       }
9678
9679       if (!aLightPos.IsNull())
9680       {
9681         aLightPos->Attenuation (anAtten[0], anAtten[1]);
9682         anAtten[1] = Atof (theArgVec[anArgIt]);
9683         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
9684       }
9685       else if (!aLightSpot.IsNull())
9686       {
9687         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9688         anAtten[1] = Atof (theArgVec[anArgIt]);
9689         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
9690       }
9691       else
9692       {
9693         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9694         return 1;
9695       }
9696     }
9697     else if (anArgCase.IsEqual ("EXP")
9698           || anArgCase.IsEqual ("EXPONENT")
9699           || anArgCase.IsEqual ("SPOTEXP")
9700           || anArgCase.IsEqual ("SPOTEXPONENT"))
9701     {
9702       if (++anArgIt >= theArgsNb)
9703       {
9704         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9705         return 1;
9706       }
9707
9708       if (!aLightSpot.IsNull())
9709       {
9710         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
9711       }
9712       else
9713       {
9714         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9715         return 1;
9716       }
9717     }
9718     else if (anArgCase.IsEqual ("HEAD")
9719           || anArgCase.IsEqual ("HEADLIGHT"))
9720     {
9721       if (++anArgIt >= theArgsNb)
9722       {
9723         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9724         return 1;
9725       }
9726
9727       if (aLightAmb.IsNull()
9728        && !aLightCurr.IsNull())
9729       {
9730         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
9731       }
9732       else
9733       {
9734         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9735         return 1;
9736       }
9737     }
9738     else
9739     {
9740       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9741     }
9742   }
9743
9744   addLight (aLightNew, isGlobal);
9745   aViewer->UpdateLights();
9746
9747   return 0;
9748 }
9749
9750 //=======================================================================
9751 //function : VRenderParams
9752 //purpose  : Enables/disables rendering features
9753 //=======================================================================
9754
9755 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9756                                        Standard_Integer  theArgNb,
9757                                        const char**      theArgVec)
9758 {
9759   Handle(V3d_View) aView = ViewerTest::CurrentView();
9760   if (aView.IsNull())
9761   {
9762     std::cerr << "Error: no active viewer!\n";
9763     return 1;
9764   }
9765
9766   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9767   TCollection_AsciiString aCmdName (theArgVec[0]);
9768   aCmdName.LowerCase();
9769   if (aCmdName == "vraytrace")
9770   {
9771     if (theArgNb == 1)
9772     {
9773       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9774       return 0;
9775     }
9776     else if (theArgNb == 2)
9777     {
9778       TCollection_AsciiString aValue (theArgVec[1]);
9779       aValue.LowerCase();
9780       if (aValue == "on"
9781        || aValue == "1")
9782       {
9783         aParams.Method = Graphic3d_RM_RAYTRACING;
9784         aView->Redraw();
9785         return 0;
9786       }
9787       else if (aValue == "off"
9788             || aValue == "0")
9789       {
9790         aParams.Method = Graphic3d_RM_RASTERIZATION;
9791         aView->Redraw();
9792         return 0;
9793       }
9794       else
9795       {
9796         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9797         return 1;
9798       }
9799     }
9800     else
9801     {
9802       std::cout << "Error: wrong number of arguments\n";
9803       return 1;
9804     }
9805   }
9806
9807   if (theArgNb < 2)
9808   {
9809     theDI << "renderMode:  ";
9810     switch (aParams.Method)
9811     {
9812       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9813       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9814     }
9815     theDI << "\n";
9816     theDI << "transparency:  ";
9817     switch (aParams.TransparencyMethod)
9818     {
9819       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
9820       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
9821                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
9822     }
9823     theDI << "\n";
9824     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9825     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
9826     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9827     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9828     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9829     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9830     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9831     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9832     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9833     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9834     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9835     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9836     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
9837     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
9838     theDI << "shadingModel: ";
9839     switch (aView->ShadingModel())
9840     {
9841       case V3d_COLOR:   theDI << "color";   break;
9842       case V3d_FLAT:    theDI << "flat";    break;
9843       case V3d_GOURAUD: theDI << "gouraud"; break;
9844       case V3d_PHONG:   theDI << "phong";   break;
9845     }
9846     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
9847     theDI << "\n";
9848     return 0;
9849   }
9850
9851   Standard_Boolean toPrint = Standard_False;
9852   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9853   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9854   {
9855     Standard_CString        anArg (theArgVec[anArgIter]);
9856     TCollection_AsciiString aFlag (anArg);
9857     aFlag.LowerCase();
9858     if (anUpdateTool.parseRedrawMode (aFlag))
9859     {
9860       continue;
9861     }
9862     else if (aFlag == "-echo"
9863           || aFlag == "-print")
9864     {
9865       toPrint = Standard_True;
9866       anUpdateTool.Invalidate();
9867     }
9868     else if (aFlag == "-mode"
9869           || aFlag == "-rendermode"
9870           || aFlag == "-render_mode")
9871     {
9872       if (toPrint)
9873       {
9874         switch (aParams.Method)
9875         {
9876           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9877           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9878         }
9879         continue;
9880       }
9881       else
9882       {
9883         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9884         return 1;
9885       }
9886     }
9887     else if (aFlag == "-ray"
9888           || aFlag == "-raytrace")
9889     {
9890       if (toPrint)
9891       {
9892         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9893         continue;
9894       }
9895
9896       aParams.Method = Graphic3d_RM_RAYTRACING;
9897     }
9898     else if (aFlag == "-rast"
9899           || aFlag == "-raster"
9900           || aFlag == "-rasterization")
9901     {
9902       if (toPrint)
9903       {
9904         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9905         continue;
9906       }
9907
9908       aParams.Method = Graphic3d_RM_RASTERIZATION;
9909     }
9910     else if (aFlag == "-msaa")
9911     {
9912       if (toPrint)
9913       {
9914         theDI << aParams.NbMsaaSamples << " ";
9915         continue;
9916       }
9917       else if (++anArgIter >= theArgNb)
9918       {
9919         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9920         return 1;
9921       }
9922
9923       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9924       if (aNbSamples < 0)
9925       {
9926         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9927         return 1;
9928       }
9929       else
9930       {
9931         aParams.NbMsaaSamples = aNbSamples;
9932       }
9933     }
9934     else if (aFlag == "-oit")
9935     {
9936       if (toPrint)
9937       {
9938         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
9939         {
9940           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
9941         }
9942         else
9943         {
9944           theDI << "off" << " ";
9945         }
9946         continue;
9947       }
9948       else if (++anArgIter >= theArgNb)
9949       {
9950         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9951         return 1;
9952       }
9953
9954       TCollection_AsciiString aParam = theArgVec[anArgIter];
9955       aParam.LowerCase();
9956       if (aParam.IsRealValue())
9957       {
9958         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
9959         if (aWeight < 0.f || aWeight > 1.f)
9960         {
9961           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
9962           return 1;
9963         }
9964
9965         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
9966         aParams.OitDepthFactor     = aWeight;
9967       }
9968       else if (aParam == "off")
9969       {
9970         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
9971       }
9972       else
9973       {
9974         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9975         return 1;
9976       }
9977     }
9978     else if (aFlag == "-depthprepass")
9979     {
9980       if (toPrint)
9981       {
9982         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
9983         continue;
9984       }
9985       aParams.ToEnableDepthPrepass = Standard_True;
9986       if (anArgIter + 1 < theArgNb
9987        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
9988       {
9989         ++anArgIter;
9990       }
9991     }
9992     else if (aFlag == "-rendscale"
9993           || aFlag == "-renderscale"
9994           || aFlag == "-renderresolutionscale")
9995     {
9996       if (toPrint)
9997       {
9998         theDI << aParams.RenderResolutionScale << " ";
9999         continue;
10000       }
10001       else if (++anArgIter >= theArgNb)
10002       {
10003         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10004         return 1;
10005       }
10006
10007       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
10008       if (aScale < 0.01)
10009       {
10010         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
10011         return 1;
10012       }
10013       else
10014       {
10015         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
10016       }
10017     }
10018     else if (aFlag == "-raydepth"
10019           || aFlag == "-ray_depth")
10020     {
10021       if (toPrint)
10022       {
10023         theDI << aParams.RaytracingDepth << " ";
10024         continue;
10025       }
10026       else if (++anArgIter >= theArgNb)
10027       {
10028         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10029         return 1;
10030       }
10031
10032       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
10033
10034       // We allow RaytracingDepth be more than 10 in case of GI enabled
10035       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
10036       {
10037         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
10038         return 1;
10039       }
10040       else
10041       {
10042         aParams.RaytracingDepth = aDepth;
10043       }
10044     }
10045     else if (aFlag == "-shad"
10046           || aFlag == "-shadows")
10047     {
10048       if (toPrint)
10049       {
10050         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
10051         continue;
10052       }
10053
10054       Standard_Boolean toEnable = Standard_True;
10055       if (++anArgIter < theArgNb
10056       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10057       {
10058         --anArgIter;
10059       }
10060       aParams.IsShadowEnabled = toEnable;
10061     }
10062     else if (aFlag == "-refl"
10063           || aFlag == "-reflections")
10064     {
10065       if (toPrint)
10066       {
10067         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10068         continue;
10069       }
10070
10071       Standard_Boolean toEnable = Standard_True;
10072       if (++anArgIter < theArgNb
10073       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10074       {
10075         --anArgIter;
10076       }
10077       aParams.IsReflectionEnabled = toEnable;
10078     }
10079     else if (aFlag == "-fsaa")
10080     {
10081       if (toPrint)
10082       {
10083         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10084         continue;
10085       }
10086
10087       Standard_Boolean toEnable = Standard_True;
10088       if (++anArgIter < theArgNb
10089       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10090       {
10091         --anArgIter;
10092       }
10093       aParams.IsAntialiasingEnabled = toEnable;
10094     }
10095     else if (aFlag == "-gleam")
10096     {
10097       if (toPrint)
10098       {
10099         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10100         continue;
10101       }
10102
10103       Standard_Boolean toEnable = Standard_True;
10104       if (++anArgIter < theArgNb
10105       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10106       {
10107         --anArgIter;
10108       }
10109       aParams.IsTransparentShadowEnabled = toEnable;
10110     }
10111     else if (aFlag == "-gi")
10112     {
10113       if (toPrint)
10114       {
10115         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10116         continue;
10117       }
10118
10119       Standard_Boolean toEnable = Standard_True;
10120       if (++anArgIter < theArgNb
10121       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10122       {
10123         --anArgIter;
10124       }
10125       aParams.IsGlobalIlluminationEnabled = toEnable;
10126       if (!toEnable)
10127       {
10128         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10129       }
10130     }
10131     else if (aFlag == "-blockedrng"
10132           || aFlag == "-brng")
10133     {
10134       if (toPrint)
10135       {
10136         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10137         continue;
10138       }
10139
10140       Standard_Boolean toEnable = Standard_True;
10141       if (++anArgIter < theArgNb
10142         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10143       {
10144         --anArgIter;
10145       }
10146       aParams.CoherentPathTracingMode = toEnable;
10147     }
10148     else if (aFlag == "-maxrad")
10149     {
10150       if (toPrint)
10151       {
10152         theDI << aParams.RadianceClampingValue << " ";
10153         continue;
10154       }
10155       else if (++anArgIter >= theArgNb)
10156       {
10157         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10158         return 1;
10159       }
10160
10161       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10162       if (!aMaxRadStr.IsRealValue())
10163       {
10164         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10165         return 1;
10166       }
10167
10168       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10169       if (aMaxRadiance <= 0.0)
10170       {
10171         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10172         return 1;
10173       }
10174       else
10175       {
10176         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
10177       }
10178     }
10179     else if (aFlag == "-iss")
10180     {
10181       if (toPrint)
10182       {
10183         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
10184         continue;
10185       }
10186
10187       Standard_Boolean toEnable = Standard_True;
10188       if (++anArgIter < theArgNb
10189         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10190       {
10191         --anArgIter;
10192       }
10193       aParams.AdaptiveScreenSampling = toEnable;
10194     }
10195     else if (aFlag == "-issd")
10196     {
10197       if (toPrint)
10198       {
10199         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
10200         continue;
10201       }
10202
10203       Standard_Boolean toEnable = Standard_True;
10204       if (++anArgIter < theArgNb
10205         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10206       {
10207         --anArgIter;
10208       }
10209       aParams.ShowSamplingTiles = toEnable;
10210     }
10211     else if (aFlag == "-nbtiles")
10212     {
10213       if (toPrint)
10214       {
10215         theDI << aParams.NbRayTracingTiles << " ";
10216         continue;
10217       }
10218       else if (++anArgIter >= theArgNb)
10219       {
10220         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10221         return 1;
10222       }
10223
10224       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
10225
10226       if (aNbTiles < 64)
10227       {
10228         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
10229         std::cerr << "Specify value in range [64, 1024].\n";
10230         return 1;
10231       }
10232       else
10233       {
10234         aParams.NbRayTracingTiles = aNbTiles;
10235       }
10236     }
10237     else if (aFlag == "-env")
10238     {
10239       if (toPrint)
10240       {
10241         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
10242         continue;
10243       }
10244
10245       Standard_Boolean toEnable = Standard_True;
10246       if (++anArgIter < theArgNb
10247         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10248       {
10249         --anArgIter;
10250       }
10251       aParams.UseEnvironmentMapBackground = toEnable;
10252     }
10253     else if (aFlag == "-twoside")
10254     {
10255       if (toPrint)
10256       {
10257         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
10258         continue;
10259       }
10260
10261       Standard_Boolean toEnable = Standard_True;
10262       if (++anArgIter < theArgNb
10263         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10264       {
10265         --anArgIter;
10266       }
10267       aParams.TwoSidedBsdfModels = toEnable;
10268     }
10269     else if (aFlag == "-shademodel"
10270           || aFlag == "-shadingmodel"
10271           || aFlag == "-shading")
10272     {
10273       if (toPrint)
10274       {
10275         switch (aView->ShadingModel())
10276         {
10277           case V3d_COLOR:   theDI << "color ";   break;
10278           case V3d_FLAT:    theDI << "flat ";    break;
10279           case V3d_GOURAUD: theDI << "gouraud "; break;
10280           case V3d_PHONG:   theDI << "phong ";   break;
10281         }
10282         continue;
10283       }
10284
10285       if (++anArgIter >= theArgNb)
10286       {
10287         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10288       }
10289
10290       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10291       aMode.LowerCase();
10292       if (aMode == "color"
10293        || aMode == "none")
10294       {
10295         aView->SetShadingModel (V3d_COLOR);
10296       }
10297       else if (aMode == "flat"
10298             || aMode == "facet")
10299       {
10300         aView->SetShadingModel (V3d_FLAT);
10301       }
10302       else if (aMode == "gouraud"
10303             || aMode == "vertex"
10304             || aMode == "vert")
10305       {
10306         aView->SetShadingModel (V3d_GOURAUD);
10307       }
10308       else if (aMode == "phong"
10309             || aMode == "fragment"
10310             || aMode == "frag"
10311             || aMode == "pixel")
10312       {
10313         aView->SetShadingModel (V3d_PHONG);
10314       }
10315       else
10316       {
10317         std::cout << "Error: unknown shading model '" << aMode << "'\n";
10318         return 1;
10319       }
10320     }
10321     else if (aFlag == "-resolution")
10322     {
10323       if (++anArgIter >= theArgNb)
10324       {
10325         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10326         return 1;
10327       }
10328
10329       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
10330       if (aResolution.IsIntegerValue())
10331       {
10332         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
10333       }
10334       else
10335       {
10336         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10337         return 1;
10338       }
10339     }
10340     else if (aFlag == "-rebuildglsl"
10341           || aFlag == "-rebuild")
10342     {
10343       if (toPrint)
10344       {
10345         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
10346         continue;
10347       }
10348
10349       Standard_Boolean toEnable = Standard_True;
10350       if (++anArgIter < theArgNb
10351           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10352       {
10353         --anArgIter;
10354       }
10355       aParams.RebuildRayTracingShaders = toEnable;
10356     }
10357     else if (aFlag == "-focal")
10358     {
10359       if (++anArgIter >= theArgNb)
10360       {
10361         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10362         return 1;
10363       }
10364
10365       TCollection_AsciiString aParam (theArgVec[anArgIter]);
10366       if (aParam.IsRealValue())
10367       {
10368         float aFocalDist = static_cast<float> (aParam.RealValue());
10369         if (aFocalDist < 0)
10370         {
10371           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10372           return 1;
10373         }
10374         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
10375       }
10376       else
10377       {
10378         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10379         return 1;
10380       }
10381     }
10382     else if (aFlag == "-aperture")
10383     {
10384       if (++anArgIter >= theArgNb)
10385       {
10386         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10387         return 1;
10388       }
10389
10390       TCollection_AsciiString aParam(theArgVec[anArgIter]);
10391       if (aParam.IsRealValue())
10392       {
10393         float aApertureSize = static_cast<float> (aParam.RealValue());
10394         if (aApertureSize < 0)
10395         {
10396           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10397           return 1;
10398         }
10399         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
10400       }
10401       else
10402       {
10403         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10404         return 1;
10405       }
10406     }
10407     else if (aFlag == "-exposure")
10408     {
10409       if (++anArgIter >= theArgNb)
10410       {
10411         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10412         return 1;
10413       }
10414
10415       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
10416       if (anExposure.IsRealValue())
10417       {
10418         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
10419       }
10420       else
10421       {
10422         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10423         return 1;
10424       }
10425     }
10426     else if (aFlag == "-whitepoint")
10427     {
10428       if (++anArgIter >= theArgNb)
10429       {
10430         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10431         return 1;
10432       }
10433
10434       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
10435       if (aWhitePoint.IsRealValue())
10436       {
10437         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
10438       }
10439       else
10440       {
10441         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10442         return 1;
10443       }
10444     }
10445     else if (aFlag == "-tonemapping")
10446     {
10447       if (++anArgIter >= theArgNb)
10448       {
10449         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10450         return 1;
10451       }
10452
10453       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10454       aMode.LowerCase();
10455
10456       if (aMode == "disabled")
10457       {
10458         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
10459       }
10460       else if (aMode == "filmic")
10461       {
10462         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
10463       }
10464       else
10465       {
10466         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10467         return 1;
10468       }
10469     }
10470     else
10471     {
10472       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
10473       return 1;
10474     }
10475   }
10476
10477   return 0;
10478 }
10479
10480 //=======================================================================
10481 //function : VProgressiveMode
10482 //purpose  :
10483 //=======================================================================
10484 #if defined(_WIN32)
10485 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
10486                                           Standard_Integer  /*theNbArgs*/,
10487                                           const char**      /*theArgs*/)
10488 {
10489   Handle(V3d_View) aView = ViewerTest::CurrentView();
10490   if (aView.IsNull())
10491   {
10492     std::cerr << "Error: no active viewer!\n";
10493     return 1;
10494   }
10495
10496   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
10497
10498   for (;;)
10499   {
10500     aView->Redraw();
10501
10502     Standard_Boolean toExit = Standard_False;
10503
10504     MSG aMsg;
10505     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
10506     {
10507       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
10508       {
10509         toExit = Standard_True;
10510       }
10511
10512       TranslateMessage (&aMsg);
10513       DispatchMessageW (&aMsg);
10514     }
10515
10516     if (toExit)
10517     {
10518       break;
10519     }
10520   }
10521
10522   return 0;
10523 }
10524 #endif
10525
10526 //=======================================================================
10527 //function : VFrustumCulling
10528 //purpose  : enables/disables view volume's culling.
10529 //=======================================================================
10530 static int VFrustumCulling (Draw_Interpretor& theDI,
10531                             Standard_Integer  theArgNb,
10532                             const char**      theArgVec)
10533 {
10534   Handle(V3d_View) aView = ViewerTest::CurrentView();
10535   if (aView.IsNull())
10536   {
10537     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
10538     return 1;
10539   }
10540
10541   if (theArgNb < 2)
10542   {
10543     theDI << (aView->IsCullingEnabled() ? "on" : "off");
10544     return 0;
10545   }
10546   else if (theArgNb != 2)
10547   {
10548     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
10549     return 1;
10550   }
10551
10552   TCollection_AsciiString aModeStr (theArgVec[1]);
10553   aModeStr.LowerCase();
10554   Standard_Boolean toEnable = 0;
10555   if (aModeStr == "on")
10556   {
10557     toEnable = 1;
10558   }
10559   else if (aModeStr == "off")
10560   {
10561     toEnable = 0;
10562   }
10563   else
10564   {
10565     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10566   }
10567
10568   aView->SetFrustumCulling (toEnable);
10569   aView->Redraw();
10570   return 0;
10571 }
10572
10573 //=======================================================================
10574 //function : VHighlightSelected
10575 //purpose  : 
10576 //=======================================================================
10577 static int VHighlightSelected (Draw_Interpretor& theDI,
10578                                Standard_Integer  theArgNb,
10579                                const char**      theArgVec)
10580 {
10581   if (ViewerTest::GetAISContext().IsNull())
10582   {
10583     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
10584     return 1;
10585   }
10586
10587   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10588
10589   if (theArgNb < 2)
10590   {
10591     theDI << (aContext->ToHilightSelected() ? "on" : "off");
10592     return 0;
10593   }
10594
10595   if (theArgNb != 2)
10596   {
10597     std::cout  << theArgVec[0] << " error : wrong number of parameters."
10598           << "Type 'help" << theArgVec[0] << "' for more information.";
10599     return 1;
10600   }
10601
10602   // Parse parameter
10603   TCollection_AsciiString aMode (theArgVec[1]);
10604   aMode.LowerCase();
10605   Standard_Boolean toEnable = Standard_False;
10606   if (aMode.IsEqual ("on"))
10607   {
10608     toEnable = Standard_True;
10609   }
10610   else if (aMode.IsEqual ("off"))
10611   {
10612     toEnable = Standard_False;
10613   }
10614   else
10615   {
10616     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10617   }
10618
10619   if (toEnable != aContext->ToHilightSelected())
10620   {
10621     aContext->SetToHilightSelected (toEnable);
10622
10623     // Move cursor to null position and  back to process updating of detection
10624     // and highlighting of selected object immediatly.
10625     Standard_Integer aPixX = 0;
10626     Standard_Integer aPixY = 0;
10627     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
10628
10629     anEventManager->GetCurrentPosition (aPixX, aPixY);
10630     anEventManager->MoveTo (0, 0);
10631     anEventManager->MoveTo (aPixX, aPixY);
10632   }
10633
10634   return 0;
10635 }
10636
10637 //=======================================================================
10638 //function : VXRotate
10639 //purpose  :
10640 //=======================================================================
10641 static Standard_Integer VXRotate (Draw_Interpretor& di,
10642                                    Standard_Integer argc,
10643                                    const char ** argv)
10644 {
10645   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10646   if (aContext.IsNull())
10647   {
10648     di << argv[0] << "ERROR : use 'vinit' command before \n";
10649     return 1;
10650   }
10651   
10652   if (argc != 3)
10653   {
10654     di << "ERROR : Usage : " << argv[0] << " name angle\n";
10655     return 1;
10656   }
10657
10658   TCollection_AsciiString aName (argv[1]);
10659   Standard_Real anAngle = Draw::Atof (argv[2]);
10660
10661   // find object
10662   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
10663   Handle(AIS_InteractiveObject) anIObj;
10664   if (!aMap.IsBound2 (aName) )
10665   {
10666     di << "Use 'vdisplay' before\n";
10667     return 1;
10668   }
10669   else
10670   {
10671     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
10672
10673     gp_Trsf aTransform;
10674     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
10675     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
10676
10677     aContext->SetLocation (anIObj, aTransform);
10678     aContext->UpdateCurrentViewer();
10679   }
10680
10681   return 0;
10682 }
10683
10684 //===============================================================================================
10685 //class   : ViewerTest_AISManipulator
10686 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
10687 //===============================================================================================
10688 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10689
10690 class ViewerTest_AISManipulator : public AIS_Manipulator
10691 {
10692 public:
10693
10694   ViewerTest_AISManipulator() : AIS_Manipulator()
10695   {
10696     GetMapOfAISManipulators().Add (this);
10697   }
10698
10699   virtual ~ViewerTest_AISManipulator()
10700   {
10701     GetMapOfAISManipulators().Remove (this);
10702   }
10703
10704   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10705 };
10706
10707 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10708 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10709
10710 //===============================================================================================
10711 //function : VManipulator
10712 //purpose  :
10713 //===============================================================================================
10714 static int VManipulator (Draw_Interpretor& theDi,
10715                          Standard_Integer  theArgsNb,
10716                          const char**      theArgVec)
10717 {
10718   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10719   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10720   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
10721   if (aView.IsNull()
10722    || aViewer.IsNull())
10723   {
10724     std::cerr << "No active viewer!\n";
10725     return 1;
10726   }
10727
10728   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
10729   Standard_Integer anArgIter = 1;
10730   for (; anArgIter < theArgsNb; ++anArgIter)
10731   {
10732     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
10733   }
10734
10735   ViewerTest_CmdParser aCmd;
10736   aCmd.AddDescription ("Manages manipulator for interactive objects:");
10737   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
10738   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
10739   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
10740   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
10741   aCmd.AddOption ("detach",         "...       - detach manipulator");
10742
10743   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
10744   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
10745   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
10746
10747   aCmd.AddOption ("move",   "... x y z - move object");
10748   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
10749   aCmd.AddOption ("scale",  "... factor - scale object");
10750
10751   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
10752   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
10753   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
10754   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
10755   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
10756   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
10757   aCmd.AddOption ("size",              "... size - set size of manipulator");
10758   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
10759
10760   aCmd.Parse (theArgsNb, theArgVec);
10761
10762   if (aCmd.HasOption ("help"))
10763   {
10764     theDi.PrintHelp (theArgVec[0]);
10765     return 0;
10766   }
10767
10768   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
10769
10770   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
10771
10772   if (aName.IsEmpty())
10773   {
10774     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
10775     return 1;
10776   }
10777
10778   // ----------------------------------
10779   // detach existing manipulator object
10780   // ----------------------------------
10781
10782   if (aCmd.HasOption ("detach"))
10783   {
10784     if (!aMapAIS.IsBound2 (aName))
10785     {
10786       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
10787       return 1;
10788     }
10789
10790     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10791     if (aManipulator.IsNull())
10792     {
10793       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10794       return 1;
10795     }
10796
10797     aManipulator->Detach();
10798     aMapAIS.UnBind2 (aName);
10799     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
10800
10801     return 0;
10802   }
10803
10804   // -----------------------------------------------
10805   // find or create manipulator if it does not exist
10806   // -----------------------------------------------
10807
10808   Handle(AIS_Manipulator) aManipulator;
10809   if (!aMapAIS.IsBound2 (aName))
10810   {
10811     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
10812
10813     aManipulator = new ViewerTest_AISManipulator();
10814     aMapAIS.Bind (aManipulator, aName);
10815   }
10816   else
10817   {
10818     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10819     if (aManipulator.IsNull())
10820     {
10821       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10822       return 1;
10823     }
10824   }
10825
10826   // -----------------------------------------
10827   // change properties of manipulator instance
10828   // -----------------------------------------
10829
10830   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
10831   {
10832     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
10833   }
10834   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
10835   {
10836     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
10837   }
10838   if (aCmd.HasOption ("followRotation", 1, Standard_True))
10839   {
10840     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
10841   }
10842   if (aCmd.HasOption ("gap", 1, Standard_True))
10843   {
10844     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
10845   }
10846   if (aCmd.HasOption ("part", 3, Standard_True))
10847   {
10848     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
10849     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
10850     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
10851     if (aMode < 1 || aMode > 3)
10852     {
10853       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
10854       return 1;
10855     }
10856
10857     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
10858   }
10859   if (aCmd.HasOption ("pos", 3, Standard_True))
10860   {
10861     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
10862     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
10863     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
10864
10865     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
10866   }
10867   if (aCmd.HasOption ("size", 1, Standard_True))
10868   {
10869     aManipulator->SetSize (aCmd.ArgFloat ("size"));
10870   }
10871   if (aCmd.HasOption ("zoomable", 1, Standard_True))
10872   {
10873     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
10874
10875     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
10876     {
10877       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
10878       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
10879     }
10880   }
10881
10882   // ---------------------------------------------------
10883   // attach, detach or access manipulator from an object
10884   // ---------------------------------------------------
10885
10886   if (aCmd.HasOption ("attach"))
10887   {
10888     // Find an object and attach manipulator to it
10889     if (!aCmd.HasOption ("attach", 1, Standard_True))
10890     {
10891       return 1;
10892     }
10893
10894     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
10895     if (!aMapAIS.IsBound2 (anObjName))
10896     {
10897       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
10898       return 1;
10899     }
10900
10901     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
10902     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
10903     for (; anIt.More(); anIt.Next())
10904     {
10905       if (anIt.Value()->IsAttached()
10906        && anIt.Value()->Object() == anObject)
10907       {
10908         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
10909         return 1;
10910       }
10911     }
10912
10913     AIS_Manipulator::OptionsForAttach anOptions;
10914     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
10915     {
10916       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
10917     }
10918     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
10919     {
10920       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
10921     }
10922     if (aCmd.HasOption ("enableModes", 1, Standard_True))
10923     {
10924       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
10925     }
10926
10927     aManipulator->Attach (anObject, anOptions);
10928   }
10929
10930   // --------------------------------------
10931   // apply transformation using manipulator
10932   // --------------------------------------
10933
10934   if (aCmd.HasOption ("startTransform", 2, Standard_True))
10935   {
10936     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
10937   }
10938   if (aCmd.HasOption ("transform", 2, Standard_True))
10939   {
10940     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
10941   }
10942   if (aCmd.HasOption ("stopTransform"))
10943   {
10944     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
10945
10946     aManipulator->StopTransform (toApply);
10947   }
10948
10949   gp_Trsf aT;
10950   if (aCmd.HasOption ("move", 3, Standard_True))
10951   {
10952     aT.SetTranslationPart (aCmd.ArgVec ("move"));
10953   }
10954   if (aCmd.HasOption ("rotate", 7, Standard_True))
10955   {
10956     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
10957   }
10958   if (aCmd.HasOption ("scale", 1))
10959   {
10960     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
10961   }
10962
10963   if (aT.Form() != gp_Identity)
10964   {
10965     aManipulator->Transform (aT);
10966   }
10967
10968   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
10969
10970   return 0;
10971 }
10972
10973 //===============================================================================================
10974 //function : VSelectionProperties
10975 //purpose  :
10976 //===============================================================================================
10977 static int VSelectionProperties (Draw_Interpretor& theDi,
10978                                  Standard_Integer  theArgsNb,
10979                                  const char**      theArgVec)
10980 {
10981   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10982   if (aCtx.IsNull())
10983   {
10984     std::cerr << "No active viewer!\n";
10985     return 1;
10986   }
10987
10988   Standard_Boolean toPrint  = theArgsNb == 1;
10989   Standard_Boolean toRedraw = Standard_False;
10990   Standard_Integer anArgIter = 1;
10991   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
10992   if (anArgIter < theArgsNb)
10993   {
10994     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
10995     anArgFirst.LowerCase();
10996     ++anArgIter;
10997     if (anArgFirst == "dynhighlight"
10998      || anArgFirst == "dynhilight"
10999      || anArgFirst == "dynamichighlight"
11000      || anArgFirst == "dynamichilight")
11001     {
11002       aType = Prs3d_TypeOfHighlight_Dynamic;
11003     }
11004     else if (anArgFirst == "localdynhighlight"
11005           || anArgFirst == "localdynhilight"
11006           || anArgFirst == "localdynamichighlight"
11007           || anArgFirst == "localdynamichilight")
11008     {
11009       aType = Prs3d_TypeOfHighlight_LocalDynamic;
11010     }
11011     else if (anArgFirst == "selhighlight"
11012           || anArgFirst == "selhilight"
11013           || anArgFirst == "selectedhighlight"
11014           || anArgFirst == "selectedhilight")
11015     {
11016       aType = Prs3d_TypeOfHighlight_Selected;
11017     }
11018     else if (anArgFirst == "localselhighlight"
11019           || anArgFirst == "localselhilight"
11020           || anArgFirst == "localselectedhighlight"
11021           || anArgFirst == "localselectedhilight")
11022     {
11023       aType = Prs3d_TypeOfHighlight_LocalSelected;
11024     }
11025     else
11026     {
11027       --anArgIter;
11028     }
11029   }
11030   for (; anArgIter < theArgsNb; ++anArgIter)
11031   {
11032     TCollection_AsciiString anArg (theArgVec[anArgIter]);
11033     anArg.LowerCase();
11034     if (anArg == "-help")
11035     {
11036       theDi.PrintHelp (theArgVec[0]);
11037       return 0;
11038     }
11039     else if (anArg == "-print")
11040     {
11041       toPrint = Standard_True;
11042     }
11043     else if (anArg == "-autoactivate")
11044     {
11045       Standard_Boolean toEnable = Standard_True;
11046       if (anArgIter + 1 < theArgsNb
11047        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11048       {
11049         ++anArgIter;
11050       }
11051       aCtx->SetAutoActivateSelection (toEnable);
11052     }
11053     else if (anArg == "-pickstrategy"
11054           || anArg == "-pickingstrategy")
11055     {
11056       if (++anArgIter >= theArgsNb)
11057       {
11058         std::cout << "Syntax error: type of highlighting is undefined\n";
11059         return 1;
11060       }
11061
11062       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11063       TCollection_AsciiString aVal (theArgVec[anArgIter]);
11064       aVal.LowerCase();
11065       if (aVal == "first"
11066        || aVal == "firstaccepted"
11067        || aVal == "firstacceptable")
11068       {
11069         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11070       }
11071       else if (aVal == "topmost"
11072             || aVal == "onlyTopmost")
11073       {
11074         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
11075       }
11076       else
11077       {
11078         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
11079         return 1;
11080       }
11081
11082       aCtx->SetPickingStrategy (aStrategy);
11083     }
11084     else if (anArg == "-pixtol"
11085           && anArgIter + 1 < theArgsNb)
11086     {
11087       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
11088     }
11089     else if ((anArg == "-mode"
11090            || anArg == "-dispmode")
11091           && anArgIter + 1 < theArgsNb)
11092     {
11093       if (aType == Prs3d_TypeOfHighlight_None)
11094       {
11095         std::cout << "Syntax error: type of highlighting is undefined\n";
11096         return 1;
11097       }
11098
11099       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
11100       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11101       aStyle->SetDisplayMode (aDispMode);
11102       toRedraw = Standard_True;
11103     }
11104     else if (anArg == "-layer"
11105           && anArgIter + 1 < theArgsNb)
11106     {
11107       if (aType == Prs3d_TypeOfHighlight_None)
11108       {
11109         std::cout << "Syntax error: type of highlighting is undefined\n";
11110         return 1;
11111       }
11112
11113       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
11114       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
11115       {
11116         TColStd_SequenceOfInteger aLayers;
11117         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
11118         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
11119         {
11120           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
11121           return 1;
11122         }
11123       }
11124
11125       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11126       aStyle->SetZLayer (aNewLayer);
11127       toRedraw = Standard_True;
11128     }
11129     else if (anArg == "-hicolor"
11130           || anArg == "-selcolor"
11131           || anArg == "-color")
11132     {
11133       if (anArg.StartsWith ("-hi"))
11134       {
11135         aType = Prs3d_TypeOfHighlight_Dynamic;
11136       }
11137       else if (anArg.StartsWith ("-sel"))
11138       {
11139         aType = Prs3d_TypeOfHighlight_Selected;
11140       }
11141       else if (aType == Prs3d_TypeOfHighlight_None)
11142       {
11143         std::cout << "Syntax error: type of highlighting is undefined\n";
11144         return 1;
11145       }
11146
11147       Quantity_Color aColor;
11148       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
11149                                                            theArgVec + anArgIter + 1,
11150                                                            aColor);
11151       if (aNbParsed == 0)
11152       {
11153         std::cout << "Syntax error: need more arguments.\n";
11154         return 1;
11155       }
11156       anArgIter += aNbParsed;
11157
11158       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11159       aStyle->SetColor (aColor);
11160       toRedraw = Standard_True;
11161     }
11162     else if ((anArg == "-transp"
11163            || anArg == "-transparency"
11164            || anArg == "-hitransp"
11165            || anArg == "-seltransp"
11166            || anArg == "-hitransplocal"
11167            || anArg == "-seltransplocal")
11168           && anArgIter + 1 < theArgsNb)
11169     {
11170       if (anArg.StartsWith ("-hi"))
11171       {
11172         aType = Prs3d_TypeOfHighlight_Dynamic;
11173       }
11174       else if (anArg.StartsWith ("-sel"))
11175       {
11176         aType = Prs3d_TypeOfHighlight_Selected;
11177       }
11178       else if (aType == Prs3d_TypeOfHighlight_None)
11179       {
11180         std::cout << "Syntax error: type of highlighting is undefined\n";
11181         return 1;
11182       }
11183
11184       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
11185       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11186       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
11187       toRedraw = Standard_True;
11188     }
11189     else if ((anArg == "-mat"
11190            || anArg == "-material")
11191           && anArgIter + 1 < theArgsNb)
11192     {
11193       if (aType == Prs3d_TypeOfHighlight_None)
11194       {
11195         std::cout << "Syntax error: type of highlighting is undefined\n";
11196         return 1;
11197       }
11198
11199       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11200       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
11201       if (aMatName != Graphic3d_NOM_DEFAULT)
11202       {
11203         ++anArgIter;
11204         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
11205         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
11206         Graphic3d_MaterialAspect aMat (aMatName);
11207         aMat.SetColor (aStyle->Color());
11208         aMat.SetTransparency (aStyle->Transparency());
11209         anAspect->SetFrontMaterial (aMat);
11210         anAspect->SetInteriorColor (aStyle->Color());
11211         aStyle->SetBasicFillAreaAspect (anAspect);
11212       }
11213       else
11214       {
11215         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
11216       }
11217       toRedraw = Standard_True;
11218     }
11219     else
11220     {
11221       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
11222     }
11223   }
11224
11225   if (toPrint)
11226   {
11227     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
11228     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
11229     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
11230     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
11231     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
11232     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
11233     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
11234     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
11235     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
11236     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
11237     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
11238     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
11239   }
11240
11241   if (aCtx->NbSelected() != 0 && toRedraw)
11242   {
11243     aCtx->HilightSelected (Standard_True);
11244   }
11245
11246   return 0;
11247 }
11248
11249 //===============================================================================================
11250 //function : VDumpSelectionImage
11251 //purpose  :
11252 //===============================================================================================
11253 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
11254                                 Standard_Integer  theArgsNb,
11255                                 const char**      theArgVec)
11256 {
11257   if (theArgsNb < 2)
11258   {
11259     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
11260     return 1;
11261   }
11262
11263   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
11264   if (aContext.IsNull())
11265   {
11266     std::cout << "Error: no active view.\n";
11267     return 1;
11268   }
11269
11270   TCollection_AsciiString aFile;
11271   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11272   Image_Format anImgFormat = Image_Format_BGR;
11273   Standard_Integer aPickedIndex = 1;
11274   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
11275   {
11276     TCollection_AsciiString aParam (theArgVec[anArgIter]);
11277     aParam.LowerCase();
11278     if (aParam == "-type")
11279     {
11280       if (++anArgIter >= theArgsNb)
11281       {
11282         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
11283         return 1;
11284       }
11285
11286       TCollection_AsciiString aValue (theArgVec[anArgIter]);
11287       aValue.LowerCase();
11288       if (aValue == "depth"
11289        || aValue == "normdepth"
11290        || aValue == "normalizeddepth")
11291       {
11292         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11293         anImgFormat = Image_Format_GrayF;
11294       }
11295       if (aValue == "depthinverted"
11296        || aValue == "normdepthinverted"
11297        || aValue == "normalizeddepthinverted"
11298        || aValue == "inverted")
11299       {
11300         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
11301         anImgFormat = Image_Format_GrayF;
11302       }
11303       else if (aValue == "unnormdepth"
11304             || aValue == "unnormalizeddepth")
11305       {
11306         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
11307         anImgFormat = Image_Format_GrayF;
11308       }
11309       else if (aValue == "objectcolor"
11310             || aValue == "object"
11311             || aValue == "color")
11312       {
11313         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
11314       }
11315       else if (aValue == "entitycolor"
11316             || aValue == "entity")
11317       {
11318         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
11319       }
11320       else if (aValue == "ownercolor"
11321             || aValue == "owner")
11322       {
11323         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
11324       }
11325       else if (aValue == "selectionmodecolor"
11326             || aValue == "selectionmode"
11327             || aValue == "selmodecolor"
11328             || aValue == "selmode")
11329       {
11330         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
11331       }
11332     }
11333     else if (aParam == "-picked"
11334           || aParam == "-pickeddepth"
11335           || aParam == "-pickedindex")
11336     {
11337       if (++anArgIter >= theArgsNb)
11338       {
11339         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
11340         return 1;
11341       }
11342
11343       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
11344     }
11345     else if (aFile.IsEmpty())
11346     {
11347       aFile = theArgVec[anArgIter];
11348     }
11349     else
11350     {
11351       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
11352       return 1;
11353     }
11354   }
11355   if (aFile.IsEmpty())
11356   {
11357     std::cout << "Syntax error: image file name is missing.\n";
11358     return 1;
11359   }
11360
11361   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
11362   Standard_Integer aWidth = 0, aHeight = 0;
11363   aView->Window()->Size (aWidth, aHeight);
11364
11365   Image_AlienPixMap aPixMap;
11366   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
11367   {
11368     std::cout << "Error: can't allocate image.\n";
11369     return 1;
11370   }
11371   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
11372   {
11373     std::cout << "Error: can't generate selection image.\n";
11374     return 1;
11375   }
11376   if (!aPixMap.Save (aFile))
11377   {
11378     std::cout << "Error: can't save selection image.\n";
11379     return 0;
11380   }
11381   return 0;
11382 }
11383
11384 //=======================================================================
11385 //function : ViewerCommands
11386 //purpose  :
11387 //=======================================================================
11388
11389 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
11390 {
11391
11392   const char *group = "ZeViewer";
11393   theCommands.Add("vinit",
11394           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
11395     "\n\t\t:     [-exitOnClose] [-closeOnEscape]"
11396   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11397     "\n\t\t:     [-display displayName]"
11398   #endif
11399     "\n\t\t: Creates new View window with specified name viewName."
11400     "\n\t\t: By default the new view is created in the viewer and in"
11401     "\n\t\t: graphic driver shared with active view."
11402     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
11403     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
11404     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
11405 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11406     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
11407     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
11408 #endif
11409     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
11410     "\n\t\t:  -width, -height width and heigth of window respectively."
11411     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
11412     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
11413     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
11414     __FILE__,VInit,group);
11415   theCommands.Add("vclose" ,
11416     "[view_id [keep_context=0|1]]\n"
11417     "or vclose ALL - to remove all created views\n"
11418     " - removes view(viewer window) defined by its view_id.\n"
11419     " - keep_context: by default 0; if 1 and the last view is deleted"
11420     " the current context is not removed.",
11421     __FILE__,VClose,group);
11422   theCommands.Add("vactivate" ,
11423     "view_id"
11424     " - activates view(viewer window) defined by its view_id",
11425     __FILE__,VActivate,group);
11426   theCommands.Add("vviewlist",
11427     "vviewlist [format={tree, long}]"
11428     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
11429     " - format: format of result output, if tree the output is a tree view;"
11430     "otherwise it's a list of full view names. By default format = tree",
11431     __FILE__,VViewList,group);
11432   theCommands.Add("vhelp" ,
11433     "vhelp            : display help on the viewer commands",
11434     __FILE__,VHelp,group);
11435   theCommands.Add("vtop" ,
11436     "vtop or <T>      : Top view. Orientation +X+Y" ,
11437     __FILE__,VTop,group);
11438   theCommands.Add("vbottom" ,
11439     "vbottom          : Bottom view. Orientation +X-Y" ,
11440     __FILE__,VBottom,group);
11441   theCommands.Add("vleft" ,
11442     "vleft            : Left view. Orientation -Y+Z" ,
11443     __FILE__,VLeft,group);
11444   theCommands.Add("vright" ,
11445     "vright           : Right view. Orientation +Y+Z" ,
11446     __FILE__,VRight,group);
11447   theCommands.Add("vaxo" ,
11448     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
11449     __FILE__,VAxo,group);
11450   theCommands.Add("vfront" ,
11451     "vfront           : Front view. Orientation +X+Z" ,
11452     __FILE__,VFront,group);
11453   theCommands.Add("vback" ,
11454     "vback            : Back view. Orientation -X+Z" ,
11455     __FILE__,VBack,group);
11456   theCommands.Add("vpick" ,
11457     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
11458     VPick,group);
11459   theCommands.Add("vfit",
11460     "vfit or <F> [-selected] [-noupdate]"
11461     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
11462     __FILE__,VFit,group);
11463   theCommands.Add ("vfitarea",
11464     "vfitarea x1 y1 x2 y2"
11465     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
11466     "\n\t\t: Fit view to show area located between two points"
11467     "\n\t\t: given in world 2D or 3D corrdinates.",
11468     __FILE__, VFitArea, group);
11469   theCommands.Add ("vzfit", "vzfit [scale]\n"
11470     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
11471     "   \"scale\" - specifies factor to scale computed z range.\n",
11472     __FILE__, VZFit, group);
11473   theCommands.Add("vrepaint",
11474             "vrepaint [-immediate]"
11475     "\n\t\t: force redraw",
11476     __FILE__,VRepaint,group);
11477   theCommands.Add("vclear",
11478     "vclear          : vclear"
11479     "\n\t\t: remove all the object from the viewer",
11480     __FILE__,VClear,group);
11481   theCommands.Add("vsetbg",
11482     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
11483     __FILE__,VSetBg,group);
11484   theCommands.Add("vsetbgmode",
11485     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
11486     __FILE__,VSetBgMode,group);
11487   theCommands.Add("vsetgradientbg",
11488     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
11489     __FILE__,VSetGradientBg,group);
11490   theCommands.Add("vsetgrbgmode",
11491     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
11492     __FILE__,VSetGradientBgMode,group);
11493   theCommands.Add("vsetcolorbg",
11494     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
11495     __FILE__,VSetColorBg,group);
11496   theCommands.Add("vsetdefaultbg",
11497     "vsetdefaultbg r g b\n"
11498     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
11499     "\n\t\t: Set default viewer background fill color (flat/gradient).",
11500     __FILE__,VSetDefaultBg,group);
11501   theCommands.Add("vscale",
11502     "vscale          : vscale X Y Z",
11503     __FILE__,VScale,group);
11504   theCommands.Add("vzbufftrihedron",
11505             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
11506     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
11507     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
11508     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
11509     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
11510     "\n\t\t: Displays a trihedron",
11511     __FILE__,VZBuffTrihedron,group);
11512   theCommands.Add("vrotate",
11513     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
11514     "\n                : Option -mouseStart starts rotation according to the mouse position"
11515     "\n                : Option -mouseMove continues rotation with angle computed"
11516     "\n                : from last and new mouse position."
11517     "\n                : vrotate AX AY AZ [X Y Z]",
11518     __FILE__,VRotate,group);
11519   theCommands.Add("vzoom",
11520     "vzoom           : vzoom coef",
11521     __FILE__,VZoom,group);
11522   theCommands.Add("vpan",
11523     "vpan            : vpan dx dy",
11524     __FILE__,VPan,group);
11525   theCommands.Add("vexport",
11526     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
11527     " : exports the view to a vector file of a given format"
11528     " : notice that EMF format requires patched gl2ps",
11529     __FILE__,VExport,group);
11530   theCommands.Add("vcolorscale",
11531     "vcolorscale name [-noupdate|-update] [-demo]"
11532     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
11533     "\n\t\t:       [-font HeightFont=20]"
11534     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
11535     "\n\t\t:       [-smoothTransition {on|off}=off]"
11536     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
11537     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
11538     "\n\t\t:       [-textpos {left|right|center|none}=right]"
11539     "\n\t\t:       [-labelAtBorder {on|off}=on]"
11540     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
11541     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
11542     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
11543     "\n\t\t:       [-xy Left=0 Bottom=0]"
11544     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
11545     "\n\t\t:  -colors   - set colors for all intervals"
11546     "\n\t\t:  -color    - set color for specific interval"
11547     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
11548     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
11549     "\n\t\t:              at border means the value inbetween neighbor intervals,"
11550     "\n\t\t:              at center means the center value within current interval"
11551     "\n\t\t:  -labels   - set labels for all intervals"
11552     "\n\t\t:  -freeLabels - same as -labels but does not require"
11553     "\n\t\t:              matching the number of intervals"
11554     "\n\t\t:  -label    - set label for specific interval"
11555     "\n\t\t:  -title    - set title"
11556     "\n\t\t:  -reversed - setup smooth color transition between intervals"
11557     "\n\t\t:  -smoothTransition - swap colorscale direction"
11558     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
11559     __FILE__, VColorScale, group);
11560   theCommands.Add("vgraduatedtrihedron",
11561     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
11562     "\t[-namefont Name] [-valuesfont Name]\n"
11563     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
11564     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
11565     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
11566     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
11567     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
11568     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
11569     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
11570     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
11571     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
11572     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
11573     " - Displays or erases graduated trihedron"
11574     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
11575     " - namefont - font of axes names. Default: Arial\n"
11576     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
11577     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
11578     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
11579     " - valuesfont - font of axes values. Default: Arial\n"
11580     " - xcolor, ycolor, zcolor - color of axis and values\n"
11581     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
11582     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
11583     __FILE__,VGraduatedTrihedron,group);
11584   theCommands.Add("vtile" ,
11585             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
11586     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
11587     "\n\t\t:  -totalSize the size of virtual bigger viewport"
11588     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
11589     "\n\t\t:  -lowerLeft tile offset as lower left corner"
11590     "\n\t\t:  -upperLeft tile offset as upper left corner",
11591     __FILE__, VTile, group);
11592   theCommands.Add("vzlayer",
11593               "vzlayer [layerId]"
11594       "\n\t\t:         [-add|-delete|-get|-settings]"
11595       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
11596       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
11597       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
11598       "\n\t\t: ZLayer list management:"
11599       "\n\t\t:   -add      add new z layer to viewer and print its id"
11600       "\n\t\t:   -delete   delete z layer"
11601       "\n\t\t:   -get      print sequence of z layers"
11602       "\n\t\t:   -settings print status of z layer settings"
11603       "\n\t\t:   -disable  disables given setting"
11604       "\n\t\t:   -enable   enables  given setting",
11605     __FILE__,VZLayer,group);
11606   theCommands.Add("vlayerline",
11607     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
11608     __FILE__,VLayerLine,group);
11609   theCommands.Add ("vgrid",
11610     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
11611     " : Mode - rectangular or circular"
11612     " : Type - lines or points",
11613     __FILE__, VGrid, group);
11614   theCommands.Add ("vpriviledgedplane",
11615     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
11616     "\n\t\t:   Ox, Oy, Oz - plane origin"
11617     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
11618     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
11619     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
11620     __FILE__, VPriviledgedPlane, group);
11621   theCommands.Add ("vconvert",
11622     "vconvert v [Mode={window|view}]"
11623     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
11624     "\n\t\t: vconvert x y z [Mode={window|grid}]"
11625     "\n\t\t:   window - convert to window coordinates, pixels"
11626     "\n\t\t:   view   - convert to view projection plane"
11627     "\n\t\t:   grid   - convert to model coordinates, given on grid"
11628     "\n\t\t:   ray    - convert projection ray to model coordiantes"
11629     "\n\t\t: - vconvert v window : convert view to window;"
11630     "\n\t\t: - vconvert v view   : convert window to view;"
11631     "\n\t\t: - vconvert x y window : convert view to window;"
11632     "\n\t\t: - vconvert x y view : convert window to view;"
11633     "\n\t\t: - vconvert x y : convert window to model;"
11634     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
11635     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
11636     "\n\t\t: - vconvert x y z window : convert model to window;"
11637     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
11638     "\n\t\t: Converts the given coordinates to window/view/model space.",
11639     __FILE__, VConvert, group);
11640   theCommands.Add ("vfps",
11641     "vfps [framesNb=100] : estimate average frame rate for active view",
11642     __FILE__, VFps, group);
11643   theCommands.Add ("vgldebug",
11644             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
11645     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
11646     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
11647     "\n\t\t: Debug context can be requested only on Windows"
11648     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
11649     "\n\t\t:  -sync     - request synchronized debug GL context"
11650     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
11651     "\n\t\t:              which are suppressed by default,"
11652     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
11653     "\n\t\t:              which are suppressed by default",
11654     __FILE__, VGlDebug, group);
11655   theCommands.Add ("vvbo",
11656     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
11657     __FILE__, VVbo, group);
11658   theCommands.Add ("vstereo",
11659             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
11660     "\n\t\t:         [-anaglyph Filter]"
11661     "\n\t\t: Control stereo output mode. Available modes for -mode:"
11662     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
11663     "\n\t\t:                     requires driver support."
11664     "\n\t\t:                     Should be called BEFORE vinit!"
11665     "\n\t\t:  anaglyph         - Anaglyph glasses"
11666     "\n\t\t:  rowInterlaced    - row-interlaced display"
11667     "\n\t\t:  columnInterlaced - column-interlaced display"
11668     "\n\t\t:  chessBoard       - chess-board output"
11669     "\n\t\t:  sideBySide       - horizontal pair"
11670     "\n\t\t:  overUnder        - vertical   pair"
11671     "\n\t\t: Available Anaglyph filters for -anaglyph:"
11672     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
11673     "\n\t\t:  greenMagentaSimple",
11674     __FILE__, VStereo, group);
11675   theCommands.Add ("vcaps",
11676             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
11677     "\n\t\t:       [-compatibleProfile {0|1}]"
11678     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
11679     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
11680     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
11681     "\n\t\t: Modify particular graphic driver options:"
11682     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
11683     "\n\t\t:             built-in GLSL programs"
11684     "\n\t\t:            (requires compatible profile)"
11685     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
11686     "\n\t\t:             arrays to GPU memory)"
11687     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
11688     "\n\t\t:  vsync    - switch VSync on or off"
11689     "\n\t\t:  winBuffer - allow using window buffer for rendering"
11690     "\n\t\t: Context creation options:"
11691     "\n\t\t:  softMode          - software OpenGL implementation"
11692     "\n\t\t:  compatibleProfile - backward-compatible profile"
11693     "\n\t\t:  quadbuffer        - QuadBuffer"
11694     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
11695     "\n\t\t: rendering paths producing the same visual result when"
11696     "\n\t\t: possible."
11697     "\n\t\t: Command is intended for testing old hardware compatibility.",
11698     __FILE__, VCaps, group);
11699   theCommands.Add ("vmemgpu",
11700     "vmemgpu [f]: print system-dependent GPU memory information if available;"
11701     " with f option returns free memory in bytes",
11702     __FILE__, VMemGpu, group);
11703   theCommands.Add ("vreadpixel",
11704     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
11705     " : Read pixel value for active view",
11706     __FILE__, VReadPixel, group);
11707   theCommands.Add("diffimage",
11708             "diffimage imageFile1 imageFile2 [diffImageFile]"
11709     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
11710     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
11711     "\n\t\t: Compare two images by content and generate difference image."
11712     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
11713     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
11714     __FILE__, VDiffImage, group);
11715   theCommands.Add ("vselect",
11716     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
11717     "- emulates different types of selection:\n"
11718     "- 1) single click selection\n"
11719     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
11720     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
11721     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
11722     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
11723     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
11724     " (partial inclusion - overlap - is not allowed by default)\n"
11725     "- 5) any of these selections with shift button pressed",
11726     __FILE__, VSelect, group);
11727   theCommands.Add ("vmoveto",
11728     "vmoveto x y"
11729     "- emulates cursor movement to pixel postion (x,y)",
11730     __FILE__, VMoveTo, group);
11731   theCommands.Add ("vviewparams",
11732               "vviewparams [-args] [-scale [s]]"
11733       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
11734       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
11735       "\n\t\t: Manage current view parameters or prints all"
11736       "\n\t\t: current values when called without argument."
11737       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
11738       "\n\t\t:   -eye  [x y z] prints or sets eye location"
11739       "\n\t\t:   -at   [x y z] prints or sets center of look"
11740       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
11741       "\n\t\t:   -proj [x y z] prints or sets direction of look"
11742       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
11743       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
11744       "\n\t\t:                 or changes the size of its maximum dimension"
11745       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
11746     __FILE__, VViewParams, group);
11747
11748   theCommands.Add("vanimation", "Alias for vanim",
11749     __FILE__, VAnimation, group);
11750
11751   theCommands.Add("vanim",
11752             "List existing animations:"
11753     "\n\t\t:  vanim"
11754     "\n\t\t: Animation playback:"
11755     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
11756     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
11757     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
11758     "\n\t\t:   -freeLook skip camera animations"
11759     "\n\t\t:   -lockLoop disable any interactions"
11760     "\n\t\t:"
11761     "\n\t\t: Animation definition:"
11762     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
11763     "\n\t\t:        [start TimeSec] [duration TimeSec]"
11764     "\n\t\t:"
11765     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
11766     "\n\t\t: specifies nested animations."
11767     "\n\t\t: There is no syntax to explicitly add new animation,"
11768     "\n\t\t: and all non-existing animations within the name will be"
11769     "\n\t\t: implicitly created on first use (including parents)."
11770     "\n\t\t:"
11771     "\n\t\t: Each animation might define the SINGLE action (see below),"
11772     "\n\t\t: like camera transition, object transformation or custom callback."
11773     "\n\t\t: Child animations can be used for defining concurrent actions."
11774     "\n\t\t:"
11775     "\n\t\t: Camera animation:"
11776     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
11777     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
11778     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
11779     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
11780     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
11781     "\n\t\t:   -atX    camera Center positions pair"
11782     "\n\t\t:   -upX    camera Up directions pair"
11783     "\n\t\t:   -scaleX camera Scale factors pair"
11784     "\n\t\t: Object animation:"
11785     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
11786     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
11787     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
11788     "\n\t\t:   -locX   object Location points pair (translation)"
11789     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
11790     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
11791     "\n\t\t: Custom callback:"
11792     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
11793     "\n\t\t:   %Pts        overall animation presentation timestamp"
11794     "\n\t\t:   %LocalPts   local animation timestamp"
11795     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
11796     "\n\t\t:"
11797     "\n\t\t: Video recording:"
11798     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
11799     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
11800     "\n\t\t:             [-crf Value] [-preset Preset]"
11801     "\n\t\t:   -fps     video framerate"
11802     "\n\t\t:   -format  file format, container (matroska, etc.)"
11803     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
11804     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
11805     "\n\t\t:   -crf     constant rate factor (specific to codec)"
11806     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
11807     __FILE__, VAnimation, group);
11808
11809   theCommands.Add("vchangeselected",
11810     "vchangeselected shape"
11811     "- adds to shape to selection or remove one from it",
11812                 __FILE__, VChangeSelected, group);
11813   theCommands.Add ("vnbselected",
11814     "vnbselected"
11815     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
11816   theCommands.Add ("vcamera",
11817               "vcamera [-ortho] [-projtype]"
11818       "\n\t\t:         [-persp]"
11819       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
11820       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
11821       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
11822       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
11823       "\n\t\t: Manage camera parameters."
11824       "\n\t\t: Prints current value when option called without argument."
11825       "\n\t\t: Orthographic camera:"
11826       "\n\t\t:   -ortho      activate orthographic projection"
11827       "\n\t\t: Perspective camera:"
11828       "\n\t\t:   -persp      activate perspective  projection (mono)"
11829       "\n\t\t:   -fovy       field of view in y axis, in degrees"
11830       "\n\t\t:   -distance   distance of eye from camera center"
11831       "\n\t\t: Stereoscopic camera:"
11832       "\n\t\t:   -stereo     perspective  projection (stereo)"
11833       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
11834       "\n\t\t:   -rightEye   perspective  projection (right eye)"
11835       "\n\t\t:   -iod        intraocular distance value"
11836       "\n\t\t:   -iodType    distance type, absolute or relative"
11837       "\n\t\t:   -zfocus     stereographic focus value"
11838       "\n\t\t:   -zfocusType focus type, absolute or relative",
11839     __FILE__, VCamera, group);
11840   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
11841     "- vautozfit [on={1|0}] [scale]\n"
11842     "    Prints or changes parameters of automatic z-fit mode:\n"
11843     "   \"on\" - turns automatic z-fit on or off\n"
11844     "   \"scale\" - specifies factor to scale computed z range.\n",
11845     __FILE__, VAutoZFit, group);
11846   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
11847     "   vzrange                - without parameters shows current values\n"
11848     "   vzrange [znear] [zfar] - applies provided values to view",
11849     __FILE__,VZRange, group);
11850   theCommands.Add ("vpurgedisplay",
11851     "vpurgedisplay"
11852     "- removes structures which don't belong to objects displayed in neutral point",
11853     __FILE__, VPurgeDisplay, group);
11854   theCommands.Add("vsetviewsize",
11855     "vsetviewsize size",
11856     __FILE__,VSetViewSize,group);
11857   theCommands.Add("vmoveview",
11858     "vmoveview Dx Dy Dz [Start = 1|0]",
11859     __FILE__,VMoveView,group);
11860   theCommands.Add("vtranslateview",
11861     "vtranslateview Dx Dy Dz [Start = 1|0)]",
11862     __FILE__,VTranslateView,group);
11863   theCommands.Add("vturnview",
11864     "vturnview Ax Ay Az [Start = 1|0]",
11865     __FILE__,VTurnView,group);
11866   theCommands.Add("vtextureenv",
11867     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
11868     "or user-defined file and optionally applying texture mapping parameters\n"
11869     "                  Usage:\n"
11870     "                  vtextureenv off - disables environment mapping\n"
11871     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
11872     "                              std_texture = (0..7)\n"
11873     "                              rep         = {clamp|repeat}\n"
11874     "                              mod         = {decal|modulate}\n"
11875     "                              flt         = {nearest|bilinear|trilinear}\n"
11876     "                              ss, st      - scale factors for s and t texture coordinates\n"
11877     "                              ts, tt      - translation for s and t texture coordinates\n"
11878     "                              rot         - texture rotation angle in degrees",
11879     __FILE__, VTextureEnv, group);
11880   theCommands.Add("vhlr",
11881             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
11882       "\n\t\t: Hidden Line Removal algorithm."
11883       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
11884       "\n\t\t:   -algoType   type of HLR algorithm.\n",
11885     __FILE__,VHLR,group);
11886   theCommands.Add("vhlrtype",
11887               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
11888       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
11889       "\n\t\t:   'algo' - exact HLR algorithm is applied"
11890       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
11891       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
11892     __FILE__,VHLRType,group);
11893   theCommands.Add("vclipplane",
11894               "vclipplane planeName [{0|1}]"
11895       "\n\t\t:   [-equation A B C D]"
11896       "\n\t\t:   [-set|-unset [objects|views]]"
11897       "\n\t\t:   [-maxPlanes]"
11898       "\n\t\t:   [-capping {0|1}]"
11899       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
11900       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
11901       "\n\t\t:       [-texRotate Angle]"
11902       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
11903       "\n\t\t:       [-useObjShader {0|1}]"
11904       "\n\t\t: Clipping planes management:"
11905       "\n\t\t:   -maxPlanes   print plane limit for view"
11906       "\n\t\t:   -delete      delete plane with given name"
11907       "\n\t\t:   {off|on|0|1} turn clipping on/off"
11908       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
11909       "\n\t\t:                applied to active View when list is omitted"
11910       "\n\t\t:   -equation A B C D change plane equation"
11911       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
11912       "\n\t\t: Capping options:"
11913       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
11914       "\n\t\t:   -color R G B          set capping color"
11915       "\n\t\t:   -texName Texture      set capping texture"
11916       "\n\t\t:   -texScale SX SY       set capping tex scale"
11917       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
11918       "\n\t\t:   -texRotate Angle      set capping tex rotation"
11919       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
11920       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
11921       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
11922       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
11923       __FILE__, VClipPlane, group);
11924   theCommands.Add("vdefaults",
11925                "vdefaults [-absDefl value]"
11926        "\n\t\t:           [-devCoeff value]"
11927        "\n\t\t:           [-angDefl value]"
11928        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
11929     , __FILE__, VDefaults, group);
11930   theCommands.Add("vlight",
11931     "tool to manage light sources, without arguments shows list of lights."
11932     "\n    Main commands: "
11933     "\n      'clear' to clear lights"
11934     "\n      '{def}aults' to load deafault lights"
11935     "\n      'add' (or 'new') <type> to add any light source"
11936     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
11937     "\n      'change' <lightId> to edit light source with specified lightId"
11938     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
11939     "\n        {pos}ition X Y Z"
11940     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
11941     "\n        color colorName"
11942     "\n        {head}light 0|1"
11943     "\n        {sm}oothness value"
11944     "\n        {int}ensity value"
11945     "\n        {constAtten}uation value"
11946     "\n        {linearAtten}uation value"
11947     "\n        angle angleDeg"
11948     "\n        {spotexp}onent value"
11949     "\n        local|global"
11950     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
11951     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
11952     __FILE__, VLight, group);
11953   theCommands.Add("vraytrace",
11954             "vraytrace [0|1]"
11955     "\n\t\t: Turns on/off ray-tracing renderer."
11956     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
11957     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
11958     __FILE__, VRenderParams, group);
11959   theCommands.Add("vrenderparams",
11960     "\n    Manages rendering parameters: "
11961     "\n      '-raster'                   Disables GPU ray-tracing"
11962     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
11963     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
11964     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
11965     "\n      '-rendScale    value        Rendering resolution scale factor"
11966     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
11967     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
11968     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
11969     "\n      '-reflections  on|off'      Enables/disables specular reflections"
11970     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
11971     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
11972     "\n      '-gi           on|off'      Enables/disables global illumination effects"
11973     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
11974     "\n      '-env          on|off'      Enables/disables environment map background"
11975     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
11976     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
11977     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
11978     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
11979     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
11980     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
11981     "\n      '-shadingModel model'       Controls shading model from enumeration"
11982     "\n                                  color, flat, gouraud, phong"
11983     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
11984     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
11985     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
11986     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
11987     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
11988     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
11989     "\n    Unlike vcaps, these parameters dramatically change visual properties."
11990     "\n    Command is intended to control presentation quality depending on"
11991     "\n    hardware capabilities and performance.",
11992     __FILE__, VRenderParams, group);
11993   theCommands.Add("vfrustumculling",
11994     "vfrustumculling [toEnable]: enables/disables objects clipping",
11995     __FILE__,VFrustumCulling,group);
11996   theCommands.Add("vhighlightselected",
11997     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
11998     "Without arguments it shows if highlighting of selected objects is enabled now.",
11999     __FILE__,VHighlightSelected,group);
12000   theCommands.Add ("vplace",
12001             "vplace dx dy"
12002     "\n\t\t: Places the point (in pixels) at the center of the window",
12003     __FILE__, VPlace, group);
12004   theCommands.Add("vxrotate",
12005     "vxrotate",
12006     __FILE__,VXRotate,group);
12007
12008     theCommands.Add("vmanipulator",
12009       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
12010       "\n    tool to create and manage AIS manipulators."
12011       "\n    Options: "
12012       "\n      '-attach AISObject'                 attach manipulator to AISObject"
12013       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
12014       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
12015       "\n      '-enableModes    {0|1}'             enable modes when attaching"
12016       "\n      '-detach'                           detach manipulator"
12017       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
12018       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
12019       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
12020       "\n      '-move x y z'                     - move attached object"
12021       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
12022       "\n      '-scale factor'                   - scale attached object"
12023       "\n      '-autoActivate      {0|1}'        - set activation on detection"
12024       "\n      '-followTranslation {0|1}'        - set following translation transform"
12025       "\n      '-followRotation    {0|1}'        - set following rotation transform"
12026       "\n      '-gap value'                      - set gap between sub-parts"
12027       "\n      '-part axis mode    {0|1}'        - set visual part"
12028       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
12029       "\n      '-size value'                     - set size of manipulator"
12030       "\n      '-zoomable {0|1}'                 - set zoom persistence",
12031     __FILE__, VManipulator, group);
12032
12033   theCommands.Add("vselprops",
12034     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
12035     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
12036     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
12037     "\n    -pickStrategy {first|topmost} : defines picking strategy"
12038     "\n                            'first'   to pick first acceptable (default)"
12039     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
12040     "\n    -pixTol    value        : sets up pixel tolerance"
12041     "\n    -dispMode  dispMode     : sets display mode for highlighting"
12042     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
12043     "\n    -color     {name|r g b} : sets highlight color"
12044     "\n    -transp    value        : sets transparency coefficient for highlight"
12045     "\n    -material  material     : sets highlight material"
12046     "\n    -print                  : prints current state of all mentioned parameters",
12047     __FILE__, VSelectionProperties, group);
12048
12049   theCommands.Add ("vseldump",
12050                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
12051                    "\n\t\t: Generate an image based on detection results:"
12052                    "\n\t\t:   depth       normalized depth values"
12053                    "\n\t\t:   unnormDepth unnormalized depth values"
12054                    "\n\t\t:   object      color of detected object"
12055                    "\n\t\t:   owner       color of detected owner"
12056                    "\n\t\t:   selMode     color of selection mode"
12057                    "\n\t\t:   entity      color of etected entity",
12058                    __FILE__, VDumpSelectionImage, group);
12059
12060 #if defined(_WIN32)
12061   theCommands.Add("vprogressive",
12062     "vprogressive",
12063     __FILE__, VProgressiveMode, group);
12064 #endif
12065 }