37900c1e2439f079a013a7e72e54a8fafc959bb6
[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 << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4659   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4660   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4661   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4662   {
4663     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4664   }
4665 }
4666
4667 //==============================================================================
4668 //function : VZLayer
4669 //purpose  : Test z layer operations for v3d viewer
4670 //==============================================================================
4671 static int VZLayer (Draw_Interpretor& theDI,
4672                     Standard_Integer  theArgNb,
4673                     const char**      theArgVec)
4674 {
4675   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4676   if (aContextAIS.IsNull())
4677   {
4678     std::cout << "No active viewer!\n";
4679     return 1;
4680   }
4681
4682   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4683   if (theArgNb < 2)
4684   {
4685     TColStd_SequenceOfInteger aLayers;
4686     aViewer->GetAllZLayers (aLayers);
4687     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4688     {
4689       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4690       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4691       printZLayerInfo (theDI, aSettings);
4692     }
4693     return 1;
4694   }
4695
4696   Standard_Integer anArgIter = 1;
4697   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4698   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4699   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4700   {
4701     ++anArgIter;
4702   }
4703
4704   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4705   if (aFirstArg.IsIntegerValue())
4706   {
4707     ++anArgIter;
4708     aLayerId = aFirstArg.IntegerValue();
4709   }
4710   else
4711   {
4712     aFirstArg.LowerCase();
4713     if (aFirstArg == "default"
4714      || aFirstArg == "def")
4715     {
4716       aLayerId = Graphic3d_ZLayerId_Default;
4717       ++anArgIter;
4718     }
4719     else if (aFirstArg == "top")
4720     {
4721       aLayerId = Graphic3d_ZLayerId_Top;
4722       ++anArgIter;
4723     }
4724     else if (aFirstArg == "topmost")
4725     {
4726       aLayerId = Graphic3d_ZLayerId_Topmost;
4727       ++anArgIter;
4728     }
4729     else if (aFirstArg == "overlay"
4730           || aFirstArg == "toposd")
4731     {
4732       aLayerId = Graphic3d_ZLayerId_TopOSD;
4733       ++anArgIter;
4734     }
4735     else if (aFirstArg == "underlay"
4736           || aFirstArg == "botosd")
4737     {
4738       aLayerId = Graphic3d_ZLayerId_BotOSD;
4739       ++anArgIter;
4740     }
4741     else
4742     {
4743       TColStd_SequenceOfInteger aLayers;
4744       aViewer->GetAllZLayers (aLayers);
4745       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4746       {
4747         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4748         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4749         {
4750           aLayerId = aLayeriter.Value();
4751           ++anArgIter;
4752           break;
4753         }
4754       }
4755     }
4756   }
4757
4758   for (; anArgIter < theArgNb; ++anArgIter)
4759   {
4760     // perform operation
4761     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4762     anArg.LowerCase();
4763     if (anUpdateTool.parseRedrawMode (anArg))
4764     {
4765       //
4766     }
4767     else if (anArg == "-add"
4768           || anArg == "add")
4769     {
4770       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4771       if (!aViewer->AddZLayer (aLayerId))
4772       {
4773         std::cout << "Error: can not add a new z layer!\n";
4774         return 0;
4775       }
4776
4777       theDI << aLayerId;
4778     }
4779     else if (anArg == "-del"
4780           || anArg == "-delete"
4781           || anArg == "del")
4782     {
4783       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4784       {
4785         if (++anArgIter >= theArgNb)
4786         {
4787           std::cout << "Syntax error: id of z layer to remove is missing\n";
4788           return 1;
4789         }
4790
4791         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4792       }
4793
4794       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4795        || aLayerId == Graphic3d_ZLayerId_Default
4796        || aLayerId == Graphic3d_ZLayerId_Top
4797        || aLayerId == Graphic3d_ZLayerId_Topmost
4798        || aLayerId == Graphic3d_ZLayerId_TopOSD
4799        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4800       {
4801         std::cout << "Syntax error: standard Z layer can not be removed\n";
4802         return 1;
4803       }
4804
4805       // move all object displayed in removing layer to default layer
4806       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4807            anObjIter.More(); anObjIter.Next())
4808       {
4809         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4810         if (aPrs.IsNull()
4811          || aPrs->ZLayer() != aLayerId)
4812         {
4813           continue;
4814         }
4815         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4816       }
4817
4818       if (!aViewer->RemoveZLayer (aLayerId))
4819       {
4820         std::cout << "Z layer can not be removed!\n";
4821       }
4822       else
4823       {
4824         theDI << aLayerId << " ";
4825       }
4826     }
4827     else if (anArg == "-get"
4828           || anArg == "get")
4829     {
4830       TColStd_SequenceOfInteger aLayers;
4831       aViewer->GetAllZLayers (aLayers);
4832       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4833       {
4834         theDI << aLayeriter.Value() << " ";
4835       }
4836
4837       theDI << "\n";
4838     }
4839     else if (anArg == "-name")
4840     {
4841       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4842       {
4843         std::cout << "Syntax error: id of Z layer is missing\n";
4844         return 1;
4845       }
4846
4847       if (++anArgIter >= theArgNb)
4848       {
4849         std::cout << "Syntax error: name is missing\n";
4850         return 1;
4851       }
4852
4853       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4854       aSettings.SetName (theArgVec[anArgIter]);
4855       aViewer->SetZLayerSettings (aLayerId, aSettings);
4856     }
4857     else if (anArg == "-origin")
4858     {
4859       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4860       {
4861         std::cout << "Syntax error: id of Z layer is missing\n";
4862         return 1;
4863       }
4864
4865       if (anArgIter + 2 >= theArgNb)
4866       {
4867         std::cout << "Syntax error: origin coordinates are missing\n";
4868         return 1;
4869       }
4870
4871       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4872       gp_XYZ anOrigin;
4873       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4874       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4875       anOrigin.SetZ (0.0);
4876       if (anArgIter + 3 < theArgNb)
4877       {
4878         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4879         anArgIter += 3;
4880       }
4881       else
4882       {
4883         anArgIter += 2;
4884       }
4885       aSettings.SetOrigin (anOrigin);
4886       aViewer->SetZLayerSettings (aLayerId, aSettings);
4887     }
4888     else if (anArg == "-settings"
4889           || anArg == "settings")
4890     {
4891       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4892       {
4893         if (++anArgIter >= theArgNb)
4894         {
4895           std::cout << "Syntax error: id of Z layer is missing\n";
4896           return 1;
4897         }
4898
4899         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4900       }
4901
4902       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4903       printZLayerInfo (theDI, aSettings);
4904     }
4905     else if (anArg == "-enable"
4906           || anArg == "enable"
4907           || anArg == "-disable"
4908           || anArg == "disable")
4909     {
4910       const Standard_Boolean toEnable = anArg == "-enable"
4911                                      || anArg == "enable";
4912       if (++anArgIter >= theArgNb)
4913       {
4914         std::cout << "Syntax error: option name is missing\n";
4915         return 1;
4916       }
4917
4918       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4919       aSubOp.LowerCase();
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       if (aSubOp == "depthtest"
4933        || aSubOp == "test")
4934       {
4935         aSettings.SetEnableDepthTest (toEnable);
4936       }
4937       else if (aSubOp == "depthwrite"
4938             || aSubOp == "write")
4939       {
4940         aSettings.SetEnableDepthWrite (toEnable);
4941       }
4942       else if (aSubOp == "depthclear"
4943             || aSubOp == "clear")
4944       {
4945         aSettings.SetClearDepth (toEnable);
4946       }
4947       else if (aSubOp == "depthoffset"
4948             || aSubOp == "offset")
4949       {
4950         Graphic3d_PolygonOffset aParams;
4951         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4952         if (toEnable)
4953         {
4954           if (anArgIter + 2 >= theArgNb)
4955           {
4956             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4957             return 1;
4958           }
4959
4960           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4961           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4962         }
4963         aSettings.SetPolygonOffset (aParams);
4964       }
4965       else if (aSubOp == "positiveoffset"
4966             || aSubOp == "poffset")
4967       {
4968         if (toEnable)
4969         {
4970           aSettings.SetDepthOffsetPositive();
4971         }
4972         else
4973         {
4974           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4975         }
4976       }
4977       else if (aSubOp == "negativeoffset"
4978             || aSubOp == "noffset")
4979       {
4980         if (toEnable)
4981         {
4982           aSettings.SetDepthOffsetNegative();
4983         }
4984         else
4985         {
4986           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4987         }
4988       }
4989       else if (aSubOp == "textureenv")
4990       {
4991         aSettings.SetEnvironmentTexture (toEnable);
4992       }
4993
4994       aViewer->SetZLayerSettings (aLayerId, aSettings);
4995     }
4996     else
4997     {
4998       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4999       return 1;
5000     }
5001   }
5002
5003   return 0;
5004 }
5005
5006 // The interactive presentation of 2d layer item
5007 // for "vlayerline" command it provides a presentation of
5008 // line with user-defined linewidth, linetype and transparency.
5009 class V3d_LineItem : public AIS_InteractiveObject
5010 {
5011 public:
5012   // CASCADE RTTI
5013   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5014
5015   // constructor
5016   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5017                                Standard_Real X2, Standard_Real Y2,
5018                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5019                                Standard_Real theWidth    = 0.5,
5020                                Standard_Real theTransp   = 1.0);
5021
5022   private:
5023
5024   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5025                 const Handle(Prs3d_Presentation)& thePresentation,
5026                 const Standard_Integer theMode) Standard_OVERRIDE;
5027
5028   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5029                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5030   {}
5031
5032 private:
5033
5034   Standard_Real       myX1, myY1, myX2, myY2;
5035   Aspect_TypeOfLine   myType;
5036   Standard_Real       myWidth;
5037 };
5038
5039 // default constructor for line item
5040 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5041                            Standard_Real X2, Standard_Real Y2,
5042                            Aspect_TypeOfLine theType,
5043                            Standard_Real theWidth,
5044                            Standard_Real theTransp) :
5045   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5046   myType(theType), myWidth(theWidth)
5047 {
5048   SetTransparency (1-theTransp);
5049 }
5050
5051 // render line
5052 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5053                             const Handle(Prs3d_Presentation)& thePresentation,
5054                             const Standard_Integer /*theMode*/)
5055 {
5056   thePresentation->Clear();
5057   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5058   Standard_Integer aWidth, aHeight;
5059   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5060   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5061   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5062   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5063   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5064   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5065   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5066   aGroup->AddPrimitiveArray (aPrim);
5067 }
5068
5069 //=============================================================================
5070 //function : VLayerLine
5071 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5072 //         : linewidth, transparency coefficient
5073 //============================================================================
5074 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5075 {
5076   // get the active view
5077   Handle(V3d_View) aView = ViewerTest::CurrentView();
5078   if (aView.IsNull())
5079   {
5080     di << "Call vinit before!\n";
5081     return 1;
5082   }
5083   else if (argc < 5)
5084   {
5085     di << "Use: " << argv[0];
5086     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5087     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5088     di << "              0 - solid  \n";
5089     di << "              1 - dashed \n";
5090     di << "              2 - dot    \n";
5091     di << "              3 - dashdot\n";
5092     di << " transparency : { 0.0 - 1.0 } \n";
5093     di << "                  0.0 - transparent\n";
5094     di << "                  1.0 - visible    \n";
5095     return 1;
5096   }
5097
5098   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5099   // get the input params
5100   Standard_Real X1 = Draw::Atof(argv[1]);
5101   Standard_Real Y1 = Draw::Atof(argv[2]);
5102   Standard_Real X2 = Draw::Atof(argv[3]);
5103   Standard_Real Y2 = Draw::Atof(argv[4]);
5104
5105   Standard_Real aWidth = 0.5;
5106   Standard_Real aTransparency = 1.0;
5107
5108   // has width
5109   if (argc > 5)
5110     aWidth = Draw::Atof(argv[5]);
5111
5112   // select appropriate line type
5113   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5114   if (argc > 6
5115   && !ViewerTest::ParseLineType (argv[6], aLineType))
5116   {
5117     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5118     return 1;
5119   }
5120
5121   // has transparency
5122   if (argc > 7)
5123   {
5124     aTransparency = Draw::Atof(argv[7]);
5125     if (aTransparency < 0 || aTransparency > 1.0)
5126       aTransparency = 1.0;
5127   }
5128
5129   static Handle (V3d_LineItem) aLine;
5130   if (!aLine.IsNull())
5131   {
5132     aContext->Erase (aLine, Standard_False);
5133   }
5134   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5135                             aLineType, aWidth,
5136                             aTransparency);
5137
5138   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5139   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5140   aLine->SetToUpdate();
5141   aContext->Display (aLine, Standard_True);
5142
5143   return 0;
5144 }
5145
5146
5147 //==============================================================================
5148 //function : VGrid
5149 //purpose  :
5150 //==============================================================================
5151
5152 static int VGrid (Draw_Interpretor& /*theDI*/,
5153                   Standard_Integer  theArgNb,
5154                   const char**      theArgVec)
5155 {
5156   // get the active view
5157   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5158   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5159   if (aView.IsNull() || aViewer.IsNull())
5160   {
5161     std::cerr << "No active view. Please call vinit.\n";
5162     return 1;
5163   }
5164
5165   Aspect_GridType     aType = aViewer->GridType();
5166   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5167   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5168   Standard_Integer anIter = 1;
5169   for (; anIter < theArgNb; ++anIter)
5170   {
5171     const char* aValue = theArgVec[anIter];
5172     if (anUpdateTool.parseRedrawMode (aValue))
5173     {
5174       continue;
5175     }
5176     else if (*aValue == 'r')
5177     {
5178       aType = Aspect_GT_Rectangular;
5179     }
5180     else if (*aValue == 'c')
5181     {
5182       aType = Aspect_GT_Circular;
5183     }
5184     else if (*aValue == 'l')
5185     {
5186       aMode = Aspect_GDM_Lines;
5187     }
5188     else if (*aValue == 'p')
5189     {
5190       aMode = Aspect_GDM_Points;
5191     }
5192     else if (strcmp (aValue, "off" ) == 0)
5193     {
5194       aViewer->DeactivateGrid();
5195       return 0;
5196     }
5197     else
5198     {
5199       break;
5200     }
5201   }
5202
5203   Standard_Integer aTail = (theArgNb - anIter);
5204   if (aTail == 0)
5205   {
5206     aViewer->ActivateGrid (aType, aMode);
5207     return 0;
5208   }
5209   else if (aTail != 2 && aTail != 5)
5210   {
5211     std::cerr << "Incorrect arguments number! Usage:\n"
5212               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5213     return 1;
5214   }
5215
5216   Standard_Real anOriginX, anOriginY, aRotAngle;
5217   if (aType == Aspect_GT_Rectangular)
5218   {
5219     Standard_Real aRStepX, aRStepY;
5220     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5221
5222     anOriginX = Draw::Atof (theArgVec[anIter++]);
5223     anOriginY = Draw::Atof (theArgVec[anIter++]);
5224     if (aTail == 5)
5225     {
5226       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5227       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5228       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5229     }
5230     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5231     aViewer->ActivateGrid (aType, aMode);
5232   }
5233   else if (aType == Aspect_GT_Circular)
5234   {
5235     Standard_Real aRadiusStep;
5236     Standard_Integer aDivisionNumber;
5237     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5238
5239     anOriginX = Draw::Atof (theArgVec[anIter++]);
5240     anOriginY = Draw::Atof (theArgVec[anIter++]);
5241     if (aTail == 5)
5242     {
5243       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5244       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5245       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5246     }
5247
5248     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5249     aViewer->ActivateGrid (aType, aMode);
5250   }
5251
5252   return 0;
5253 }
5254
5255 //==============================================================================
5256 //function : VPriviledgedPlane
5257 //purpose  :
5258 //==============================================================================
5259
5260 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5261                               Standard_Integer  theArgNb,
5262                               const char**      theArgVec)
5263 {
5264   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5265   {
5266     std::cerr << "Error: wrong number of arguments! See usage:\n";
5267     theDI.PrintHelp (theArgVec[0]);
5268     return 1;
5269   }
5270
5271   // get the active viewer
5272   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5273   if (aViewer.IsNull())
5274   {
5275     std::cerr << "Error: no active viewer. Please call vinit.\n";
5276     return 1;
5277   }
5278
5279   if (theArgNb == 1)
5280   {
5281     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5282     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5283     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5284     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5285     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5286           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5287           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5288     return 0;
5289   }
5290
5291   Standard_Integer anArgIdx = 1;
5292   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5293   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5294   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5295   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5296   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5297   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5298
5299   gp_Ax3 aPriviledgedPlane;
5300   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5301   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5302   if (theArgNb > 7)
5303   {
5304     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5305     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5306     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5307     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5308     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5309   }
5310   else
5311   {
5312     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5313   }
5314
5315   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5316
5317   return 0;
5318 }
5319
5320 //==============================================================================
5321 //function : VConvert
5322 //purpose  :
5323 //==============================================================================
5324
5325 static int VConvert (Draw_Interpretor& theDI,
5326                      Standard_Integer  theArgNb,
5327                      const char**      theArgVec)
5328 {
5329   // get the active view
5330   Handle(V3d_View) aView = ViewerTest::CurrentView();
5331   if (aView.IsNull())
5332   {
5333     std::cerr << "Error: no active view. Please call vinit.\n";
5334     return 1;
5335   }
5336
5337   enum { Model, Ray, View, Window, Grid } aMode = Model;
5338
5339   // access coordinate arguments
5340   TColStd_SequenceOfReal aCoord;
5341   Standard_Integer anArgIdx = 1;
5342   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5343   {
5344     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5345     if (!anArg.IsRealValue())
5346     {
5347       break;
5348     }
5349     aCoord.Append (anArg.RealValue());
5350   }
5351
5352   // non-numeric argument too early
5353   if (aCoord.IsEmpty())
5354   {
5355     std::cerr << "Error: wrong number of arguments! See usage:\n";
5356     theDI.PrintHelp (theArgVec[0]);
5357     return 1;
5358   }
5359
5360   // collect all other arguments and options
5361   for (; anArgIdx < theArgNb; ++anArgIdx)
5362   {
5363     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5364     anArg.LowerCase();
5365     if      (anArg == "window") aMode = Window;
5366     else if (anArg == "view")   aMode = View;
5367     else if (anArg == "grid")   aMode = Grid;
5368     else if (anArg == "ray")    aMode = Ray;
5369     else
5370     {
5371       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5372       theDI.PrintHelp (theArgVec[0]);
5373       return 1;
5374     }
5375   }
5376
5377   // complete input checks
5378   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5379       (aCoord.Length() == 2 && theArgNb > 4) ||
5380       (aCoord.Length() == 3 && theArgNb > 5))
5381   {
5382     std::cerr << "Error: wrong number of arguments! See usage:\n";
5383     theDI.PrintHelp (theArgVec[0]);
5384     return 1;
5385   }
5386
5387   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5388   Standard_Integer aXYp[2] = {0, 0};
5389
5390   // convert one-dimensional coordinate
5391   if (aCoord.Length() == 1)
5392   {
5393     switch (aMode)
5394     {
5395       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5396       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5397       default:
5398         std::cerr << "Error: wrong arguments! See usage:\n";
5399         theDI.PrintHelp (theArgVec[0]);
5400         return 1;
5401     }
5402   }
5403
5404   // convert 2D coordinates from projection or view reference space
5405   if (aCoord.Length() == 2)
5406   {
5407     switch (aMode)
5408     {
5409       case Model :
5410         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5411         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5412         return 0;
5413
5414       case View :
5415         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5416         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5417         return 0;
5418
5419       case Window :
5420         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5421         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5422         return 0;
5423
5424       case Grid :
5425         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5426         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5427         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5428         return 0;
5429
5430       case Ray :
5431         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5432                                 (Standard_Integer) aCoord (2),
5433                                 aXYZ[0], aXYZ[1], aXYZ[2],
5434                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5435         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5436         return 0;
5437
5438       default:
5439         std::cerr << "Error: wrong arguments! See usage:\n";
5440         theDI.PrintHelp (theArgVec[0]);
5441         return 1;
5442     }
5443   }
5444
5445   // convert 3D coordinates from view reference space
5446   else if (aCoord.Length() == 3)
5447   {
5448     switch (aMode)
5449     {
5450       case Window :
5451         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5452         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5453         return 0;
5454
5455       case Grid :
5456         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5457         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5458         return 0;
5459
5460       default:
5461         std::cerr << "Error: wrong arguments! See usage:\n";
5462         theDI.PrintHelp (theArgVec[0]);
5463         return 1;
5464     }
5465   }
5466
5467   return 0;
5468 }
5469
5470 //==============================================================================
5471 //function : VFps
5472 //purpose  :
5473 //==============================================================================
5474
5475 static int VFps (Draw_Interpretor& theDI,
5476                  Standard_Integer  theArgNb,
5477                  const char**      theArgVec)
5478 {
5479   // get the active view
5480   Handle(V3d_View) aView = ViewerTest::CurrentView();
5481   if (aView.IsNull())
5482   {
5483     std::cerr << "No active view. Please call vinit.\n";
5484     return 1;
5485   }
5486
5487   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5488   if (aFramesNb <= 0)
5489   {
5490     std::cerr << "Incorrect arguments!\n";
5491     return 1;
5492   }
5493
5494   // the time is meaningless for first call
5495   // due to async OpenGl rendering
5496   aView->Redraw();
5497
5498   // redraw view in loop to estimate average values
5499   OSD_Timer aTimer;
5500   aTimer.Start();
5501   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5502   {
5503     aView->Redraw();
5504   }
5505   aTimer.Stop();
5506   Standard_Real aCpu;
5507   const Standard_Real aTime = aTimer.ElapsedTime();
5508   aTimer.OSD_Chronometer::Show (aCpu);
5509
5510   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5511   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5512
5513   // return statistics
5514   theDI << "FPS: " << aFpsAver << "\n"
5515         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5516
5517   // compute additional statistics in ray-tracing mode
5518   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5519
5520   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5521   {
5522     Standard_Integer aSizeX;
5523     Standard_Integer aSizeY;
5524
5525     aView->Window()->Size (aSizeX, aSizeY);
5526
5527     // 1 shadow ray and 1 secondary ray pew each bounce
5528     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5529
5530     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5531   }
5532
5533   return 0;
5534 }
5535
5536 //==============================================================================
5537 //function : VGlDebug
5538 //purpose  :
5539 //==============================================================================
5540
5541 static int VGlDebug (Draw_Interpretor& theDI,
5542                      Standard_Integer  theArgNb,
5543                      const char**      theArgVec)
5544 {
5545   Handle(OpenGl_GraphicDriver) aDriver;
5546   Handle(V3d_View) aView = ViewerTest::CurrentView();
5547   if (!aView.IsNull())
5548   {
5549     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5550   }
5551   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5552   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5553
5554   if (theArgNb < 2)
5555   {
5556     TCollection_AsciiString aDebActive, aSyncActive;
5557     if (aCaps == NULL)
5558     {
5559       aCaps = aDefCaps;
5560     }
5561     else
5562     {
5563       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5564                                                                   "GL_ARB_debug_output");
5565       aDebActive = isActive ? " (active)" : " (inactive)";
5566       if (isActive)
5567       {
5568         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5569         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5570       }
5571     }
5572
5573     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5574           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5575           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5576           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5577     return 0;
5578   }
5579
5580   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5581   {
5582     Standard_CString        anArg     = theArgVec[anArgIter];
5583     TCollection_AsciiString anArgCase (anArg);
5584     anArgCase.LowerCase();
5585     Standard_Boolean toEnableDebug = Standard_True;
5586     if (anArgCase == "-glsl"
5587      || anArgCase == "-glslwarn"
5588      || anArgCase == "-glslwarns"
5589      || anArgCase == "-glslwarnings")
5590     {
5591       Standard_Boolean toShowWarns = Standard_True;
5592       if (++anArgIter < theArgNb
5593       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5594       {
5595         --anArgIter;
5596       }
5597       aDefCaps->glslWarnings = toShowWarns;
5598       if (aCaps != NULL)
5599       {
5600         aCaps->glslWarnings = toShowWarns;
5601       }
5602     }
5603     else if (anArgCase == "-extra"
5604           || anArgCase == "-extramsg"
5605           || anArgCase == "-extramessages")
5606     {
5607       Standard_Boolean toShow = Standard_True;
5608       if (++anArgIter < theArgNb
5609       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5610       {
5611         --anArgIter;
5612       }
5613       aDefCaps->suppressExtraMsg = !toShow;
5614       if (aCaps != NULL)
5615       {
5616         aCaps->suppressExtraMsg = !toShow;
5617       }
5618     }
5619     else if (anArgCase == "-noextra"
5620           || anArgCase == "-noextramsg"
5621           || anArgCase == "-noextramessages")
5622     {
5623       Standard_Boolean toSuppress = Standard_True;
5624       if (++anArgIter < theArgNb
5625       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5626       {
5627         --anArgIter;
5628       }
5629       aDefCaps->suppressExtraMsg = toSuppress;
5630       if (aCaps != NULL)
5631       {
5632         aCaps->suppressExtraMsg = toSuppress;
5633       }
5634     }
5635     else if (anArgCase == "-sync")
5636     {
5637       Standard_Boolean toSync = Standard_True;
5638       if (++anArgIter < theArgNb
5639       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5640       {
5641         --anArgIter;
5642       }
5643       aDefCaps->contextSyncDebug = toSync;
5644       if (toSync)
5645       {
5646         aDefCaps->contextDebug = Standard_True;
5647       }
5648     }
5649     else if (anArgCase == "-debug")
5650     {
5651       if (++anArgIter < theArgNb
5652       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5653       {
5654         --anArgIter;
5655       }
5656       aDefCaps->contextDebug = toEnableDebug;
5657     }
5658     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5659           && (anArgIter + 1 == theArgNb))
5660     {
5661       // simple alias to turn on almost everything
5662       aDefCaps->contextDebug     = toEnableDebug;
5663       aDefCaps->contextSyncDebug = toEnableDebug;
5664       aDefCaps->glslWarnings     = toEnableDebug;
5665     }
5666     else
5667     {
5668       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5669       return 1;
5670     }
5671   }
5672
5673   return 0;
5674 }
5675
5676 //==============================================================================
5677 //function : VVbo
5678 //purpose  :
5679 //==============================================================================
5680
5681 static int VVbo (Draw_Interpretor& theDI,
5682                  Standard_Integer  theArgNb,
5683                  const char**      theArgVec)
5684 {
5685   const Standard_Boolean toSet    = (theArgNb > 1);
5686   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5687   if (toSet)
5688   {
5689     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5690   }
5691
5692   // get the context
5693   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5694   if (aContextAIS.IsNull())
5695   {
5696     if (!toSet)
5697     {
5698       std::cerr << "No active view!\n";
5699     }
5700     return 1;
5701   }
5702   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5703   if (!aDriver.IsNull())
5704   {
5705     if (!toSet)
5706     {
5707       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5708     }
5709     else
5710     {
5711       aDriver->ChangeOptions().vboDisable = toUseVbo;
5712     }
5713   }
5714
5715   return 0;
5716 }
5717
5718 //==============================================================================
5719 //function : VCaps
5720 //purpose  :
5721 //==============================================================================
5722
5723 static int VCaps (Draw_Interpretor& theDI,
5724                   Standard_Integer  theArgNb,
5725                   const char**      theArgVec)
5726 {
5727   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5728   Handle(OpenGl_GraphicDriver)   aDriver;
5729   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5730   if (!aContext.IsNull())
5731   {
5732     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5733     aCaps   = &aDriver->ChangeOptions();
5734   }
5735
5736   if (theArgNb < 2)
5737   {
5738     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5739     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5740     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5741     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5742     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5743     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5744     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5745     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5746     return 0;
5747   }
5748
5749   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5750   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5751   {
5752     Standard_CString        anArg     = theArgVec[anArgIter];
5753     TCollection_AsciiString anArgCase (anArg);
5754     anArgCase.LowerCase();
5755     if (anUpdateTool.parseRedrawMode (anArg))
5756     {
5757       continue;
5758     }
5759     else if (anArgCase == "-vsync"
5760           || anArgCase == "-swapinterval")
5761     {
5762       Standard_Boolean toEnable = Standard_True;
5763       if (++anArgIter < theArgNb
5764       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5765       {
5766         --anArgIter;
5767       }
5768       aCaps->swapInterval = toEnable;
5769     }
5770     else if (anArgCase == "-ffp")
5771     {
5772       Standard_Boolean toEnable = Standard_True;
5773       if (++anArgIter < theArgNb
5774       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5775       {
5776         --anArgIter;
5777       }
5778       aCaps->ffpEnable = toEnable;
5779     }
5780     else if (anArgCase == "-vbo")
5781     {
5782       Standard_Boolean toEnable = Standard_True;
5783       if (++anArgIter < theArgNb
5784       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5785       {
5786         --anArgIter;
5787       }
5788       aCaps->vboDisable = !toEnable;
5789     }
5790     else if (anArgCase == "-sprite"
5791           || anArgCase == "-sprites")
5792     {
5793       Standard_Boolean toEnable = Standard_True;
5794       if (++anArgIter < theArgNb
5795       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5796       {
5797         --anArgIter;
5798       }
5799       aCaps->pntSpritesDisable = !toEnable;
5800     }
5801     else if (anArgCase == "-softmode")
5802     {
5803       Standard_Boolean toEnable = Standard_True;
5804       if (++anArgIter < theArgNb
5805       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5806       {
5807         --anArgIter;
5808       }
5809       aCaps->contextNoAccel = toEnable;
5810     }
5811     else if (anArgCase == "-winbuffer"
5812           || anArgCase == "-windowbuffer"
5813           || anArgCase == "-usewinbuffer"
5814           || anArgCase == "-usewindowbuffer"
5815           || anArgCase == "-usesystembuffer")
5816     {
5817       Standard_Boolean toEnable = Standard_True;
5818       if (++anArgIter < theArgNb
5819       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5820       {
5821         --anArgIter;
5822       }
5823       aCaps->useSystemBuffer = toEnable;
5824     }
5825     else if (anArgCase == "-accel"
5826           || anArgCase == "-acceleration")
5827     {
5828       Standard_Boolean toEnable = Standard_True;
5829       if (++anArgIter < theArgNb
5830       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5831       {
5832         --anArgIter;
5833       }
5834       aCaps->contextNoAccel = !toEnable;
5835     }
5836     else if (anArgCase == "-compat"
5837           || anArgCase == "-compatprofile"
5838           || anArgCase == "-compatible"
5839           || anArgCase == "-compatibleprofile")
5840     {
5841       Standard_Boolean toEnable = Standard_True;
5842       if (++anArgIter < theArgNb
5843       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5844       {
5845         --anArgIter;
5846       }
5847       aCaps->contextCompatible = toEnable;
5848       if (!aCaps->contextCompatible)
5849       {
5850         aCaps->ffpEnable = Standard_False;
5851       }
5852     }
5853     else if (anArgCase == "-core"
5854           || anArgCase == "-coreprofile")
5855     {
5856       Standard_Boolean toEnable = Standard_True;
5857       if (++anArgIter < theArgNb
5858       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5859       {
5860         --anArgIter;
5861       }
5862       aCaps->contextCompatible = !toEnable;
5863       if (!aCaps->contextCompatible)
5864       {
5865         aCaps->ffpEnable = Standard_False;
5866       }
5867     }
5868     else if (anArgCase == "-stereo"
5869           || anArgCase == "-quadbuffer")
5870     {
5871       Standard_Boolean toEnable = Standard_True;
5872       if (++anArgIter < theArgNb
5873       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5874       {
5875         --anArgIter;
5876       }
5877       aCaps->contextStereo = toEnable;
5878     }
5879     else
5880     {
5881       std::cout << "Error: unknown argument '" << anArg << "'\n";
5882       return 1;
5883     }
5884   }
5885   if (aCaps != &ViewerTest_myDefaultCaps)
5886   {
5887     ViewerTest_myDefaultCaps = *aCaps;
5888   }
5889   return 0;
5890 }
5891
5892 //==============================================================================
5893 //function : VMemGpu
5894 //purpose  :
5895 //==============================================================================
5896
5897 static int VMemGpu (Draw_Interpretor& theDI,
5898                     Standard_Integer  theArgNb,
5899                     const char**      theArgVec)
5900 {
5901   // get the context
5902   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5903   if (aContextAIS.IsNull())
5904   {
5905     std::cerr << "No active view. Please call vinit.\n";
5906     return 1;
5907   }
5908
5909   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5910   if (aDriver.IsNull())
5911   {
5912     std::cerr << "Graphic driver not available.\n";
5913     return 1;
5914   }
5915
5916   Standard_Size aFreeBytes = 0;
5917   TCollection_AsciiString anInfo;
5918   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5919   {
5920     std::cerr << "Information not available.\n";
5921     return 1;
5922   }
5923
5924   if (theArgNb > 1 && *theArgVec[1] == 'f')
5925   {
5926     theDI << Standard_Real (aFreeBytes);
5927   }
5928   else
5929   {
5930     theDI << anInfo;
5931   }
5932
5933   return 0;
5934 }
5935
5936 // ==============================================================================
5937 // function : VReadPixel
5938 // purpose  :
5939 // ==============================================================================
5940 static int VReadPixel (Draw_Interpretor& theDI,
5941                        Standard_Integer  theArgNb,
5942                        const char**      theArgVec)
5943 {
5944   // get the active view
5945   Handle(V3d_View) aView = ViewerTest::CurrentView();
5946   if (aView.IsNull())
5947   {
5948     std::cerr << "No active view. Please call vinit.\n";
5949     return 1;
5950   }
5951   else if (theArgNb < 3)
5952   {
5953     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5954     return 1;
5955   }
5956
5957   Image_Format         aFormat     = Image_Format_RGBA;
5958   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
5959
5960   Standard_Integer aWidth, aHeight;
5961   aView->Window()->Size (aWidth, aHeight);
5962   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5963   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5964   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5965   {
5966     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5967     return 1;
5968   }
5969
5970   Standard_Boolean toShowName = Standard_False;
5971   Standard_Boolean toShowHls  = Standard_False;
5972   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5973   {
5974     TCollection_AsciiString aParam (theArgVec[anIter]);
5975     aParam.LowerCase();
5976     if (aParam == "rgb")
5977     {
5978       aFormat     = Image_Format_RGB;
5979       aBufferType = Graphic3d_BT_RGB;
5980     }
5981     else if (aParam == "hls")
5982     {
5983       aFormat     = Image_Format_RGB;
5984       aBufferType = Graphic3d_BT_RGB;
5985       toShowHls   = Standard_True;
5986     }
5987     else if (aParam == "rgbf")
5988     {
5989       aFormat     = Image_Format_RGBF;
5990       aBufferType = Graphic3d_BT_RGB;
5991     }
5992     else if (aParam == "rgba")
5993     {
5994       aFormat     = Image_Format_RGBA;
5995       aBufferType = Graphic3d_BT_RGBA;
5996     }
5997     else if (aParam == "rgbaf")
5998     {
5999       aFormat     = Image_Format_RGBAF;
6000       aBufferType = Graphic3d_BT_RGBA;
6001     }
6002     else if (aParam == "depth")
6003     {
6004       aFormat     = Image_Format_GrayF;
6005       aBufferType = Graphic3d_BT_Depth;
6006     }
6007     else if (aParam == "name")
6008     {
6009       toShowName = Standard_True;
6010     }
6011   }
6012
6013   Image_PixMap anImage;
6014   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6015   {
6016     std::cerr << "Image allocation failed\n";
6017     return 1;
6018   }
6019   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6020   {
6021     std::cerr << "Image dump failed\n";
6022     return 1;
6023   }
6024
6025   // redirect possible warning messages that could have been added by ToPixMap
6026   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6027   // contaminate result of the command
6028   Standard_CString aWarnLog = theDI.Result();
6029   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6030   {
6031     std::cout << aWarnLog << std::endl;
6032   }
6033   theDI.Reset();
6034
6035   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6036   if (toShowName)
6037   {
6038     if (aBufferType == Graphic3d_BT_RGBA)
6039     {
6040       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6041     }
6042     else
6043     {
6044       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6045     }
6046   }
6047   else
6048   {
6049     switch (aBufferType)
6050     {
6051       default:
6052       case Graphic3d_BT_RGB:
6053       {
6054         if (toShowHls)
6055         {
6056           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6057         }
6058         else
6059         {
6060           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6061         }
6062         break;
6063       }
6064       case Graphic3d_BT_RGBA:
6065       {
6066         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6067         break;
6068       }
6069       case Graphic3d_BT_Depth:
6070       {
6071         theDI << aColor.GetRGB().Red();
6072         break;
6073       }
6074     }
6075   }
6076
6077   return 0;
6078 }
6079
6080 //! Auxiliary presentation for an image plane.
6081 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6082 {
6083 public:
6084   //! Main constructor.
6085   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6086                        const Standard_Real theWidth,
6087                        const Standard_Real theHeight,
6088                        const TCollection_AsciiString& theLabel)
6089   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6090   {
6091     SetDisplayMode (0);
6092     SetHilightMode (1);
6093     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6094     {
6095       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6096       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6097       Graphic3d_MaterialAspect aMat;
6098       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6099       aMat.SetAmbient  (1.0);
6100       aMat.SetDiffuse  (1.0);
6101       aMat.SetSpecular (1.0);
6102       aMat.SetEmissive (1.0);
6103       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6104       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6105       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6106       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6107       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6108       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6109       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6110       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6111       aFillAspect->SetFrontMaterial (aMat);
6112       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6113       aFillAspect->SetTextureMapOn();
6114     }
6115     {
6116       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6117       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6118       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6119       myDrawer->SetTextAspect (aTextAspect);
6120     }
6121     {
6122       const gp_Dir aNorm (0.0, 0.0, 1.0);
6123       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6124       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6125       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6126       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6127       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6128       myTris->AddEdge (1);
6129       myTris->AddEdge (2);
6130       myTris->AddEdge (3);
6131       myTris->AddEdge (3);
6132       myTris->AddEdge (2);
6133       myTris->AddEdge (4);
6134
6135       myRect = new Graphic3d_ArrayOfPolylines (4);
6136       myRect->AddVertex (myTris->Vertice (1));
6137       myRect->AddVertex (myTris->Vertice (3));
6138       myRect->AddVertex (myTris->Vertice (4));
6139       myRect->AddVertex (myTris->Vertice (2));
6140     }
6141   }
6142
6143   //! Returns TRUE for accepted display modes.
6144   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6145
6146   //! Compute presentation.
6147   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6148   {
6149     switch (theMode)
6150     {
6151       case 0:
6152       {
6153         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6154         aGroup->AddPrimitiveArray (myTris);
6155         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6156         aGroup->AddPrimitiveArray (myRect);
6157         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6158         return;
6159       }
6160       case 1:
6161       {
6162         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6163         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6164         aGroup->AddPrimitiveArray (myRect);
6165         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6166         return;
6167       }
6168     }
6169   }
6170
6171   //! Compute selection.
6172   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6173   {
6174     if (theMode == 0)
6175     {
6176       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6177       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6178       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6179       theSel->Add (aSensitive);
6180     }
6181   }
6182
6183 private:
6184   Handle(Graphic3d_ArrayOfTriangles) myTris;
6185   Handle(Graphic3d_ArrayOfPolylines) myRect;
6186   TCollection_AsciiString myLabel;
6187   Standard_Real myWidth;
6188   Standard_Real myHeight;
6189 };
6190
6191 //==============================================================================
6192 //function : VDiffImage
6193 //purpose  : The draw-command compares two images.
6194 //==============================================================================
6195
6196 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6197 {
6198   if (theArgNb < 3)
6199   {
6200     std::cout << "Syntax error: not enough arguments.\n";
6201     return 1;
6202   }
6203
6204   Standard_Integer anArgIter = 1;
6205   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6206   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6207   TCollection_AsciiString aDiffImagePath;
6208   Standard_Real    aTolColor        = -1.0;
6209   Standard_Integer toBlackWhite     = -1;
6210   Standard_Integer isBorderFilterOn = -1;
6211   Standard_Boolean isOldSyntax = Standard_False;
6212   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6213   for (; anArgIter < theArgNb; ++anArgIter)
6214   {
6215     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6216     anArg.LowerCase();
6217     if (anArgIter + 1 < theArgNb
6218      && (anArg == "-toleranceofcolor"
6219       || anArg == "-tolerancecolor"
6220       || anArg == "-tolerance"
6221       || anArg == "-toler"))
6222     {
6223       aTolColor = Atof (theArgVec[++anArgIter]);
6224       if (aTolColor < 0.0 || aTolColor > 1.0)
6225       {
6226         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6227         return 1;
6228       }
6229     }
6230     else if (anArg == "-blackwhite")
6231     {
6232       Standard_Boolean toEnable = Standard_True;
6233       if (anArgIter + 1 < theArgNb
6234        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6235       {
6236         ++anArgIter;
6237       }
6238       toBlackWhite = toEnable ? 1 : 0;
6239     }
6240     else if (anArg == "-borderfilter")
6241     {
6242       Standard_Boolean toEnable = Standard_True;
6243       if (anArgIter + 1 < theArgNb
6244        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6245       {
6246         ++anArgIter;
6247       }
6248       isBorderFilterOn = toEnable ? 1 : 0;
6249     }
6250     else if (anArg == "-exitonclose")
6251     {
6252       Draw_ToExitOnCloseView = true;
6253       if (anArgIter + 1 < theArgNb
6254        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6255       {
6256         ++anArgIter;
6257       }
6258     }
6259     else if (anArg == "-closeonescape"
6260           || anArg == "-closeonesc")
6261     {
6262       Draw_ToCloseViewOnEsc = true;
6263       if (anArgIter + 1 < theArgNb
6264        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6265       {
6266         ++anArgIter;
6267       }
6268     }
6269     else if (anArgIter + 3 < theArgNb
6270           && anArg == "-display")
6271     {
6272       aViewName   = theArgVec[++anArgIter];
6273       aPrsNameRef = theArgVec[++anArgIter];
6274       aPrsNameNew = theArgVec[++anArgIter];
6275       if (anArgIter + 1 < theArgNb
6276       && *theArgVec[anArgIter + 1] != '-')
6277       {
6278         aPrsNameDiff = theArgVec[++anArgIter];
6279       }
6280     }
6281     else if (aTolColor < 0.0
6282           && anArg.IsRealValue())
6283     {
6284       isOldSyntax = Standard_True;
6285       aTolColor = anArg.RealValue();
6286       if (aTolColor < 0.0 || aTolColor > 1.0)
6287       {
6288         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6289         return 1;
6290       }
6291     }
6292     else if (isOldSyntax
6293           && toBlackWhite == -1
6294           && (anArg == "0" || anArg == "1"))
6295     {
6296       toBlackWhite = anArg == "1" ? 1 : 0;
6297     }
6298     else if (isOldSyntax
6299           && isBorderFilterOn == -1
6300           && (anArg == "0" || anArg == "1"))
6301     {
6302       isBorderFilterOn = anArg == "1" ? 1 : 0;
6303     }
6304     else if (aDiffImagePath.IsEmpty())
6305     {
6306       aDiffImagePath = theArgVec[anArgIter];
6307     }
6308     else
6309     {
6310       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6311       return 1;
6312     }
6313   }
6314
6315   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6316   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6317   if (!anImgRef->Load (anImgPathRef))
6318   {
6319     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6320     return 1;
6321   }
6322   if (!anImgNew->Load (anImgPathNew))
6323   {
6324     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6325     return 1;
6326   }
6327
6328   // compare the images
6329   Image_Diff aComparer;
6330   Standard_Integer aDiffColorsNb = -1;
6331   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6332   {
6333     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6334     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6335     aDiffColorsNb = aComparer.Compare();
6336     theDI << aDiffColorsNb << "\n";
6337   }
6338
6339   // save image of difference
6340   Handle(Image_AlienPixMap) aDiff;
6341   if (aDiffColorsNb > 0
6342   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6343   {
6344     aDiff = new Image_AlienPixMap();
6345     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6346     {
6347       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6348       return 1;
6349     }
6350     aComparer.SaveDiffImage (*aDiff);
6351     if (!aDiffImagePath.IsEmpty()
6352      && !aDiff->Save (aDiffImagePath))
6353     {
6354       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6355       return 1;
6356     }
6357   }
6358
6359   if (aViewName.IsEmpty())
6360   {
6361     return 0;
6362   }
6363
6364   ViewerTest_Names aViewNames (aViewName);
6365   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6366   {
6367     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6368     theDI.Eval (aCommand.ToCString());
6369   }
6370
6371   Standard_Integer aPxLeft = 0;
6372   Standard_Integer aPxTop  = 0;
6373   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6374   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6375                               ? int(anImgRef->SizeY() * 2)
6376                               : int(anImgRef->SizeY());
6377   TCollection_AsciiString aDisplayName;
6378   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop,
6379                                                             aWinSizeX, aWinSizeY,
6380                                                             aViewName.ToCString(),
6381                                                             aDisplayName.ToCString());
6382
6383   Standard_Real aRatio = anImgRef->Ratio();
6384   Standard_Real aSizeX = 1.0;
6385   Standard_Real aSizeY = aSizeX / aRatio;
6386   {
6387     OSD_Path aPath (anImgPathRef);
6388     TCollection_AsciiString aLabelRef;
6389     if (!aPath.Name().IsEmpty())
6390     {
6391       aLabelRef = aPath.Name() + aPath.Extension();
6392     }
6393     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6394
6395     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6396     gp_Trsf aTrsfRef;
6397     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6398     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6399     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6400   }
6401   {
6402     OSD_Path aPath (anImgPathNew);
6403     TCollection_AsciiString aLabelNew;
6404     if (!aPath.Name().IsEmpty())
6405     {
6406       aLabelNew = aPath.Name() + aPath.Extension();
6407     }
6408     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6409
6410     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6411     gp_Trsf aTrsfRef;
6412     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6413     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6414     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6415   }
6416   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6417   if (!aDiff.IsNull())
6418   {
6419     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6420     gp_Trsf aTrsfDiff;
6421     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6422     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6423   }
6424   if (!aPrsNameDiff.IsEmpty())
6425   {
6426     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6427   }
6428   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6429   ViewerTest::CurrentView()->FitAll();
6430   return 0;
6431 }
6432
6433 //=======================================================================
6434 //function : VSelect
6435 //purpose  : Emulates different types of selection by mouse:
6436 //           1) single click selection
6437 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6438 //           3) selection with polygon having corners at
6439 //           pixel positions (x1,y1),...,(xn,yn)
6440 //           4) any of these selections with shift button pressed
6441 //=======================================================================
6442 static Standard_Integer VSelect (Draw_Interpretor& di,
6443                                  Standard_Integer argc,
6444                                  const char ** argv)
6445 {
6446   if(argc < 3)
6447   {
6448     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6449     return 1;
6450   }
6451
6452   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6453   if(myAIScontext.IsNull())
6454   {
6455     di << "use 'vinit' command before " << argv[0] << "\n";
6456     return 1;
6457   }
6458
6459   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6460   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6461   TCollection_AsciiString anArg;
6462   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6463   anArg.LowerCase();
6464   if (anArg == "-allowoverlap")
6465   {
6466     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6467       : argc == 7;
6468     if (!isValidated)
6469     {
6470       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6471       return 1;
6472     }
6473
6474     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6475     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6476     aCoordsNb -= 2;
6477   }
6478
6479   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6480   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6481   if(aCoordsNb == 2)
6482   {
6483     if(isShiftSelection)
6484       aCurrentEventManager->ShiftSelect();
6485     else
6486       aCurrentEventManager->Select();
6487   }
6488   else if(aCoordsNb == 4)
6489   {
6490     if(isShiftSelection)
6491       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6492     else
6493       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6494   }
6495   else
6496   {
6497     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6498
6499     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6500       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6501
6502     if(isShiftSelection)
6503       aCurrentEventManager->ShiftSelect(aPolyline);
6504     else
6505       aCurrentEventManager->Select(aPolyline);
6506   }
6507   return 0;
6508 }
6509
6510 //=======================================================================
6511 //function : VMoveTo
6512 //purpose  : Emulates cursor movement to defined pixel position
6513 //=======================================================================
6514 static Standard_Integer VMoveTo (Draw_Interpretor& di,
6515                                 Standard_Integer argc,
6516                                 const char ** argv)
6517 {
6518   if(argc != 3)
6519   {
6520     di << "Usage : " << argv[0] << " x y\n";
6521     return 1;
6522   }
6523
6524   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6525   if(aContext.IsNull())
6526   {
6527     di << "use 'vinit' command before " << argv[0] << "\n";
6528     return 1;
6529   }
6530   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6531   return 0;
6532 }
6533
6534 namespace
6535 {
6536   //! Global map storing all animations registered in ViewerTest.
6537   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6538
6539   //! The animation calling the Draw Harness command.
6540   class ViewerTest_AnimationProc : public AIS_Animation
6541   {
6542   public:
6543
6544     //! Main constructor.
6545     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6546                               Draw_Interpretor* theDI,
6547                               const TCollection_AsciiString& theCommand)
6548     : AIS_Animation (theAnimationName),
6549       myDrawInter(theDI),
6550       myCommand  (theCommand)
6551     {
6552       //
6553     }
6554
6555   protected:
6556
6557     //! Evaluate the command.
6558     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6559     {
6560       TCollection_AsciiString aCmd = myCommand;
6561       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6562       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6563       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6564       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6565       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6566       myDrawInter->Eval (aCmd.ToCString());
6567     }
6568
6569     //! Find the keyword in the command and replace it with value.
6570     //! @return the position of the keyword to pass value
6571     void replace (TCollection_AsciiString&       theCmd,
6572                   const TCollection_AsciiString& theKey,
6573                   const TCollection_AsciiString& theVal)
6574     {
6575       TCollection_AsciiString aCmd (theCmd);
6576       aCmd.LowerCase();
6577       const Standard_Integer aPos = aCmd.Search (theKey);
6578       if (aPos == -1)
6579       {
6580         return;
6581       }
6582
6583       TCollection_AsciiString aPart1, aPart2;
6584       Standard_Integer aPart1To = aPos - 1;
6585       if (aPart1To >= 1
6586        && aPart1To <= theCmd.Length())
6587       {
6588         aPart1 = theCmd.SubString (1, aPart1To);
6589       }
6590
6591       Standard_Integer aPart2From = aPos + theKey.Length();
6592       if (aPart2From >= 1
6593        && aPart2From <= theCmd.Length())
6594       {
6595         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6596       }
6597
6598       theCmd = aPart1 + theVal + aPart2;
6599     }
6600
6601   protected:
6602
6603     Draw_Interpretor*       myDrawInter;
6604     TCollection_AsciiString myCommand;
6605
6606   };
6607
6608   //! Replace the animation with the new one.
6609   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6610                                 Handle(AIS_Animation)&       theAnimation,
6611                                 const Handle(AIS_Animation)& theAnimationNew)
6612   {
6613     theAnimationNew->CopyFrom (theAnimation);
6614     if (!theParentAnimation.IsNull())
6615     {
6616       theParentAnimation->Replace (theAnimation, theAnimationNew);
6617     }
6618     else
6619     {
6620       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6621       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6622     }
6623     theAnimation = theAnimationNew;
6624   }
6625
6626   //! Parse the point.
6627   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6628   {
6629     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6630     if (!anXYZ[0].IsRealValue()
6631      || !anXYZ[1].IsRealValue()
6632      || !anXYZ[2].IsRealValue())
6633     {
6634       return Standard_False;
6635     }
6636
6637     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6638     return Standard_True;
6639   }
6640
6641   //! Parse the quaternion.
6642   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6643   {
6644     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6645     if (!anXYZW[0].IsRealValue()
6646      || !anXYZW[1].IsRealValue()
6647      || !anXYZW[2].IsRealValue()
6648      || !anXYZW[3].IsRealValue())
6649     {
6650       return Standard_False;
6651     }
6652
6653     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6654     return Standard_True;
6655   }
6656
6657   //! Auxiliary class for flipping image upside-down.
6658   class ImageFlipper
6659   {
6660   public:
6661
6662     //! Empty constructor.
6663     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6664
6665     //! Perform flipping.
6666     Standard_Boolean FlipY (Image_PixMap& theImage)
6667     {
6668       if (theImage.IsEmpty()
6669        || theImage.SizeX() == 0
6670        || theImage.SizeY() == 0)
6671       {
6672         return Standard_False;
6673       }
6674
6675       const Standard_Size aRowSize = theImage.SizeRowBytes();
6676       if (myTmp.Size() < aRowSize
6677       && !myTmp.Allocate (aRowSize))
6678       {
6679         return Standard_False;
6680       }
6681
6682       // for odd height middle row should be left as is
6683       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6684       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6685       {
6686         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6687         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6688         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
6689         memcpy (aTop,               aBot,         aRowSize);
6690         memcpy (aBot,               myTmp.Data(), aRowSize);
6691       }
6692       return Standard_True;
6693     }
6694
6695   private:
6696     NCollection_Buffer myTmp;
6697   };
6698
6699 }
6700
6701 //=================================================================================================
6702 //function : VViewParams
6703 //purpose  : Gets or sets AIS View characteristics
6704 //=================================================================================================
6705 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6706 {
6707   Handle(V3d_View) aView = ViewerTest::CurrentView();
6708   if (aView.IsNull())
6709   {
6710     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6711     return 1;
6712   }
6713
6714   Standard_Boolean toSetProj     = Standard_False;
6715   Standard_Boolean toSetUp       = Standard_False;
6716   Standard_Boolean toSetAt       = Standard_False;
6717   Standard_Boolean toSetEye      = Standard_False;
6718   Standard_Boolean toSetScale    = Standard_False;
6719   Standard_Boolean toSetSize     = Standard_False;
6720   Standard_Boolean toSetCenter2d = Standard_False;
6721   Standard_Real    aViewScale = aView->Scale();
6722   Standard_Real    aViewSize  = 1.0;
6723   Graphic3d_Vec2i  aCenter2d;
6724   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6725   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6726   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6727   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6728   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6729   if (theArgsNb == 1)
6730   {
6731     // print all of the available view parameters
6732     char aText[4096];
6733     Sprintf (aText,
6734              "Scale: %g\n"
6735              "Proj:  %12g %12g %12g\n"
6736              "Up:    %12g %12g %12g\n"
6737              "At:    %12g %12g %12g\n"
6738              "Eye:   %12g %12g %12g\n",
6739               aViewScale,
6740               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6741               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6742               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6743               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6744     theDi << aText;
6745     return 0;
6746   }
6747
6748   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6749   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6750   {
6751     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6752     anArg.LowerCase();
6753     if (anUpdateTool.parseRedrawMode (anArg))
6754     {
6755       continue;
6756     }
6757     else if (anArg == "-cmd"
6758           || anArg == "-command"
6759           || anArg == "-args")
6760     {
6761       char aText[4096];
6762       Sprintf (aText,
6763                "-scale %g "
6764                "-proj %g %g %g "
6765                "-up %g %g %g "
6766                "-at %g %g %g\n",
6767                 aViewScale,
6768                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6769                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6770                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6771       theDi << aText;
6772     }
6773     else if (anArg == "-scale"
6774           || anArg == "-size")
6775     {
6776       if (anArgIter + 1 < theArgsNb
6777        && *theArgVec[anArgIter + 1] != '-')
6778       {
6779         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6780         if (aValueArg.IsRealValue())
6781         {
6782           ++anArgIter;
6783           if (anArg == "-scale")
6784           {
6785             toSetScale = Standard_True;
6786             aViewScale = aValueArg.RealValue();
6787           }
6788           else if (anArg == "-size")
6789           {
6790             toSetSize = Standard_True;
6791             aViewSize = aValueArg.RealValue();
6792           }
6793           continue;
6794         }
6795       }
6796       if (anArg == "-scale")
6797       {
6798         theDi << "Scale: " << aView->Scale() << "\n";
6799       }
6800       else if (anArg == "-size")
6801       {
6802         Graphic3d_Vec2d aSizeXY;
6803         aView->Size (aSizeXY.x(), aSizeXY.y());
6804         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6805       }
6806     }
6807     else if (anArg == "-eye"
6808           || anArg == "-at"
6809           || anArg == "-up"
6810           || anArg == "-proj")
6811     {
6812       if (anArgIter + 3 < theArgsNb)
6813       {
6814         gp_XYZ anXYZ;
6815         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6816         {
6817           anArgIter += 3;
6818           if (anArg == "-eye")
6819           {
6820             toSetEye = Standard_True;
6821             aViewEye = anXYZ;
6822           }
6823           else if (anArg == "-at")
6824           {
6825             toSetAt = Standard_True;
6826             aViewAt = anXYZ;
6827           }
6828           else if (anArg == "-up")
6829           {
6830             toSetUp = Standard_True;
6831             aViewUp = anXYZ;
6832           }
6833           else if (anArg == "-proj")
6834           {
6835             toSetProj = Standard_True;
6836             aViewProj = anXYZ;
6837           }
6838           continue;
6839         }
6840       }
6841
6842       if (anArg == "-eye")
6843       {
6844         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6845       }
6846       else if (anArg == "-at")
6847       {
6848         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6849       }
6850       else if (anArg == "-up")
6851       {
6852         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6853       }
6854       else if (anArg == "-proj")
6855       {
6856         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6857       }
6858     }
6859     else if (anArg == "-center")
6860     {
6861       if (anArgIter + 2 < theArgsNb)
6862       {
6863         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6864         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6865         if (anX.IsIntegerValue()
6866          && anY.IsIntegerValue())
6867         {
6868           toSetCenter2d = Standard_True;
6869           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6870         }
6871       }
6872     }
6873     else
6874     {
6875       std::cout << "Syntax error at '" << anArg << "'\n";
6876       return 1;
6877     }
6878   }
6879
6880   // change view parameters in proper order
6881   if (toSetScale)
6882   {
6883     aView->SetScale (aViewScale);
6884   }
6885   if (toSetSize)
6886   {
6887     aView->SetSize (aViewSize);
6888   }
6889   if (toSetEye)
6890   {
6891     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6892   }
6893   if (toSetAt)
6894   {
6895     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6896   }
6897   if (toSetProj)
6898   {
6899     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6900   }
6901   if (toSetUp)
6902   {
6903     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6904   }
6905   if (toSetCenter2d)
6906   {
6907     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6908   }
6909
6910   return 0;
6911 }
6912
6913 //==============================================================================
6914 //function : VAnimation
6915 //purpose  :
6916 //==============================================================================
6917 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6918                                     Standard_Integer  theArgNb,
6919                                     const char**      theArgVec)
6920 {
6921   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6922   if (theArgNb < 2)
6923   {
6924     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6925          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6926     {
6927       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6928     }
6929     return 0;
6930   }
6931   if (aCtx.IsNull())
6932   {
6933     std::cout << "Error: no active view\n";
6934     return 1;
6935   }
6936
6937   Standard_Integer anArgIter = 1;
6938   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6939   if (aNameArg.IsEmpty())
6940   {
6941     std::cout << "Syntax error: animation name is not defined.\n";
6942     return 1;
6943   }
6944
6945   TCollection_AsciiString aNameArgLower = aNameArg;
6946   aNameArgLower.LowerCase();
6947   if (aNameArgLower == "-reset"
6948    || aNameArgLower == "-clear")
6949   {
6950     ViewerTest_AnimationTimelineMap.Clear();
6951     return 0;
6952   }
6953   else if (aNameArg.Value (1) == '-')
6954   {
6955     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6956     return 1;
6957   }
6958
6959   const char* aNameSplitter = "/";
6960   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6961   if (aSplitPos == -1)
6962   {
6963     aNameSplitter = ".";
6964     aSplitPos = aNameArg.Search (aNameSplitter);
6965   }
6966
6967   // find existing or create a new animation by specified name within syntax "parent.child".
6968   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6969   for (; !aNameArg.IsEmpty();)
6970   {
6971     TCollection_AsciiString aNameParent;
6972     if (aSplitPos != -1)
6973     {
6974       if (aSplitPos == aNameArg.Length())
6975       {
6976         std::cout << "Syntax error: animation name is not defined.\n";
6977         return 1;
6978       }
6979
6980       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6981       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6982
6983       aSplitPos = aNameArg.Search (aNameSplitter);
6984     }
6985     else
6986     {
6987       aNameParent = aNameArg;
6988       aNameArg.Clear();
6989     }
6990
6991     if (anAnimation.IsNull())
6992     {
6993       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6994       {
6995         anAnimation = new AIS_Animation (aNameParent);
6996         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6997       }
6998       aRootAnimation = anAnimation;
6999     }
7000     else
7001     {
7002       aParentAnimation = anAnimation;
7003       anAnimation = aParentAnimation->Find (aNameParent);
7004       if (anAnimation.IsNull())
7005       {
7006         anAnimation = new AIS_Animation (aNameParent);
7007         aParentAnimation->Add (anAnimation);
7008       }
7009     }
7010   }
7011
7012   if (anArgIter >= theArgNb)
7013   {
7014     // just print the list of children
7015     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7016     {
7017       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7018     }
7019     return 0;
7020   }
7021
7022   // animation parameters
7023   Standard_Boolean toPlay = Standard_False;
7024   Standard_Real aPlaySpeed     = 1.0;
7025   Standard_Real aPlayStartTime = anAnimation->StartPts();
7026   Standard_Real aPlayDuration  = anAnimation->Duration();
7027   Standard_Boolean isFreeCamera = Standard_False;
7028   Standard_Boolean isLockLoop   = Standard_False;
7029
7030   // video recording parameters
7031   TCollection_AsciiString aRecFile;
7032   Image_VideoParams aRecParams;
7033
7034   Handle(V3d_View) aView = ViewerTest::CurrentView();
7035   for (; anArgIter < theArgNb; ++anArgIter)
7036   {
7037     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7038     anArg.LowerCase();
7039     // general options
7040     if (anArg == "-reset"
7041      || anArg == "-clear")
7042     {
7043       anAnimation->Clear();
7044     }
7045     else if (anArg == "-remove"
7046           || anArg == "-del"
7047           || anArg == "-delete")
7048     {
7049       if (!aParentAnimation.IsNull())
7050       {
7051         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7052       }
7053       else
7054       {
7055         aParentAnimation->Remove (anAnimation);
7056       }
7057     }
7058     // playback options
7059     else if (anArg == "-play")
7060     {
7061       toPlay = Standard_True;
7062       if (++anArgIter < theArgNb)
7063       {
7064         if (*theArgVec[anArgIter] == '-')
7065         {
7066           --anArgIter;
7067           continue;
7068         }
7069         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7070
7071         if (++anArgIter < theArgNb)
7072         {
7073           if (*theArgVec[anArgIter] == '-')
7074           {
7075             --anArgIter;
7076             continue;
7077           }
7078           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7079         }
7080       }
7081     }
7082     else if (anArg == "-resume")
7083     {
7084       toPlay = Standard_True;
7085       aPlayStartTime = anAnimation->ElapsedTime();
7086       if (++anArgIter < theArgNb)
7087       {
7088         if (*theArgVec[anArgIter] == '-')
7089         {
7090           --anArgIter;
7091           continue;
7092         }
7093
7094         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7095       }
7096     }
7097     else if (anArg == "-playspeed"
7098           || anArg == "-speed")
7099     {
7100       if (++anArgIter >= theArgNb)
7101       {
7102         std::cout << "Syntax error at " << anArg << ".\n";
7103         return 1;
7104       }
7105       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7106     }
7107     else if (anArg == "-lock"
7108           || anArg == "-lockloop"
7109           || anArg == "-playlockloop")
7110     {
7111       isLockLoop = Standard_True;
7112     }
7113     else if (anArg == "-freecamera"
7114           || anArg == "-playfreecamera"
7115           || anArg == "-freelook")
7116     {
7117       isFreeCamera = Standard_True;
7118     }
7119     // video recodring options
7120     else if (anArg == "-rec"
7121           || anArg == "-record")
7122     {
7123       if (++anArgIter >= theArgNb)
7124       {
7125         std::cout << "Syntax error at " << anArg << ".\n";
7126         return 1;
7127       }
7128
7129       aRecFile = theArgVec[anArgIter];
7130       if (aRecParams.FpsNum <= 0)
7131       {
7132         aRecParams.FpsNum = 24;
7133       }
7134
7135       if (anArgIter + 2 < theArgNb
7136       && *theArgVec[anArgIter + 1] != '-'
7137       && *theArgVec[anArgIter + 2] != '-')
7138       {
7139         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7140         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7141         if (aWidthArg .IsIntegerValue()
7142          && aHeightArg.IsIntegerValue())
7143         {
7144           aRecParams.Width  = aWidthArg .IntegerValue();
7145           aRecParams.Height = aHeightArg.IntegerValue();
7146           anArgIter += 2;
7147         }
7148       }
7149     }
7150     else if (anArg == "-fps")
7151     {
7152       if (++anArgIter >= theArgNb)
7153       {
7154         std::cout << "Syntax error at " << anArg << ".\n";
7155         return 1;
7156       }
7157
7158       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7159       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7160       if (aSplitIndex == 0)
7161       {
7162         aRecParams.FpsNum = aFpsArg.IntegerValue();
7163       }
7164       else
7165       {
7166         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7167         aFpsArg.Split (aFpsArg.Length() - 1);
7168         const TCollection_AsciiString aNumStr = aFpsArg;
7169         aRecParams.FpsNum = aNumStr.IntegerValue();
7170         aRecParams.FpsDen = aDenStr.IntegerValue();
7171         if (aRecParams.FpsDen < 1)
7172         {
7173           std::cout << "Syntax error at " << anArg << ".\n";
7174           return 1;
7175         }
7176       }
7177     }
7178     else if (anArg == "-format")
7179     {
7180       if (++anArgIter >= theArgNb)
7181       {
7182         std::cout << "Syntax error at " << anArg << ".\n";
7183         return 1;
7184       }
7185       aRecParams.Format = theArgVec[anArgIter];
7186     }
7187     else if (anArg == "-pix_fmt"
7188           || anArg == "-pixfmt"
7189           || anArg == "-pixelformat")
7190     {
7191       if (++anArgIter >= theArgNb)
7192       {
7193         std::cout << "Syntax error at " << anArg << ".\n";
7194         return 1;
7195       }
7196       aRecParams.PixelFormat = theArgVec[anArgIter];
7197     }
7198     else if (anArg == "-codec"
7199           || anArg == "-vcodec"
7200           || anArg == "-videocodec")
7201     {
7202       if (++anArgIter >= theArgNb)
7203       {
7204         std::cout << "Syntax error at " << anArg << ".\n";
7205         return 1;
7206       }
7207       aRecParams.VideoCodec = theArgVec[anArgIter];
7208     }
7209     else if (anArg == "-crf"
7210           || anArg == "-preset"
7211           || anArg == "-qp")
7212     {
7213       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7214       if (++anArgIter >= theArgNb)
7215       {
7216         std::cout << "Syntax error at " << anArg << ".\n";
7217         return 1;
7218       }
7219
7220       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7221     }
7222     // animation definition options
7223     else if (anArg == "-start"
7224           || anArg == "-starttime"
7225           || anArg == "-startpts")
7226     {
7227       if (++anArgIter >= theArgNb)
7228       {
7229         std::cout << "Syntax error at " << anArg << ".\n";
7230         return 1;
7231       }
7232
7233       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7234       aRootAnimation->UpdateTotalDuration();
7235     }
7236     else if (anArg == "-end"
7237           || anArg == "-endtime"
7238           || anArg == "-endpts")
7239     {
7240       if (++anArgIter >= theArgNb)
7241       {
7242         std::cout << "Syntax error at " << anArg << ".\n";
7243         return 1;
7244       }
7245
7246       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7247       aRootAnimation->UpdateTotalDuration();
7248     }
7249     else if (anArg == "-dur"
7250           || anArg == "-duration")
7251     {
7252       if (++anArgIter >= theArgNb)
7253       {
7254         std::cout << "Syntax error at " << anArg << ".\n";
7255         return 1;
7256       }
7257
7258       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7259       aRootAnimation->UpdateTotalDuration();
7260     }
7261     else if (anArg == "-command"
7262           || anArg == "-cmd"
7263           || anArg == "-invoke"
7264           || anArg == "-eval"
7265           || anArg == "-proc")
7266     {
7267       if (++anArgIter >= theArgNb)
7268       {
7269         std::cout << "Syntax error at " << anArg << ".\n";
7270         return 1;
7271       }
7272
7273       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7274       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7275     }
7276     else if (anArg == "-objecttrsf"
7277           || anArg == "-objectransformation"
7278           || anArg == "-objtransformation"
7279           || anArg == "-objtrsf"
7280           || anArg == "-object"
7281           || anArg == "-obj")
7282     {
7283       if (++anArgIter >= theArgNb)
7284       {
7285         std::cout << "Syntax error at " << anArg << ".\n";
7286         return 1;
7287       }
7288
7289       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7290       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7291       if (!aMapOfAIS.IsBound2 (anObjName))
7292       {
7293         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7294         return 1;
7295       }
7296
7297       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
7298       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7299       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7300       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7301       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7302       Standard_Boolean isTrsfSet = Standard_False;
7303       Standard_Integer aTrsfArgIter = anArgIter + 1;
7304       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7305       {
7306         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7307         aTrsfArg.LowerCase();
7308         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7309         if (aTrsfArg.StartsWith ("-rotation")
7310          || aTrsfArg.StartsWith ("-rot"))
7311         {
7312           isTrsfSet = Standard_True;
7313           if (aTrsfArgIter + 4 >= theArgNb
7314           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7315           {
7316             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7317             return 1;
7318           }
7319           aTrsfArgIter += 4;
7320         }
7321         else if (aTrsfArg.StartsWith ("-location")
7322               || aTrsfArg.StartsWith ("-loc"))
7323         {
7324           isTrsfSet = Standard_True;
7325           if (aTrsfArgIter + 3 >= theArgNb
7326           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7327           {
7328             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7329             return 1;
7330           }
7331           aTrsfArgIter += 3;
7332         }
7333         else if (aTrsfArg.StartsWith ("-scale"))
7334         {
7335           isTrsfSet = Standard_True;
7336           if (++aTrsfArgIter >= theArgNb)
7337           {
7338             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7339             return 1;
7340           }
7341
7342           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7343           if (!aScaleStr.IsRealValue())
7344           {
7345             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7346             return 1;
7347           }
7348           aScales[anIndex] = aScaleStr.RealValue();
7349         }
7350         else
7351         {
7352           anArgIter = aTrsfArgIter - 1;
7353           break;
7354         }
7355       }
7356       if (!isTrsfSet)
7357       {
7358         std::cout << "Syntax error at " << anArg << ".\n";
7359         return 1;
7360       }
7361       else if (aTrsfArgIter >= theArgNb)
7362       {
7363         anArgIter = theArgNb;
7364       }
7365
7366       aTrsfs[0].SetRotation        (aRotQuats[0]);
7367       aTrsfs[1].SetRotation        (aRotQuats[1]);
7368       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7369       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7370       aTrsfs[0].SetScaleFactor     (aScales[0]);
7371       aTrsfs[1].SetScaleFactor     (aScales[1]);
7372
7373       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7374       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7375     }
7376     else if (anArg == "-viewtrsf"
7377           || anArg == "-view")
7378     {
7379       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7380       if (aCamAnimation.IsNull())
7381       {
7382         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7383         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7384       }
7385
7386       Handle(Graphic3d_Camera) aCams[2] =
7387       {
7388         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7389         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7390       };
7391
7392       Standard_Boolean isTrsfSet = Standard_False;
7393       Standard_Integer aViewArgIter = anArgIter + 1;
7394       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7395       {
7396         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7397         aViewArg.LowerCase();
7398         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7399         if (aViewArg.StartsWith ("-scale"))
7400         {
7401           isTrsfSet = Standard_True;
7402           if (++aViewArgIter >= theArgNb)
7403           {
7404             std::cout << "Syntax error at " << anArg << ".\n";
7405             return 1;
7406           }
7407
7408           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7409           if (!aScaleStr.IsRealValue())
7410           {
7411             std::cout << "Syntax error at " << aViewArg << ".\n";
7412             return 1;
7413           }
7414           Standard_Real aScale = aScaleStr.RealValue();
7415           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7416           aCams[anIndex]->SetScale (aScale);
7417         }
7418         else if (aViewArg.StartsWith ("-eye")
7419               || aViewArg.StartsWith ("-center")
7420               || aViewArg.StartsWith ("-at")
7421               || aViewArg.StartsWith ("-up"))
7422         {
7423           isTrsfSet = Standard_True;
7424           gp_XYZ anXYZ;
7425           if (aViewArgIter + 3 >= theArgNb
7426           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7427           {
7428             std::cout << "Syntax error at " << aViewArg << ".\n";
7429             return 1;
7430           }
7431           aViewArgIter += 3;
7432
7433           if (aViewArg.StartsWith ("-eye"))
7434           {
7435             aCams[anIndex]->SetEye (anXYZ);
7436           }
7437           else if (aViewArg.StartsWith ("-center")
7438                 || aViewArg.StartsWith ("-at"))
7439           {
7440             aCams[anIndex]->SetCenter (anXYZ);
7441           }
7442           else if (aViewArg.StartsWith ("-up"))
7443           {
7444             aCams[anIndex]->SetUp (anXYZ);
7445           }
7446         }
7447         else
7448         {
7449           anArgIter = aViewArgIter - 1;
7450           break;
7451         }
7452       }
7453       if (!isTrsfSet)
7454       {
7455         std::cout << "Syntax error at " << anArg << ".\n";
7456         return 1;
7457       }
7458       else if (aViewArgIter >= theArgNb)
7459       {
7460         anArgIter = theArgNb;
7461       }
7462
7463       aCamAnimation->SetCameraStart(aCams[0]);
7464       aCamAnimation->SetCameraEnd  (aCams[1]);
7465     }
7466     else
7467     {
7468       std::cout << "Syntax error at " << anArg << ".\n";
7469       return 1;
7470     }
7471   }
7472
7473   if (!toPlay && aRecFile.IsEmpty())
7474   {
7475     return 0;
7476   }
7477
7478   // Start animation timeline and process frame updating.
7479   TheIsAnimating = Standard_True;
7480   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7481   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7482   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7483   if (isFreeCamera)
7484   {
7485     aView->Camera()->Copy (aCameraBack);
7486   }
7487
7488   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7489   if (aRecParams.FpsNum <= 0)
7490   {
7491     while (!anAnimation->IsStopped())
7492     {
7493       aCameraBack->Copy (aView->Camera());
7494       const Standard_Real aPts = anAnimation->UpdateTimer();
7495       if (isFreeCamera)
7496       {
7497         aView->Camera()->Copy (aCameraBack);
7498       }
7499
7500       if (aPts >= anUpperPts)
7501       {
7502         anAnimation->Pause();
7503         break;
7504       }
7505
7506       if (aView->IsInvalidated())
7507       {
7508         aView->Redraw();
7509       }
7510       else
7511       {
7512         aView->RedrawImmediate();
7513       }
7514
7515       if (!isLockLoop)
7516       {
7517         // handle user events
7518         theDI.Eval ("after 1 set waiter 1");
7519         theDI.Eval ("vwait waiter");
7520       }
7521       if (!TheIsAnimating)
7522       {
7523         anAnimation->Pause();
7524         theDI << aPts;
7525         break;
7526       }
7527     }
7528
7529     if (aView->IsInvalidated())
7530     {
7531       aView->Redraw();
7532     }
7533     else
7534     {
7535       aView->RedrawImmediate();
7536     }
7537   }
7538   else
7539   {
7540     OSD_Timer aPerfTimer;
7541     aPerfTimer.Start();
7542
7543     Handle(Image_VideoRecorder) aRecorder;
7544     ImageFlipper aFlipper;
7545     Handle(Draw_ProgressIndicator) aProgress;
7546     if (!aRecFile.IsEmpty())
7547     {
7548       if (aRecParams.Width  <= 0
7549        || aRecParams.Height <= 0)
7550       {
7551         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7552       }
7553
7554       aRecorder = new Image_VideoRecorder();
7555       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7556       {
7557         std::cout << "Error: failed to open video file for recording\n";
7558         return 0;
7559       }
7560
7561       aProgress = new Draw_ProgressIndicator (theDI, 1);
7562     }
7563
7564     // Manage frame-rated animation here
7565     Standard_Real aPts = aPlayStartTime;
7566     int64_t aNbFrames = 0;
7567     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7568     Standard_Integer aSecondsProgress = 0;
7569     for (; aPts <= anUpperPts && aPSentry.More();)
7570     {
7571       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
7572       aPts = aPlayStartTime + aRecPts;
7573       ++aNbFrames;
7574       if (!anAnimation->Update (aPts))
7575       {
7576         break;
7577       }
7578
7579       if (!aRecorder.IsNull())
7580       {
7581         V3d_ImageDumpOptions aDumpParams;
7582         aDumpParams.Width          = aRecParams.Width;
7583         aDumpParams.Height         = aRecParams.Height;
7584         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
7585         aDumpParams.StereoOptions  = V3d_SDO_MONO;
7586         aDumpParams.ToAdjustAspect = Standard_True;
7587         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
7588         {
7589           std::cout << "Error: view dump is failed!\n";
7590           return 0;
7591         }
7592         aFlipper.FlipY (aRecorder->ChangeFrame());
7593         if (!aRecorder->PushFrame())
7594         {
7595           return 0;
7596         }
7597       }
7598       else
7599       {
7600         aView->Redraw();
7601       }
7602
7603       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7604       {
7605         aPSentry.Next();
7606         ++aSecondsProgress;
7607       }
7608     }
7609
7610     aPerfTimer.Stop();
7611     anAnimation->Stop();
7612     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7613     theDI << "Average FPS: " << aRecFps << "\n"
7614           << "Nb. Frames: "  << Standard_Real(aNbFrames);
7615
7616     aView->Redraw();
7617   }
7618
7619   aView->SetImmediateUpdate (wasImmediateUpdate);
7620   TheIsAnimating = Standard_False;
7621   return 0;
7622 }
7623
7624
7625 //=======================================================================
7626 //function : VChangeSelected
7627 //purpose  : Adds the shape to selection or remove one from it
7628 //=======================================================================
7629 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7630                                 Standard_Integer argc,
7631                                 const char ** argv)
7632 {
7633   if(argc != 2)
7634   {
7635     di<<"Usage : " << argv[0] << " shape \n";
7636     return 1;
7637   }
7638   //get AIS_Shape:
7639   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7640   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
7641   TCollection_AsciiString aName(argv[1]);
7642   Handle(AIS_InteractiveObject) anAISObject;
7643
7644   if(!aMap.IsBound2(aName))
7645   {
7646     di<<"Use 'vdisplay' before";
7647     return 1;
7648   }
7649   else
7650   {
7651     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
7652     if(anAISObject.IsNull()){
7653       di<<"No interactive object \n";
7654       return 1;
7655     }
7656
7657     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
7658   }
7659   return 0;
7660 }
7661
7662 //=======================================================================
7663 //function : VNbSelected
7664 //purpose  : Returns number of selected objects
7665 //=======================================================================
7666 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7667                                 Standard_Integer argc,
7668                                 const char ** argv)
7669 {
7670   if(argc != 1)
7671   {
7672     di << "Usage : " << argv[0] << "\n";
7673     return 1;
7674   }
7675   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7676   if(aContext.IsNull())
7677   {
7678     di << "use 'vinit' command before " << argv[0] << "\n";
7679     return 1;
7680   }
7681   di << aContext->NbSelected() << "\n";
7682   return 0;
7683 }
7684
7685 //=======================================================================
7686 //function : VPurgeDisplay
7687 //purpose  : Switches altialiasing on or off
7688 //=======================================================================
7689 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7690                                 Standard_Integer argc,
7691                                 const char ** argv)
7692 {
7693   if (argc > 1)
7694   {
7695     di << "Usage : " << argv[0] << "\n";
7696     return 1;
7697   }
7698   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7699   if (aContext.IsNull())
7700   {
7701     di << "use 'vinit' command before " << argv[0] << "\n";
7702     return 1;
7703   }
7704
7705   di << aContext->PurgeDisplay() << "\n";
7706   return 0;
7707 }
7708
7709 //=======================================================================
7710 //function : VSetViewSize
7711 //purpose  :
7712 //=======================================================================
7713 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7714                                 Standard_Integer argc,
7715                                 const char ** argv)
7716 {
7717   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7718   if(aContext.IsNull())
7719   {
7720     di << "use 'vinit' command before " << argv[0] << "\n";
7721     return 1;
7722   }
7723   if(argc != 2)
7724   {
7725     di<<"Usage : " << argv[0] << " Size\n";
7726     return 1;
7727   }
7728   Standard_Real aSize = Draw::Atof (argv[1]);
7729   if (aSize <= 0.)
7730   {
7731     di<<"Bad Size value  : " << aSize << "\n";
7732     return 1;
7733   }
7734
7735   Handle(V3d_View) aView = ViewerTest::CurrentView();
7736   aView->SetSize(aSize);
7737   return 0;
7738 }
7739
7740 //=======================================================================
7741 //function : VMoveView
7742 //purpose  :
7743 //=======================================================================
7744 static Standard_Integer VMoveView (Draw_Interpretor& di,
7745                                 Standard_Integer argc,
7746                                 const char ** argv)
7747 {
7748   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7749   if(aContext.IsNull())
7750   {
7751     di << "use 'vinit' command before " << argv[0] << "\n";
7752     return 1;
7753   }
7754   if(argc < 4 || argc > 5)
7755   {
7756     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7757     return 1;
7758   }
7759   Standard_Real Dx = Draw::Atof (argv[1]);
7760   Standard_Real Dy = Draw::Atof (argv[2]);
7761   Standard_Real Dz = Draw::Atof (argv[3]);
7762   Standard_Boolean aStart = Standard_True;
7763   if (argc == 5)
7764   {
7765       aStart = (Draw::Atoi (argv[4]) > 0);
7766   }
7767
7768   Handle(V3d_View) aView = ViewerTest::CurrentView();
7769   aView->Move(Dx,Dy,Dz,aStart);
7770   return 0;
7771 }
7772
7773 //=======================================================================
7774 //function : VTranslateView
7775 //purpose  :
7776 //=======================================================================
7777 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7778                                 Standard_Integer argc,
7779                                 const char ** argv)
7780 {
7781   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7782   if(aContext.IsNull())
7783   {
7784     di << "use 'vinit' command before " << argv[0] << "\n";
7785     return 1;
7786   }
7787   if(argc < 4 || argc > 5)
7788   {
7789     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7790     return 1;
7791   }
7792   Standard_Real Dx = Draw::Atof (argv[1]);
7793   Standard_Real Dy = Draw::Atof (argv[2]);
7794   Standard_Real Dz = Draw::Atof (argv[3]);
7795   Standard_Boolean aStart = Standard_True;
7796   if (argc == 5)
7797   {
7798       aStart = (Draw::Atoi (argv[4]) > 0);
7799   }
7800
7801   Handle(V3d_View) aView = ViewerTest::CurrentView();
7802   aView->Translate(Dx,Dy,Dz,aStart);
7803   return 0;
7804 }
7805
7806 //=======================================================================
7807 //function : VTurnView
7808 //purpose  :
7809 //=======================================================================
7810 static Standard_Integer VTurnView (Draw_Interpretor& di,
7811                                 Standard_Integer argc,
7812                                 const char ** argv)
7813 {
7814   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7815   if(aContext.IsNull()) {
7816     di << "use 'vinit' command before " << argv[0] << "\n";
7817     return 1;
7818   }
7819   if(argc < 4 || argc > 5){
7820     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7821     return 1;
7822   }
7823   Standard_Real Ax = Draw::Atof (argv[1]);
7824   Standard_Real Ay = Draw::Atof (argv[2]);
7825   Standard_Real Az = Draw::Atof (argv[3]);
7826   Standard_Boolean aStart = Standard_True;
7827   if (argc == 5)
7828   {
7829       aStart = (Draw::Atoi (argv[4]) > 0);
7830   }
7831
7832   Handle(V3d_View) aView = ViewerTest::CurrentView();
7833   aView->Turn(Ax,Ay,Az,aStart);
7834   return 0;
7835 }
7836
7837 //==============================================================================
7838 //function : VTextureEnv
7839 //purpose  : ENables or disables environment mapping
7840 //==============================================================================
7841 class OCC_TextureEnv : public Graphic3d_TextureEnv
7842 {
7843 public:
7844   OCC_TextureEnv(const Standard_CString FileName);
7845   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7846   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7847                             const Standard_Boolean theModulateFlag,
7848                             const Graphic3d_TypeOfTextureFilter theFilter,
7849                             const Standard_ShortReal theXScale,
7850                             const Standard_ShortReal theYScale,
7851                             const Standard_ShortReal theXShift,
7852                             const Standard_ShortReal theYShift,
7853                             const Standard_ShortReal theAngle);
7854   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7855 };
7856 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7857
7858 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7859   : Graphic3d_TextureEnv(theFileName)
7860 {
7861 }
7862
7863 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7864   : Graphic3d_TextureEnv(theTexId)
7865 {
7866 }
7867
7868 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7869                                           const Standard_Boolean theModulateFlag,
7870                                           const Graphic3d_TypeOfTextureFilter theFilter,
7871                                           const Standard_ShortReal theXScale,
7872                                           const Standard_ShortReal theYScale,
7873                                           const Standard_ShortReal theXShift,
7874                                           const Standard_ShortReal theYShift,
7875                                           const Standard_ShortReal theAngle)
7876 {
7877   myParams->SetRepeat     (theRepeatFlag);
7878   myParams->SetModulate   (theModulateFlag);
7879   myParams->SetFilter     (theFilter);
7880   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7881   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7882   myParams->SetRotation   (theAngle);
7883 }
7884
7885 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7886 {
7887   // get the active view
7888   Handle(V3d_View) aView = ViewerTest::CurrentView();
7889   if (aView.IsNull())
7890   {
7891     std::cerr << "No active view. Please call vinit.\n";
7892     return 1;
7893   }
7894
7895   // Checking the input arguments
7896   Standard_Boolean anEnableFlag = Standard_False;
7897   Standard_Boolean isOk         = theArgNb >= 2;
7898   if (isOk)
7899   {
7900     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7901     anEnableFlag = anEnableOpt.IsEqual("on");
7902     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7903   }
7904   if (anEnableFlag)
7905   {
7906     isOk = (theArgNb == 3 || theArgNb == 11);
7907     if (isOk)
7908     {
7909       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7910       isOk = (!aTextureOpt.IsIntegerValue() ||
7911              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7912
7913       if (isOk && theArgNb == 11)
7914       {
7915         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7916                                 aModulateOpt(theArgVec[4]),
7917                                 aFilterOpt  (theArgVec[5]),
7918                                 aSScaleOpt  (theArgVec[6]),
7919                                 aTScaleOpt  (theArgVec[7]),
7920                                 aSTransOpt  (theArgVec[8]),
7921                                 aTTransOpt  (theArgVec[9]),
7922                                 anAngleOpt  (theArgVec[10]);
7923         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7924                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7925                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7926                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7927                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7928                 anAngleOpt.IsRealValue());
7929       }
7930     }
7931   }
7932
7933   if (!isOk)
7934   {
7935     std::cerr << "Usage :" << std::endl;
7936     std::cerr << theArgVec[0] << " off" << std::endl;
7937     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;
7938     return 1;
7939   }
7940
7941   if (anEnableFlag)
7942   {
7943     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7944     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7945                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7946                                      new OCC_TextureEnv(theArgVec[2]);
7947
7948     if (theArgNb == 11)
7949     {
7950       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7951       aTexEnv->SetTextureParameters(
7952         aRepeatOpt.  IsEqual("repeat"),
7953         aModulateOpt.IsEqual("modulate"),
7954         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7955                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7956                                                                            Graphic3d_TOTF_TRILINEAR,
7957         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7958         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7959         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7960         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7961         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7962         );
7963     }
7964     aView->SetTextureEnv(aTexEnv);
7965   }
7966   else // Disabling environment mapping
7967   {
7968     Handle(Graphic3d_TextureEnv) aTexture;
7969     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7970   }
7971
7972   aView->Redraw();
7973   return 0;
7974 }
7975
7976 namespace
7977 {
7978   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7979
7980   //! Remove registered clipping plane from all views and objects.
7981   static void removePlane (MapOfPlanes& theRegPlanes,
7982                            const TCollection_AsciiString& theName)
7983   {
7984     Handle(Graphic3d_ClipPlane) aClipPlane;
7985     if (!theRegPlanes.Find (theName, aClipPlane))
7986     {
7987       std::cout << "Warning: no such plane.\n";
7988       return;
7989     }
7990
7991     theRegPlanes.UnBind (theName);
7992     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7993          anIObjIt.More(); anIObjIt.Next())
7994     {
7995       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7996       aPrs->RemoveClipPlane (aClipPlane);
7997     }
7998
7999     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8000          aViewIt.More(); aViewIt.Next())
8001     {
8002       const Handle(V3d_View)& aView = aViewIt.Key2();
8003       aView->RemoveClipPlane(aClipPlane);
8004     }
8005
8006     ViewerTest::RedrawAllViews();
8007   }
8008 }
8009
8010 //===============================================================================================
8011 //function : VClipPlane
8012 //purpose  :
8013 //===============================================================================================
8014 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8015 {
8016   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8017   static MapOfPlanes aRegPlanes;
8018
8019   if (theArgsNb < 2)
8020   {
8021     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8022     {
8023       theDi << aPlaneIter.Key() << " ";
8024     }
8025     return 0;
8026   }
8027
8028   TCollection_AsciiString aCommand (theArgVec[1]);
8029   aCommand.LowerCase();
8030   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8031   if (anActiveView.IsNull())
8032   {
8033     std::cout << "Error: no active view.\n";
8034     return 1;
8035   }
8036
8037   // print maximum number of planes for current viewer
8038   if (aCommand == "-maxplanes"
8039    || aCommand == "maxplanes")
8040   {
8041     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8042           << " plane slots provided by driver.\n";
8043     return 0;
8044   }
8045
8046   // create / delete plane instance
8047   if (aCommand == "-create"
8048    || aCommand == "create"
8049    || aCommand == "-delete"
8050    || aCommand == "delete"
8051    || aCommand == "-clone"
8052    || aCommand == "clone")
8053   {
8054     if (theArgsNb < 3)
8055     {
8056       std::cout << "Syntax error: plane name is required.\n";
8057       return 1;
8058     }
8059
8060     Standard_Boolean toCreate = aCommand == "-create"
8061                              || aCommand == "create";
8062     Standard_Boolean toClone  = aCommand == "-clone"
8063                              || aCommand == "clone";
8064     Standard_Boolean toDelete = aCommand == "-delete"
8065                              || aCommand == "delete";
8066     TCollection_AsciiString aPlane (theArgVec[2]);
8067
8068     if (toCreate)
8069     {
8070       if (aRegPlanes.IsBound (aPlane))
8071       {
8072         std::cout << "Warning: existing plane has been overridden.\n";
8073         toDelete = true;
8074       }
8075       else
8076       {
8077         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8078         return 0;
8079       }
8080     }
8081     else if (toClone) // toClone
8082     {
8083       if (!aRegPlanes.IsBound (aPlane))
8084       {
8085         std::cout << "Error: no such plane.\n";
8086         return 1;
8087       }
8088       else if (theArgsNb < 4)
8089       {
8090         std::cout << "Syntax error: enter name for new plane.\n";
8091         return 1;
8092       }
8093
8094       TCollection_AsciiString aClone (theArgVec[3]);
8095       if (aRegPlanes.IsBound (aClone))
8096       {
8097         std::cout << "Error: plane name is in use.\n";
8098         return 1;
8099       }
8100
8101       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8102
8103       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8104       return 0;
8105     }
8106
8107     if (toDelete)
8108     {
8109       if (aPlane == "ALL"
8110        || aPlane == "all"
8111        || aPlane == "*")
8112       {
8113         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8114         {
8115           aPlane = aPlaneIter.Key();
8116           removePlane (aRegPlanes, aPlane);
8117           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8118         }
8119       }
8120       else
8121       {
8122         removePlane (aRegPlanes, aPlane);
8123       }
8124     }
8125
8126     if (toCreate)
8127     {
8128       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8129     }
8130     return 0;
8131   }
8132
8133   // set / unset plane command
8134   if (aCommand == "set"
8135    || aCommand == "unset")
8136   {
8137     if (theArgsNb < 5)
8138     {
8139       std::cout << "Syntax error: need more arguments.\n";
8140       return 1;
8141     }
8142
8143     // redirect to new syntax
8144     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8145     anArgVec.SetValue (1, theArgVec[0]);
8146     anArgVec.SetValue (2, theArgVec[2]);
8147     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8148     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8149     {
8150       anArgVec.SetValue (anIt, theArgVec[anIt]);
8151     }
8152
8153     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8154   }
8155
8156   // change plane command
8157   TCollection_AsciiString aPlaneName;
8158   Handle(Graphic3d_ClipPlane) aClipPlane;
8159   Standard_Integer anArgIter = 0;
8160   if (aCommand == "-change"
8161    || aCommand == "change")
8162   {
8163     // old syntax support
8164     if (theArgsNb < 3)
8165     {
8166       std::cout << "Syntax error: need more arguments.\n";
8167       return 1;
8168     }
8169
8170     anArgIter  = 3;
8171     aPlaneName = theArgVec[2];
8172     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8173     {
8174       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8175       return 1;
8176     }
8177   }
8178   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8179   {
8180     anArgIter  = 2;
8181     aPlaneName = theArgVec[1];
8182   }
8183   else
8184   {
8185     anArgIter  = 2;
8186     aPlaneName = theArgVec[1];
8187     aClipPlane = new Graphic3d_ClipPlane();
8188     aRegPlanes.Bind (aPlaneName, aClipPlane);
8189     theDi << "Created new plane " << aPlaneName << ".\n";
8190   }
8191
8192   if (theArgsNb - anArgIter < 1)
8193   {
8194     std::cout << "Syntax error: need more arguments.\n";
8195     return 1;
8196   }
8197
8198   for (; anArgIter < theArgsNb; ++anArgIter)
8199   {
8200     const char**     aChangeArgs   = theArgVec + anArgIter;
8201     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8202     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8203     aChangeArg.LowerCase();
8204
8205     Standard_Boolean toEnable = Standard_True;
8206     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8207     {
8208       aClipPlane->SetOn (toEnable);
8209     }
8210     else if (aChangeArg == "-equation"
8211           || aChangeArg == "equation")
8212     {
8213       if (aNbChangeArgs < 5)
8214       {
8215         std::cout << "Syntax error: need more arguments.\n";
8216         return 1;
8217       }
8218
8219       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
8220       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
8221       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
8222       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
8223       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8224       anArgIter += 4;
8225     }
8226     else if (aChangeArg == "-capping"
8227           || aChangeArg == "capping")
8228     {
8229       if (aNbChangeArgs < 2)
8230       {
8231         std::cout << "Syntax error: need more arguments.\n";
8232         return 1;
8233       }
8234
8235       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8236       {
8237         aClipPlane->SetCapping (toEnable);
8238         anArgIter += 1;
8239       }
8240       else
8241       {
8242         // just skip otherwise (old syntax)
8243       }
8244     }
8245     else if (aChangeArg == "-useobjectmaterial"
8246           || aChangeArg == "-useobjectmat"
8247           || aChangeArg == "-useobjmat"
8248           || aChangeArg == "-useobjmaterial")
8249     {
8250       if (aNbChangeArgs < 2)
8251       {
8252         std::cout << "Syntax error: need more arguments.\n";
8253         return 1;
8254       }
8255
8256       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8257       {
8258         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8259         anArgIter += 1;
8260       }
8261     }
8262     else if (aChangeArg == "-useobjecttexture"
8263           || aChangeArg == "-useobjecttex"
8264           || aChangeArg == "-useobjtexture"
8265           || aChangeArg == "-useobjtex")
8266     {
8267       if (aNbChangeArgs < 2)
8268       {
8269         std::cout << "Syntax error: need more arguments.\n";
8270         return 1;
8271       }
8272
8273       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8274       {
8275         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8276         anArgIter += 1;
8277       }
8278     }
8279     else if (aChangeArg == "-useobjectshader"
8280           || aChangeArg == "-useobjshader")
8281     {
8282       if (aNbChangeArgs < 2)
8283       {
8284         std::cout << "Syntax error: need more arguments.\n";
8285         return 1;
8286       }
8287
8288       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8289       {
8290         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8291         anArgIter += 1;
8292       }
8293     }
8294     else if (aChangeArg == "-color"
8295           || aChangeArg == "color")
8296     {
8297       Quantity_Color aColor;
8298       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8299                                                            aChangeArgs + 1,
8300                                                            aColor);
8301       if (aNbParsed == 0)
8302       {
8303         std::cout << "Syntax error: need more arguments.\n";
8304         return 1;
8305       }
8306
8307       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8308       aMat.SetAmbientColor (aColor);
8309       aMat.SetDiffuseColor (aColor);
8310       aClipPlane->SetCappingMaterial (aMat);
8311       anArgIter += aNbParsed;
8312     }
8313     else if (aChangeArg == "-texname"
8314           || aChangeArg == "texname")
8315     {
8316       if (aNbChangeArgs < 2)
8317       {
8318         std::cout << "Syntax error: need more arguments.\n";
8319         return 1;
8320       }
8321
8322       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8323       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8324       if (!aTexture->IsDone())
8325       {
8326         aClipPlane->SetCappingTexture (NULL);
8327       }
8328       else
8329       {
8330         aTexture->EnableModulate();
8331         aTexture->EnableRepeat();
8332         aClipPlane->SetCappingTexture (aTexture);
8333       }
8334       anArgIter += 1;
8335     }
8336     else if (aChangeArg == "-texscale"
8337           || aChangeArg == "texscale")
8338     {
8339       if (aClipPlane->CappingTexture().IsNull())
8340       {
8341         std::cout << "Error: no texture is set.\n";
8342         return 1;
8343       }
8344
8345       if (aNbChangeArgs < 3)
8346       {
8347         std::cout << "Syntax error: need more arguments.\n";
8348         return 1;
8349       }
8350
8351       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8352       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8353       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8354       anArgIter += 2;
8355     }
8356     else if (aChangeArg == "-texorigin"
8357           || aChangeArg == "texorigin") // texture origin
8358     {
8359       if (aClipPlane->CappingTexture().IsNull())
8360       {
8361         std::cout << "Error: no texture is set.\n";
8362         return 1;
8363       }
8364
8365       if (aNbChangeArgs < 3)
8366       {
8367         std::cout << "Syntax error: need more arguments.\n";
8368         return 1;
8369       }
8370
8371       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8372       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8373
8374       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8375       anArgIter += 2;
8376     }
8377     else if (aChangeArg == "-texrotate"
8378           || aChangeArg == "texrotate") // texture rotation
8379     {
8380       if (aClipPlane->CappingTexture().IsNull())
8381       {
8382         std::cout << "Error: no texture is set.\n";
8383         return 1;
8384       }
8385
8386       if (aNbChangeArgs < 2)
8387       {
8388         std::cout << "Syntax error: need more arguments.\n";
8389         return 1;
8390       }
8391
8392       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8393       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8394       anArgIter += 1;
8395     }
8396     else if (aChangeArg == "-hatch"
8397           || aChangeArg == "hatch")
8398     {
8399       if (aNbChangeArgs < 2)
8400       {
8401         std::cout << "Syntax error: need more arguments.\n";
8402         return 1;
8403       }
8404
8405       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8406       aHatchStr.LowerCase();
8407       if (aHatchStr == "on")
8408       {
8409         aClipPlane->SetCappingHatchOn();
8410       }
8411       else if (aHatchStr == "off")
8412       {
8413         aClipPlane->SetCappingHatchOff();
8414       }
8415       else
8416       {
8417         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8418       }
8419       anArgIter += 1;
8420     }
8421     else if (aChangeArg == "-delete"
8422           || aChangeArg == "delete")
8423     {
8424       removePlane (aRegPlanes, aPlaneName);
8425       return 0;
8426     }
8427     else if (aChangeArg == "-set"
8428           || aChangeArg == "-unset")
8429     {
8430       // set / unset plane command
8431       Standard_Boolean toSet = aChangeArg == "-set";
8432       Standard_Integer anIt = 1;
8433       for (; anIt < aNbChangeArgs; ++anIt)
8434       {
8435         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8436         if (anEntityName.IsEmpty()
8437          || anEntityName.Value (1) == '-')
8438         {
8439           break;
8440         }
8441         else if (ViewerTest_myViews.IsBound1 (anEntityName))
8442         {
8443           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8444           if (toSet)
8445           {
8446             aView->AddClipPlane (aClipPlane);
8447           }
8448           else
8449           {
8450             aView->RemoveClipPlane (aClipPlane);
8451           }
8452           continue;
8453         }
8454         else if (GetMapOfAIS().IsBound2 (anEntityName))
8455         {
8456           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
8457           if (toSet)
8458           {
8459             aIObj->AddClipPlane (aClipPlane);
8460           }
8461           else
8462           {
8463             aIObj->RemoveClipPlane (aClipPlane);
8464           }
8465         }
8466         else
8467         {
8468           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
8469           return 1;
8470         }
8471       }
8472
8473       if (anIt == 1)
8474       {
8475         // apply to active view
8476         if (toSet)
8477         {
8478           anActiveView->AddClipPlane (aClipPlane);
8479         }
8480         else
8481         {
8482           anActiveView->RemoveClipPlane (aClipPlane);
8483         }
8484       }
8485       else
8486       {
8487         anArgIter = anArgIter + anIt - 1;
8488       }
8489     }
8490     else
8491     {
8492       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8493       return 1;
8494     }
8495   }
8496
8497   ViewerTest::RedrawAllViews();
8498   return 0;
8499 }
8500
8501 //===============================================================================================
8502 //function : VZRange
8503 //purpose  :
8504 //===============================================================================================
8505 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8506 {
8507   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8508
8509   if (aCurrentView.IsNull())
8510   {
8511     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8512     return 1;
8513   }
8514
8515   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
8516
8517   if (theArgsNb < 2)
8518   {
8519     theDi << "ZNear: " << aCamera->ZNear() << "\n";
8520     theDi << "ZFar: " << aCamera->ZFar() << "\n";
8521     return 0;
8522   }
8523
8524   if (theArgsNb == 3)
8525   {
8526     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8527     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
8528
8529     if (aNewZNear >= aNewZFar)
8530     {
8531       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
8532       return 1;
8533     }
8534
8535     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8536     {
8537       std::cout << theArgVec[0] << ": invalid arguments: ";
8538       std::cout << "znear, zfar should be positive for perspective camera.\n";
8539       return 1;
8540     }
8541
8542     aCamera->SetZRange (aNewZNear, aNewZFar);
8543   }
8544   else
8545   {
8546     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8547     return 1;
8548   }
8549
8550   aCurrentView->Redraw();
8551
8552   return 0;
8553 }
8554
8555 //===============================================================================================
8556 //function : VAutoZFit
8557 //purpose  :
8558 //===============================================================================================
8559 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8560 {
8561   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8562
8563   if (aCurrentView.IsNull())
8564   {
8565     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8566     return 1;
8567   }
8568
8569   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
8570
8571   if (theArgsNb > 3)
8572   {
8573     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8574     return 1;
8575   }
8576
8577   if (theArgsNb < 2)
8578   {
8579     theDi << "Auto z-fit mode: \n"
8580           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
8581           << "Scale: " << aScale << "\n";
8582     return 0;
8583   }
8584
8585   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
8586
8587   if (theArgsNb >= 3)
8588   {
8589     aScale = Draw::Atoi (theArgVec[2]);
8590   }
8591
8592   aCurrentView->SetAutoZFitMode (isOn, aScale);
8593   aCurrentView->AutoZFit();
8594   aCurrentView->Redraw();
8595
8596   return 0;
8597 }
8598
8599 //! Auxiliary function to print projection type
8600 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
8601 {
8602   switch (theProjType)
8603   {
8604     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
8605     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
8606     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
8607     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
8608     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
8609   }
8610   return "UNKNOWN";
8611 }
8612
8613 //===============================================================================================
8614 //function : VCamera
8615 //purpose  :
8616 //===============================================================================================
8617 static int VCamera (Draw_Interpretor& theDI,
8618                     Standard_Integer  theArgsNb,
8619                     const char**      theArgVec)
8620 {
8621   Handle(V3d_View) aView = ViewerTest::CurrentView();
8622   if (aView.IsNull())
8623   {
8624     std::cout << "Error: no active view.\n";
8625     return 1;
8626   }
8627
8628   Handle(Graphic3d_Camera) aCamera = aView->Camera();
8629   if (theArgsNb < 2)
8630   {
8631     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
8632     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
8633     theDI << "Distance:   " << aCamera->Distance() << "\n";
8634     theDI << "IOD:        " << aCamera->IOD() << "\n";
8635     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
8636     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
8637     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
8638     return 0;
8639   }
8640
8641   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8642   {
8643     Standard_CString        anArg = theArgVec[anArgIter];
8644     TCollection_AsciiString anArgCase (anArg);
8645     anArgCase.LowerCase();
8646     if (anArgCase == "-proj"
8647      || anArgCase == "-projection"
8648      || anArgCase == "-projtype"
8649      || anArgCase == "-projectiontype")
8650     {
8651       theDI << projTypeName (aCamera->ProjectionType()) << " ";
8652     }
8653     else if (anArgCase == "-ortho"
8654           || anArgCase == "-orthographic")
8655     {
8656       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8657     }
8658     else if (anArgCase == "-persp"
8659           || anArgCase == "-perspective"
8660           || anArgCase == "-perspmono"
8661           || anArgCase == "-perspectivemono"
8662           || anArgCase == "-mono")
8663     {
8664       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8665     }
8666     else if (anArgCase == "-stereo"
8667           || anArgCase == "-stereoscopic"
8668           || anArgCase == "-perspstereo"
8669           || anArgCase == "-perspectivestereo")
8670     {
8671       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8672     }
8673     else if (anArgCase == "-left"
8674           || anArgCase == "-lefteye"
8675           || anArgCase == "-monoleft"
8676           || anArgCase == "-monolefteye"
8677           || anArgCase == "-perpsleft"
8678           || anArgCase == "-perpslefteye")
8679     {
8680       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8681     }
8682     else if (anArgCase == "-right"
8683           || anArgCase == "-righteye"
8684           || anArgCase == "-monoright"
8685           || anArgCase == "-monorighteye"
8686           || anArgCase == "-perpsright")
8687     {
8688       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8689     }
8690     else if (anArgCase == "-dist"
8691           || anArgCase == "-distance")
8692     {
8693       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8694       if (anArgValue != NULL
8695       && *anArgValue != '-')
8696       {
8697         ++anArgIter;
8698         aCamera->SetDistance (Draw::Atof (anArgValue));
8699         continue;
8700       }
8701       theDI << aCamera->Distance() << " ";
8702     }
8703     else if (anArgCase == "-iod")
8704     {
8705       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8706       if (anArgValue != NULL
8707       && *anArgValue != '-')
8708       {
8709         ++anArgIter;
8710         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8711         continue;
8712       }
8713       theDI << aCamera->IOD() << " ";
8714     }
8715     else if (anArgCase == "-iodtype")
8716     {
8717       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8718       TCollection_AsciiString anValueCase (anArgValue);
8719       anValueCase.LowerCase();
8720       if (anValueCase == "abs"
8721        || anValueCase == "absolute")
8722       {
8723         ++anArgIter;
8724         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8725         continue;
8726       }
8727       else if (anValueCase == "rel"
8728             || anValueCase == "relative")
8729       {
8730         ++anArgIter;
8731         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8732         continue;
8733       }
8734       else if (*anArgValue != '-')
8735       {
8736         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8737         return 1;
8738       }
8739       switch (aCamera->GetIODType())
8740       {
8741         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8742         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8743       }
8744     }
8745     else if (anArgCase == "-zfocus")
8746     {
8747       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8748       if (anArgValue != NULL
8749       && *anArgValue != '-')
8750       {
8751         ++anArgIter;
8752         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8753         continue;
8754       }
8755       theDI << aCamera->ZFocus() << " ";
8756     }
8757     else if (anArgCase == "-zfocustype")
8758     {
8759       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8760       TCollection_AsciiString anValueCase (anArgValue);
8761       anValueCase.LowerCase();
8762       if (anValueCase == "abs"
8763        || anValueCase == "absolute")
8764       {
8765         ++anArgIter;
8766         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8767         continue;
8768       }
8769       else if (anValueCase == "rel"
8770             || anValueCase == "relative")
8771       {
8772         ++anArgIter;
8773         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8774         continue;
8775       }
8776       else if (*anArgValue != '-')
8777       {
8778         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8779         return 1;
8780       }
8781       switch (aCamera->ZFocusType())
8782       {
8783         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8784         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8785       }
8786     }
8787     else if (anArgCase == "-fov"
8788           || anArgCase == "-fovy")
8789     {
8790       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8791       if (anArgValue != NULL
8792       && *anArgValue != '-')
8793       {
8794         ++anArgIter;
8795         aCamera->SetFOVy (Draw::Atof (anArgValue));
8796         continue;
8797       }
8798       theDI << aCamera->FOVy() << " ";
8799     }
8800     else
8801     {
8802       std::cout << "Error: unknown argument '" << anArg << "'\n";
8803       return 1;
8804     }
8805   }
8806
8807   aView->AutoZFit();
8808   aView->Redraw();
8809
8810   return 0;
8811 }
8812
8813 //! Parse stereo output mode
8814 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8815                                          Graphic3d_StereoMode& theMode)
8816 {
8817   TCollection_AsciiString aFlag (theArg);
8818   aFlag.LowerCase();
8819   if (aFlag == "quadbuffer")
8820   {
8821     theMode = Graphic3d_StereoMode_QuadBuffer;
8822   }
8823   else if (aFlag == "anaglyph")
8824   {
8825     theMode = Graphic3d_StereoMode_Anaglyph;
8826   }
8827   else if (aFlag == "row"
8828         || aFlag == "rowinterlaced")
8829   {
8830     theMode = Graphic3d_StereoMode_RowInterlaced;
8831   }
8832   else if (aFlag == "col"
8833         || aFlag == "colinterlaced"
8834         || aFlag == "columninterlaced")
8835   {
8836     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8837   }
8838   else if (aFlag == "chess"
8839         || aFlag == "chessboard")
8840   {
8841     theMode = Graphic3d_StereoMode_ChessBoard;
8842   }
8843   else if (aFlag == "sbs"
8844         || aFlag == "sidebyside")
8845   {
8846     theMode = Graphic3d_StereoMode_SideBySide;
8847   }
8848   else if (aFlag == "ou"
8849         || aFlag == "overunder")
8850   {
8851     theMode = Graphic3d_StereoMode_OverUnder;
8852   }
8853   else if (aFlag == "pageflip"
8854         || aFlag == "softpageflip")
8855   {
8856     theMode = Graphic3d_StereoMode_SoftPageFlip;
8857   }
8858   else
8859   {
8860     return Standard_False;
8861   }
8862   return Standard_True;
8863 }
8864
8865 //! Parse anaglyph filter
8866 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8867                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8868 {
8869   TCollection_AsciiString aFlag (theArg);
8870   aFlag.LowerCase();
8871   if (aFlag == "redcyansimple")
8872   {
8873     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8874   }
8875   else if (aFlag == "redcyan"
8876         || aFlag == "redcyanoptimized")
8877   {
8878     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8879   }
8880   else if (aFlag == "yellowbluesimple")
8881   {
8882     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8883   }
8884   else if (aFlag == "yellowblue"
8885         || aFlag == "yellowblueoptimized")
8886   {
8887     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8888   }
8889   else if (aFlag == "greenmagenta"
8890         || aFlag == "greenmagentasimple")
8891   {
8892     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8893   }
8894   else
8895   {
8896     return Standard_False;
8897   }
8898   return Standard_True;
8899 }
8900
8901 //==============================================================================
8902 //function : VStereo
8903 //purpose  :
8904 //==============================================================================
8905
8906 static int VStereo (Draw_Interpretor& theDI,
8907                     Standard_Integer  theArgNb,
8908                     const char**      theArgVec)
8909 {
8910   Handle(V3d_View) aView = ViewerTest::CurrentView();
8911   if (theArgNb < 2)
8912   {
8913     if (aView.IsNull())
8914     {
8915       std::cout << "Error: no active viewer!\n";
8916       return 0;
8917     }
8918
8919     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8920     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8921     if (isActive)
8922     {
8923       TCollection_AsciiString aMode;
8924       switch (aView->RenderingParams().StereoMode)
8925       {
8926         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8927         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8928         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8929         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8930         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8931         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8932         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8933         case Graphic3d_StereoMode_Anaglyph  :
8934           aMode = "anaglyph";
8935           switch (aView->RenderingParams().AnaglyphFilter)
8936           {
8937             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8938             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8939             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8940             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8941             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8942             default: break;
8943           }
8944         default: break;
8945       }
8946       theDI << "Mode " << aMode << "\n";
8947     }
8948     return 0;
8949   }
8950
8951   Handle(Graphic3d_Camera) aCamera;
8952   Graphic3d_RenderingParams*   aParams   = NULL;
8953   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8954   if (!aView.IsNull())
8955   {
8956     aParams   = &aView->ChangeRenderingParams();
8957     aMode     = aParams->StereoMode;
8958     aCamera   = aView->Camera();
8959   }
8960
8961   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8962   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8963   {
8964     Standard_CString        anArg = theArgVec[anArgIter];
8965     TCollection_AsciiString aFlag (anArg);
8966     aFlag.LowerCase();
8967     if (anUpdateTool.parseRedrawMode (aFlag))
8968     {
8969       continue;
8970     }
8971     else if (aFlag == "0"
8972           || aFlag == "off")
8973     {
8974       if (++anArgIter < theArgNb)
8975       {
8976         std::cout << "Error: wrong number of arguments!\n";
8977         return 1;
8978       }
8979
8980       if (!aCamera.IsNull()
8981        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8982       {
8983         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8984       }
8985       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8986       return 0;
8987     }
8988     else if (aFlag == "1"
8989           || aFlag == "on")
8990     {
8991       if (++anArgIter < theArgNb)
8992       {
8993         std::cout << "Error: wrong number of arguments!\n";
8994         return 1;
8995       }
8996
8997       if (!aCamera.IsNull())
8998       {
8999         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9000       }
9001       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9002       return 0;
9003     }
9004     else if (aFlag == "-reverse"
9005           || aFlag == "-reversed"
9006           || aFlag == "-swap")
9007     {
9008       Standard_Boolean toEnable = Standard_True;
9009       if (++anArgIter < theArgNb
9010       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9011       {
9012         --anArgIter;
9013       }
9014       aParams->ToReverseStereo = toEnable;
9015     }
9016     else if (aFlag == "-noreverse"
9017           || aFlag == "-noswap")
9018     {
9019       Standard_Boolean toDisable = Standard_True;
9020       if (++anArgIter < theArgNb
9021       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9022       {
9023         --anArgIter;
9024       }
9025       aParams->ToReverseStereo = !toDisable;
9026     }
9027     else if (aFlag == "-mode"
9028           || aFlag == "-stereomode")
9029     {
9030       if (++anArgIter >= theArgNb
9031       || !parseStereoMode (theArgVec[anArgIter], aMode))
9032       {
9033         std::cout << "Error: syntax error at '" << anArg << "'\n";
9034         return 1;
9035       }
9036
9037       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9038       {
9039         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9040       }
9041     }
9042     else if (aFlag == "-anaglyph"
9043           || aFlag == "-anaglyphfilter")
9044     {
9045       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9046       if (++anArgIter >= theArgNb
9047       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9048       {
9049         std::cout << "Error: syntax error at '" << anArg << "'\n";
9050         return 1;
9051       }
9052
9053       aMode = Graphic3d_StereoMode_Anaglyph;
9054       aParams->AnaglyphFilter = aFilter;
9055     }
9056     else if (parseStereoMode (anArg, aMode)) // short syntax
9057     {
9058       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9059       {
9060         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9061       }
9062     }
9063     else
9064     {
9065       std::cout << "Error: syntax error at '" << anArg << "'\n";
9066       return 1;
9067     }
9068   }
9069
9070   if (!aView.IsNull())
9071   {
9072     aParams->StereoMode = aMode;
9073     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9074   }
9075   return 0;
9076 }
9077
9078 //===============================================================================================
9079 //function : VDefaults
9080 //purpose  :
9081 //===============================================================================================
9082 static int VDefaults (Draw_Interpretor& theDi,
9083                       Standard_Integer  theArgsNb,
9084                       const char**      theArgVec)
9085 {
9086   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9087   if (aCtx.IsNull())
9088   {
9089     std::cerr << "No active viewer!\n";
9090     return 1;
9091   }
9092
9093   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9094   if (theArgsNb < 2)
9095   {
9096     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9097     {
9098       theDi << "DeflType:           relative\n"
9099             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9100     }
9101     else
9102     {
9103       theDi << "DeflType:           absolute\n"
9104             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9105     }
9106     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9107     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9108     return 0;
9109   }
9110
9111   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9112   {
9113     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9114     anArg.UpperCase();
9115     if (anArg == "-ABSDEFL"
9116      || anArg == "-ABSOLUTEDEFLECTION"
9117      || anArg == "-DEFL"
9118      || anArg == "-DEFLECTION")
9119     {
9120       if (++anArgIter >= theArgsNb)
9121       {
9122         std::cout << "Error: wrong syntax at " << anArg << "\n";
9123         return 1;
9124       }
9125       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9126       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9127     }
9128     else if (anArg == "-RELDEFL"
9129           || anArg == "-RELATIVEDEFLECTION"
9130           || anArg == "-DEVCOEFF"
9131           || anArg == "-DEVIATIONCOEFF"
9132           || anArg == "-DEVIATIONCOEFFICIENT")
9133     {
9134       if (++anArgIter >= theArgsNb)
9135       {
9136         std::cout << "Error: wrong syntax at " << anArg << "\n";
9137         return 1;
9138       }
9139       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9140       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9141     }
9142     else if (anArg == "-ANGDEFL"
9143           || anArg == "-ANGULARDEFL"
9144           || anArg == "-ANGULARDEFLECTION")
9145     {
9146       if (++anArgIter >= theArgsNb)
9147       {
9148         std::cout << "Error: wrong syntax at " << anArg << "\n";
9149         return 1;
9150       }
9151       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9152       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9153     }
9154     else if (anArg == "-AUTOTR"
9155           || anArg == "-AUTOTRIANG"
9156           || anArg == "-AUTOTRIANGULATION")
9157     {
9158       if (++anArgIter >= theArgsNb)
9159       {
9160         std::cout << "Error: wrong syntax at " << anArg << "\n";
9161         return 1;
9162       }
9163       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9164       aValue.LowerCase();
9165       if (aValue == "on"
9166        || aValue == "1")
9167       {
9168         aDefParams->SetAutoTriangulation (Standard_True);
9169       }
9170       else if (aValue == "off"
9171             || aValue == "0")
9172       {
9173         aDefParams->SetAutoTriangulation (Standard_False);
9174       }
9175     }
9176     else
9177     {
9178       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9179     }
9180   }
9181
9182   return 0;
9183 }
9184
9185 //! Auxiliary method
9186 inline void addLight (const Handle(V3d_Light)& theLightNew,
9187                       const Standard_Boolean   theIsGlobal)
9188 {
9189   if (theLightNew.IsNull())
9190   {
9191     return;
9192   }
9193
9194   if (theIsGlobal)
9195   {
9196     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
9197   }
9198   else
9199   {
9200     ViewerTest::CurrentView()->SetLightOn (theLightNew);
9201   }
9202 }
9203
9204 //! Auxiliary method
9205 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9206 {
9207   TCollection_AsciiString anArgNextCase (theArgNext);
9208   anArgNextCase.UpperCase();
9209   if (anArgNextCase.Length() > 5
9210    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9211   {
9212     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9213   }
9214   else
9215   {
9216     return theArgNext.IntegerValue();
9217   }
9218 }
9219
9220 //===============================================================================================
9221 //function : VLight
9222 //purpose  :
9223 //===============================================================================================
9224 static int VLight (Draw_Interpretor& theDi,
9225                    Standard_Integer  theArgsNb,
9226                    const char**      theArgVec)
9227 {
9228   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9229   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9230   if (aView.IsNull()
9231    || aViewer.IsNull())
9232   {
9233     std::cerr << "No active viewer!\n";
9234     return 1;
9235   }
9236
9237   Standard_Real anXYZ[3]   = {};
9238   Standard_Real anAtten[2] = {};
9239   if (theArgsNb < 2)
9240   {
9241     // print lights info
9242     Standard_Integer aLightId = 0;
9243     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9244     {
9245       Handle(V3d_Light) aLight = aLightIter.Value();
9246       const Quantity_Color aColor = aLight->Color();
9247       theDi << "Light" << aLightId << "\n";
9248       switch (aLight->Type())
9249       {
9250         case V3d_AMBIENT:
9251         {
9252           theDi << "  Type:       Ambient\n";
9253           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9254           break;
9255         }
9256         case V3d_DIRECTIONAL:
9257         {
9258           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
9259           theDi << "  Type:       Directional\n";
9260           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9261           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9262           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9263           if (!aLightDir.IsNull())
9264           {
9265             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9266             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9267             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9268             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9269           }
9270           break;
9271         }
9272         case V3d_POSITIONAL:
9273         {
9274           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
9275           theDi << "  Type:       Positional\n";
9276           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9277           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9278           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9279           if (!aLightPos.IsNull())
9280           {
9281             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9282             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9283             aLightPos->Attenuation (anAtten[0], anAtten[1]);
9284             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9285           }
9286           break;
9287         }
9288         case V3d_SPOT:
9289         {
9290           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
9291           theDi << "  Type:       Spot\n";
9292           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9293           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9294           if (!aLightSpot.IsNull())
9295           {
9296             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9297             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9298             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9299             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9300             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9301             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9302             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
9303             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
9304           }
9305           break;
9306         }
9307         default:
9308         {
9309           theDi << "  Type:       UNKNOWN\n";
9310           break;
9311         }
9312       }
9313       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
9314     }
9315   }
9316
9317   Handle(V3d_Light) aLightNew;
9318   Handle(V3d_Light) aLightOld;
9319   Standard_Boolean  isGlobal = Standard_True;
9320   Standard_Boolean  toCreate = Standard_False;
9321   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9322   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9323   {
9324     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9325     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
9326     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
9327     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
9328     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
9329
9330     TCollection_AsciiString aName, aValue;
9331     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9332     TCollection_AsciiString anArgCase (anArg);
9333     anArgCase.UpperCase();
9334     if (anUpdateTool.parseRedrawMode (anArg))
9335     {
9336       continue;
9337     }
9338
9339     if (anArgCase.IsEqual ("NEW")
9340      || anArgCase.IsEqual ("ADD")
9341      || anArgCase.IsEqual ("CREATE"))
9342     {
9343       toCreate = Standard_True;
9344     }
9345     else if (anArgCase.IsEqual ("GLOB")
9346           || anArgCase.IsEqual ("GLOBAL"))
9347     {
9348       isGlobal = Standard_True;
9349     }
9350     else if (anArgCase.IsEqual ("LOC")
9351           || anArgCase.IsEqual ("LOCAL"))
9352     {
9353       isGlobal = Standard_False;
9354     }
9355     else if (anArgCase.IsEqual ("DEF")
9356           || anArgCase.IsEqual ("DEFAULTS"))
9357     {
9358       toCreate = Standard_False;
9359       aViewer->SetDefaultLights();
9360     }
9361     else if (anArgCase.IsEqual ("CLR")
9362           || anArgCase.IsEqual ("CLEAR"))
9363     {
9364       toCreate = Standard_False;
9365       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
9366       {
9367         Handle(V3d_Light) aLight = aLightIter.Value();
9368         aViewer->DelLight (aLight);
9369         aLightIter = aView->ActiveLightIterator();
9370       }
9371     }
9372     else if (anArgCase.IsEqual ("AMB")
9373           || anArgCase.IsEqual ("AMBIENT")
9374           || anArgCase.IsEqual ("AMBLIGHT"))
9375     {
9376       addLight (aLightNew, isGlobal);
9377       if (!toCreate)
9378       {
9379         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9380         return 1;
9381       }
9382       toCreate  = Standard_False;
9383       aLightNew = new V3d_AmbientLight (aViewer);
9384     }
9385     else if (anArgCase.IsEqual ("DIRECTIONAL")
9386           || anArgCase.IsEqual ("DIRLIGHT"))
9387     {
9388       addLight (aLightNew, isGlobal);
9389       if (!toCreate)
9390       {
9391         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9392         return 1;
9393       }
9394       toCreate  = Standard_False;
9395       aLightNew = new V3d_DirectionalLight (aViewer);
9396     }
9397     else if (anArgCase.IsEqual ("SPOT")
9398           || anArgCase.IsEqual ("SPOTLIGHT"))
9399     {
9400       addLight (aLightNew, isGlobal);
9401       if (!toCreate)
9402       {
9403         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9404         return 1;
9405       }
9406       toCreate  = Standard_False;
9407       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
9408     }
9409     else if (anArgCase.IsEqual ("POSLIGHT")
9410           || anArgCase.IsEqual ("POSITIONAL"))
9411     {
9412       addLight (aLightNew, isGlobal);
9413       if (!toCreate)
9414       {
9415         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9416         return 1;
9417       }
9418       toCreate  = Standard_False;
9419       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
9420     }
9421     else if (anArgCase.IsEqual ("CHANGE"))
9422     {
9423       addLight (aLightNew, isGlobal);
9424       aLightNew.Nullify();
9425       if (++anArgIt >= theArgsNb)
9426       {
9427         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9428         return 1;
9429       }
9430
9431       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
9432       Standard_Integer aLightIt = 0;
9433       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9434       {
9435         if (aLightIt == aLightId)
9436         {
9437           aLightOld = aLightIter.Value();
9438           break;
9439         }
9440       }
9441
9442       if (aLightOld.IsNull())
9443       {
9444         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
9445         return 1;
9446       }
9447     }
9448     else if (anArgCase.IsEqual ("DEL")
9449           || anArgCase.IsEqual ("DELETE"))
9450     {
9451       Handle(V3d_Light) aLightDel;
9452       if (++anArgIt >= theArgsNb)
9453       {
9454         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9455         return 1;
9456       }
9457
9458       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9459       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
9460       Standard_Integer aLightIt = 0;
9461       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9462       {
9463         aLightDel = aLightIter.Value();
9464         if (aLightIt == aLightDelId)
9465         {
9466           break;
9467         }
9468       }
9469       if (!aLightDel.IsNull())
9470       {
9471         aViewer->DelLight (aLightDel);
9472       }
9473     }
9474     else if (anArgCase.IsEqual ("COLOR")
9475           || anArgCase.IsEqual ("COLOUR"))
9476     {
9477       if (++anArgIt >= theArgsNb)
9478       {
9479         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9480         return 1;
9481       }
9482
9483       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9484       anArgNext.UpperCase();
9485       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
9486       if (!aLightCurr.IsNull())
9487       {
9488         aLightCurr->SetColor (aColor);
9489       }
9490     }
9491     else if (anArgCase.IsEqual ("POS")
9492           || anArgCase.IsEqual ("POSITION"))
9493     {
9494       if ((anArgIt + 3) >= theArgsNb)
9495       {
9496         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9497         return 1;
9498       }
9499
9500       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9501       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9502       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9503       if (!aLightDir.IsNull())
9504       {
9505         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9506       }
9507       else if (!aLightPos.IsNull())
9508       {
9509         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9510       }
9511       else if (!aLightSpot.IsNull())
9512       {
9513         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9514       }
9515       else
9516       {
9517         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9518         return 1;
9519       }
9520     }
9521     else if (anArgCase.IsEqual ("DIR")
9522           || anArgCase.IsEqual ("DIRECTION"))
9523     {
9524       if ((anArgIt + 3) >= theArgsNb)
9525       {
9526         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9527         return 1;
9528       }
9529
9530       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9531       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9532       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9533       if (!aLightDir.IsNull())
9534       {
9535         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9536       }
9537       else if (!aLightSpot.IsNull())
9538       {
9539         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9540       }
9541       else
9542       {
9543         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9544         return 1;
9545       }
9546     }
9547     else if (anArgCase.IsEqual ("SM")
9548           || anArgCase.IsEqual ("SMOOTHNESS"))
9549     {
9550       if (++anArgIt >= theArgsNb)
9551       {
9552         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9553         return 1;
9554       }
9555
9556       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
9557
9558       if (fabs (aSmoothness) < Precision::Confusion())
9559       {
9560         aLightCurr->SetIntensity (1.f);
9561       }
9562       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
9563       {
9564         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
9565       }
9566       else
9567       {
9568         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
9569         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
9570       }
9571
9572       if (!aLightPos.IsNull())
9573       {
9574         aLightPos->SetSmoothRadius (aSmoothness);
9575       }
9576       else if (!aLightDir.IsNull())
9577       {
9578         aLightDir->SetSmoothAngle (aSmoothness);
9579       }
9580     }
9581     else if (anArgCase.IsEqual ("INT")
9582           || anArgCase.IsEqual ("INTENSITY"))
9583     {
9584       if (++anArgIt >= theArgsNb)
9585       {
9586         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9587         return 1;
9588       }
9589
9590       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
9591
9592       if (!aLightCurr.IsNull())
9593       {
9594         aLightCurr->SetIntensity (aIntensity);
9595       }
9596     }
9597     else if (anArgCase.IsEqual ("ANG")
9598           || anArgCase.IsEqual ("ANGLE"))
9599     {
9600       if (++anArgIt >= theArgsNb)
9601       {
9602         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9603         return 1;
9604       }
9605
9606       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
9607
9608       if (!aLightSpot.IsNull())
9609       {
9610         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
9611       }
9612     }
9613     else if (anArgCase.IsEqual ("CONSTATTEN")
9614           || anArgCase.IsEqual ("CONSTATTENUATION"))
9615     {
9616       if (++anArgIt >= theArgsNb)
9617       {
9618         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9619         return 1;
9620       }
9621
9622       if (!aLightPos.IsNull())
9623       {
9624         aLightPos->Attenuation (anAtten[0], anAtten[1]);
9625         anAtten[0] = Atof (theArgVec[anArgIt]);
9626         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
9627       }
9628       else if (!aLightSpot.IsNull())
9629       {
9630         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9631         anAtten[0] = Atof (theArgVec[anArgIt]);
9632         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
9633       }
9634       else
9635       {
9636         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9637         return 1;
9638       }
9639     }
9640     else if (anArgCase.IsEqual ("LINATTEN")
9641           || anArgCase.IsEqual ("LINEARATTEN")
9642           || anArgCase.IsEqual ("LINEARATTENUATION"))
9643     {
9644       if (++anArgIt >= theArgsNb)
9645       {
9646         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9647         return 1;
9648       }
9649
9650       if (!aLightPos.IsNull())
9651       {
9652         aLightPos->Attenuation (anAtten[0], anAtten[1]);
9653         anAtten[1] = Atof (theArgVec[anArgIt]);
9654         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
9655       }
9656       else if (!aLightSpot.IsNull())
9657       {
9658         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
9659         anAtten[1] = Atof (theArgVec[anArgIt]);
9660         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
9661       }
9662       else
9663       {
9664         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9665         return 1;
9666       }
9667     }
9668     else if (anArgCase.IsEqual ("EXP")
9669           || anArgCase.IsEqual ("EXPONENT")
9670           || anArgCase.IsEqual ("SPOTEXP")
9671           || anArgCase.IsEqual ("SPOTEXPONENT"))
9672     {
9673       if (++anArgIt >= theArgsNb)
9674       {
9675         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9676         return 1;
9677       }
9678
9679       if (!aLightSpot.IsNull())
9680       {
9681         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
9682       }
9683       else
9684       {
9685         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9686         return 1;
9687       }
9688     }
9689     else if (anArgCase.IsEqual ("HEAD")
9690           || anArgCase.IsEqual ("HEADLIGHT"))
9691     {
9692       if (++anArgIt >= theArgsNb)
9693       {
9694         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9695         return 1;
9696       }
9697
9698       if (aLightAmb.IsNull()
9699        && !aLightCurr.IsNull())
9700       {
9701         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
9702       }
9703       else
9704       {
9705         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9706         return 1;
9707       }
9708     }
9709     else
9710     {
9711       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9712     }
9713   }
9714
9715   addLight (aLightNew, isGlobal);
9716   aViewer->UpdateLights();
9717
9718   return 0;
9719 }
9720
9721 //=======================================================================
9722 //function : VRenderParams
9723 //purpose  : Enables/disables rendering features
9724 //=======================================================================
9725
9726 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9727                                        Standard_Integer  theArgNb,
9728                                        const char**      theArgVec)
9729 {
9730   Handle(V3d_View) aView = ViewerTest::CurrentView();
9731   if (aView.IsNull())
9732   {
9733     std::cerr << "Error: no active viewer!\n";
9734     return 1;
9735   }
9736
9737   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9738   TCollection_AsciiString aCmdName (theArgVec[0]);
9739   aCmdName.LowerCase();
9740   if (aCmdName == "vraytrace")
9741   {
9742     if (theArgNb == 1)
9743     {
9744       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9745       return 0;
9746     }
9747     else if (theArgNb == 2)
9748     {
9749       TCollection_AsciiString aValue (theArgVec[1]);
9750       aValue.LowerCase();
9751       if (aValue == "on"
9752        || aValue == "1")
9753       {
9754         aParams.Method = Graphic3d_RM_RAYTRACING;
9755         aView->Redraw();
9756         return 0;
9757       }
9758       else if (aValue == "off"
9759             || aValue == "0")
9760       {
9761         aParams.Method = Graphic3d_RM_RASTERIZATION;
9762         aView->Redraw();
9763         return 0;
9764       }
9765       else
9766       {
9767         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9768         return 1;
9769       }
9770     }
9771     else
9772     {
9773       std::cout << "Error: wrong number of arguments\n";
9774       return 1;
9775     }
9776   }
9777
9778   if (theArgNb < 2)
9779   {
9780     theDI << "renderMode:  ";
9781     switch (aParams.Method)
9782     {
9783       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9784       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9785     }
9786     theDI << "\n";
9787     theDI << "transparency:  ";
9788     switch (aParams.TransparencyMethod)
9789     {
9790       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
9791       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
9792                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
9793     }
9794     theDI << "\n";
9795     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9796     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
9797     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9798     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9799     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9800     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9801     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9802     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9803     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9804     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9805     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9806     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9807     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
9808     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
9809     theDI << "shadingModel: ";
9810     switch (aView->ShadingModel())
9811     {
9812       case V3d_COLOR:   theDI << "color";   break;
9813       case V3d_FLAT:    theDI << "flat";    break;
9814       case V3d_GOURAUD: theDI << "gouraud"; break;
9815       case V3d_PHONG:   theDI << "phong";   break;
9816     }
9817     theDI << "\n";
9818     return 0;
9819   }
9820
9821   Standard_Boolean toPrint = Standard_False;
9822   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9823   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9824   {
9825     Standard_CString        anArg (theArgVec[anArgIter]);
9826     TCollection_AsciiString aFlag (anArg);
9827     aFlag.LowerCase();
9828     if (anUpdateTool.parseRedrawMode (aFlag))
9829     {
9830       continue;
9831     }
9832     else if (aFlag == "-echo"
9833           || aFlag == "-print")
9834     {
9835       toPrint = Standard_True;
9836       anUpdateTool.Invalidate();
9837     }
9838     else if (aFlag == "-mode"
9839           || aFlag == "-rendermode"
9840           || aFlag == "-render_mode")
9841     {
9842       if (toPrint)
9843       {
9844         switch (aParams.Method)
9845         {
9846           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9847           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9848         }
9849         continue;
9850       }
9851       else
9852       {
9853         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9854         return 1;
9855       }
9856     }
9857     else if (aFlag == "-ray"
9858           || aFlag == "-raytrace")
9859     {
9860       if (toPrint)
9861       {
9862         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9863         continue;
9864       }
9865
9866       aParams.Method = Graphic3d_RM_RAYTRACING;
9867     }
9868     else if (aFlag == "-rast"
9869           || aFlag == "-raster"
9870           || aFlag == "-rasterization")
9871     {
9872       if (toPrint)
9873       {
9874         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9875         continue;
9876       }
9877
9878       aParams.Method = Graphic3d_RM_RASTERIZATION;
9879     }
9880     else if (aFlag == "-msaa")
9881     {
9882       if (toPrint)
9883       {
9884         theDI << aParams.NbMsaaSamples << " ";
9885         continue;
9886       }
9887       else if (++anArgIter >= theArgNb)
9888       {
9889         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9890         return 1;
9891       }
9892
9893       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9894       if (aNbSamples < 0)
9895       {
9896         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9897         return 1;
9898       }
9899       else
9900       {
9901         aParams.NbMsaaSamples = aNbSamples;
9902       }
9903     }
9904     else if (aFlag == "-oit")
9905     {
9906       if (toPrint)
9907       {
9908         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
9909         {
9910           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
9911         }
9912         else
9913         {
9914           theDI << "off" << " ";
9915         }
9916         continue;
9917       }
9918       else if (++anArgIter >= theArgNb)
9919       {
9920         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9921         return 1;
9922       }
9923
9924       TCollection_AsciiString aParam = theArgVec[anArgIter];
9925       aParam.LowerCase();
9926       if (aParam.IsRealValue())
9927       {
9928         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
9929         if (aWeight < 0.f || aWeight > 1.f)
9930         {
9931           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
9932           return 1;
9933         }
9934
9935         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
9936         aParams.OitDepthFactor     = aWeight;
9937       }
9938       else if (aParam == "off")
9939       {
9940         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
9941       }
9942       else
9943       {
9944         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9945         return 1;
9946       }
9947     }
9948     else if (aFlag == "-rendscale"
9949           || aFlag == "-renderscale"
9950           || aFlag == "-renderresolutionscale")
9951     {
9952       if (toPrint)
9953       {
9954         theDI << aParams.RenderResolutionScale << " ";
9955         continue;
9956       }
9957       else if (++anArgIter >= theArgNb)
9958       {
9959         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9960         return 1;
9961       }
9962
9963       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
9964       if (aScale < 0.01)
9965       {
9966         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
9967         return 1;
9968       }
9969       else
9970       {
9971         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
9972       }
9973     }
9974     else if (aFlag == "-raydepth"
9975           || aFlag == "-ray_depth")
9976     {
9977       if (toPrint)
9978       {
9979         theDI << aParams.RaytracingDepth << " ";
9980         continue;
9981       }
9982       else if (++anArgIter >= theArgNb)
9983       {
9984         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9985         return 1;
9986       }
9987
9988       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9989
9990       // We allow RaytracingDepth be more than 10 in case of GI enabled
9991       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9992       {
9993         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9994         return 1;
9995       }
9996       else
9997       {
9998         aParams.RaytracingDepth = aDepth;
9999       }
10000     }
10001     else if (aFlag == "-shad"
10002           || aFlag == "-shadows")
10003     {
10004       if (toPrint)
10005       {
10006         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
10007         continue;
10008       }
10009
10010       Standard_Boolean toEnable = Standard_True;
10011       if (++anArgIter < theArgNb
10012       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10013       {
10014         --anArgIter;
10015       }
10016       aParams.IsShadowEnabled = toEnable;
10017     }
10018     else if (aFlag == "-refl"
10019           || aFlag == "-reflections")
10020     {
10021       if (toPrint)
10022       {
10023         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10024         continue;
10025       }
10026
10027       Standard_Boolean toEnable = Standard_True;
10028       if (++anArgIter < theArgNb
10029       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10030       {
10031         --anArgIter;
10032       }
10033       aParams.IsReflectionEnabled = toEnable;
10034     }
10035     else if (aFlag == "-fsaa")
10036     {
10037       if (toPrint)
10038       {
10039         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10040         continue;
10041       }
10042
10043       Standard_Boolean toEnable = Standard_True;
10044       if (++anArgIter < theArgNb
10045       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10046       {
10047         --anArgIter;
10048       }
10049       aParams.IsAntialiasingEnabled = toEnable;
10050     }
10051     else if (aFlag == "-gleam")
10052     {
10053       if (toPrint)
10054       {
10055         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10056         continue;
10057       }
10058
10059       Standard_Boolean toEnable = Standard_True;
10060       if (++anArgIter < theArgNb
10061       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10062       {
10063         --anArgIter;
10064       }
10065       aParams.IsTransparentShadowEnabled = toEnable;
10066     }
10067     else if (aFlag == "-gi")
10068     {
10069       if (toPrint)
10070       {
10071         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10072         continue;
10073       }
10074
10075       Standard_Boolean toEnable = Standard_True;
10076       if (++anArgIter < theArgNb
10077       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10078       {
10079         --anArgIter;
10080       }
10081       aParams.IsGlobalIlluminationEnabled = toEnable;
10082       if (!toEnable)
10083       {
10084         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10085       }
10086     }
10087     else if (aFlag == "-blockedrng"
10088           || aFlag == "-brng")
10089     {
10090       if (toPrint)
10091       {
10092         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10093         continue;
10094       }
10095
10096       Standard_Boolean toEnable = Standard_True;
10097       if (++anArgIter < theArgNb
10098         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10099       {
10100         --anArgIter;
10101       }
10102       aParams.CoherentPathTracingMode = toEnable;
10103     }
10104     else if (aFlag == "-maxrad")
10105     {
10106       if (toPrint)
10107       {
10108         theDI << aParams.RadianceClampingValue << " ";
10109         continue;
10110       }
10111       else if (++anArgIter >= theArgNb)
10112       {
10113         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10114         return 1;
10115       }
10116
10117       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10118       if (!aMaxRadStr.IsRealValue())
10119       {
10120         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10121         return 1;
10122       }
10123
10124       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10125       if (aMaxRadiance <= 0.0)
10126       {
10127         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10128         return 1;
10129       }
10130       else
10131       {
10132         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
10133       }
10134     }
10135     else if (aFlag == "-iss")
10136     {
10137       if (toPrint)
10138       {
10139         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
10140         continue;
10141       }
10142
10143       Standard_Boolean toEnable = Standard_True;
10144       if (++anArgIter < theArgNb
10145         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10146       {
10147         --anArgIter;
10148       }
10149       aParams.AdaptiveScreenSampling = toEnable;
10150     }
10151     else if (aFlag == "-issd")
10152     {
10153       if (toPrint)
10154       {
10155         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
10156         continue;
10157       }
10158
10159       Standard_Boolean toEnable = Standard_True;
10160       if (++anArgIter < theArgNb
10161         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10162       {
10163         --anArgIter;
10164       }
10165       aParams.ShowSamplingTiles = toEnable;
10166     }
10167     else if (aFlag == "-nbtiles")
10168     {
10169       if (toPrint)
10170       {
10171         theDI << aParams.NbRayTracingTiles << " ";
10172         continue;
10173       }
10174       else if (++anArgIter >= theArgNb)
10175       {
10176         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10177         return 1;
10178       }
10179
10180       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
10181
10182       if (aNbTiles < 64)
10183       {
10184         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
10185         std::cerr << "Specify value in range [64, 1024].\n";
10186         return 1;
10187       }
10188       else
10189       {
10190         aParams.NbRayTracingTiles = aNbTiles;
10191       }
10192     }
10193     else if (aFlag == "-env")
10194     {
10195       if (toPrint)
10196       {
10197         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
10198         continue;
10199       }
10200
10201       Standard_Boolean toEnable = Standard_True;
10202       if (++anArgIter < theArgNb
10203         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10204       {
10205         --anArgIter;
10206       }
10207       aParams.UseEnvironmentMapBackground = toEnable;
10208     }
10209     else if (aFlag == "-twoside")
10210     {
10211       if (toPrint)
10212       {
10213         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
10214         continue;
10215       }
10216
10217       Standard_Boolean toEnable = Standard_True;
10218       if (++anArgIter < theArgNb
10219         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10220       {
10221         --anArgIter;
10222       }
10223       aParams.TwoSidedBsdfModels = toEnable;
10224     }
10225     else if (aFlag == "-shademodel"
10226           || aFlag == "-shadingmodel"
10227           || aFlag == "-shading")
10228     {
10229       if (toPrint)
10230       {
10231         switch (aView->ShadingModel())
10232         {
10233           case V3d_COLOR:   theDI << "color ";   break;
10234           case V3d_FLAT:    theDI << "flat ";    break;
10235           case V3d_GOURAUD: theDI << "gouraud "; break;
10236           case V3d_PHONG:   theDI << "phong ";   break;
10237         }
10238         continue;
10239       }
10240
10241       if (++anArgIter >= theArgNb)
10242       {
10243         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10244       }
10245
10246       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10247       aMode.LowerCase();
10248       if (aMode == "color"
10249        || aMode == "none")
10250       {
10251         aView->SetShadingModel (V3d_COLOR);
10252       }
10253       else if (aMode == "flat"
10254             || aMode == "facet")
10255       {
10256         aView->SetShadingModel (V3d_FLAT);
10257       }
10258       else if (aMode == "gouraud"
10259             || aMode == "vertex"
10260             || aMode == "vert")
10261       {
10262         aView->SetShadingModel (V3d_GOURAUD);
10263       }
10264       else if (aMode == "phong"
10265             || aMode == "fragment"
10266             || aMode == "frag"
10267             || aMode == "pixel")
10268       {
10269         aView->SetShadingModel (V3d_PHONG);
10270       }
10271       else
10272       {
10273         std::cout << "Error: unknown shading model '" << aMode << "'\n";
10274         return 1;
10275       }
10276     }
10277     else if (aFlag == "-resolution")
10278     {
10279       if (++anArgIter >= theArgNb)
10280       {
10281         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10282         return 1;
10283       }
10284
10285       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
10286       if (aResolution.IsIntegerValue())
10287       {
10288         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
10289       }
10290       else
10291       {
10292         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10293         return 1;
10294       }
10295     }
10296     else if (aFlag == "-rebuildglsl"
10297           || aFlag == "-rebuild")
10298     {
10299       if (toPrint)
10300       {
10301         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
10302         continue;
10303       }
10304
10305       Standard_Boolean toEnable = Standard_True;
10306       if (++anArgIter < theArgNb
10307           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10308       {
10309         --anArgIter;
10310       }
10311       aParams.RebuildRayTracingShaders = toEnable;
10312     }
10313     else if (aFlag == "-focal")
10314     {
10315       if (++anArgIter >= theArgNb)
10316       {
10317         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10318         return 1;
10319       }
10320
10321       TCollection_AsciiString aParam (theArgVec[anArgIter]);
10322       if (aParam.IsRealValue())
10323       {
10324         float aFocalDist = static_cast<float> (aParam.RealValue());
10325         if (aFocalDist < 0)
10326         {
10327           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10328           return 1;
10329         }
10330         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
10331       }
10332       else
10333       {
10334         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10335         return 1;
10336       }
10337     }
10338     else if (aFlag == "-aperture")
10339     {
10340       if (++anArgIter >= theArgNb)
10341       {
10342         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10343         return 1;
10344       }
10345
10346       TCollection_AsciiString aParam(theArgVec[anArgIter]);
10347       if (aParam.IsRealValue())
10348       {
10349         float aApertureSize = static_cast<float> (aParam.RealValue());
10350         if (aApertureSize < 0)
10351         {
10352           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10353           return 1;
10354         }
10355         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
10356       }
10357       else
10358       {
10359         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10360         return 1;
10361       }
10362     }
10363     else if (aFlag == "-exposure")
10364     {
10365       if (++anArgIter >= theArgNb)
10366       {
10367         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10368         return 1;
10369       }
10370
10371       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
10372       if (anExposure.IsRealValue())
10373       {
10374         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
10375       }
10376       else
10377       {
10378         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10379         return 1;
10380       }
10381     }
10382     else if (aFlag == "-whitepoint")
10383     {
10384       if (++anArgIter >= theArgNb)
10385       {
10386         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10387         return 1;
10388       }
10389
10390       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
10391       if (aWhitePoint.IsRealValue())
10392       {
10393         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
10394       }
10395       else
10396       {
10397         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10398         return 1;
10399       }
10400     }
10401     else if (aFlag == "-tonemapping")
10402     {
10403       if (++anArgIter >= theArgNb)
10404       {
10405         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10406         return 1;
10407       }
10408
10409       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10410       aMode.LowerCase();
10411
10412       if (aMode == "disabled")
10413       {
10414         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
10415       }
10416       else if (aMode == "filmic")
10417       {
10418         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
10419       }
10420       else
10421       {
10422         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10423         return 1;
10424       }
10425     }
10426     else
10427     {
10428       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
10429       return 1;
10430     }
10431   }
10432
10433   return 0;
10434 }
10435
10436 //=======================================================================
10437 //function : VProgressiveMode
10438 //purpose  :
10439 //=======================================================================
10440 #if defined(_WIN32)
10441 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
10442                                           Standard_Integer  /*theNbArgs*/,
10443                                           const char**      /*theArgs*/)
10444 {
10445   Handle(V3d_View) aView = ViewerTest::CurrentView();
10446   if (aView.IsNull())
10447   {
10448     std::cerr << "Error: no active viewer!\n";
10449     return 1;
10450   }
10451
10452   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
10453
10454   for (;;)
10455   {
10456     aView->Redraw();
10457
10458     Standard_Boolean toExit = Standard_False;
10459
10460     MSG aMsg;
10461     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
10462     {
10463       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
10464       {
10465         toExit = Standard_True;
10466       }
10467
10468       TranslateMessage (&aMsg);
10469       DispatchMessageW (&aMsg);
10470     }
10471
10472     if (toExit)
10473     {
10474       break;
10475     }
10476   }
10477
10478   return 0;
10479 }
10480 #endif
10481
10482 //=======================================================================
10483 //function : VFrustumCulling
10484 //purpose  : enables/disables view volume's culling.
10485 //=======================================================================
10486 static int VFrustumCulling (Draw_Interpretor& theDI,
10487                             Standard_Integer  theArgNb,
10488                             const char**      theArgVec)
10489 {
10490   Handle(V3d_View) aView = ViewerTest::CurrentView();
10491   if (aView.IsNull())
10492   {
10493     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
10494     return 1;
10495   }
10496
10497   if (theArgNb < 2)
10498   {
10499     theDI << (aView->IsCullingEnabled() ? "on" : "off");
10500     return 0;
10501   }
10502   else if (theArgNb != 2)
10503   {
10504     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
10505     return 1;
10506   }
10507
10508   TCollection_AsciiString aModeStr (theArgVec[1]);
10509   aModeStr.LowerCase();
10510   Standard_Boolean toEnable = 0;
10511   if (aModeStr == "on")
10512   {
10513     toEnable = 1;
10514   }
10515   else if (aModeStr == "off")
10516   {
10517     toEnable = 0;
10518   }
10519   else
10520   {
10521     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10522   }
10523
10524   aView->SetFrustumCulling (toEnable);
10525   aView->Redraw();
10526   return 0;
10527 }
10528
10529 //=======================================================================
10530 //function : VHighlightSelected
10531 //purpose  : 
10532 //=======================================================================
10533 static int VHighlightSelected (Draw_Interpretor& theDI,
10534                                Standard_Integer  theArgNb,
10535                                const char**      theArgVec)
10536 {
10537   if (ViewerTest::GetAISContext().IsNull())
10538   {
10539     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
10540     return 1;
10541   }
10542
10543   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10544
10545   if (theArgNb < 2)
10546   {
10547     theDI << (aContext->ToHilightSelected() ? "on" : "off");
10548     return 0;
10549   }
10550
10551   if (theArgNb != 2)
10552   {
10553     std::cout  << theArgVec[0] << " error : wrong number of parameters."
10554           << "Type 'help" << theArgVec[0] << "' for more information.";
10555     return 1;
10556   }
10557
10558   // Parse parameter
10559   TCollection_AsciiString aMode (theArgVec[1]);
10560   aMode.LowerCase();
10561   Standard_Boolean toEnable = Standard_False;
10562   if (aMode.IsEqual ("on"))
10563   {
10564     toEnable = Standard_True;
10565   }
10566   else if (aMode.IsEqual ("off"))
10567   {
10568     toEnable = Standard_False;
10569   }
10570   else
10571   {
10572     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10573   }
10574
10575   if (toEnable != aContext->ToHilightSelected())
10576   {
10577     aContext->SetToHilightSelected (toEnable);
10578
10579     // Move cursor to null position and  back to process updating of detection
10580     // and highlighting of selected object immediatly.
10581     Standard_Integer aPixX = 0;
10582     Standard_Integer aPixY = 0;
10583     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
10584
10585     anEventManager->GetCurrentPosition (aPixX, aPixY);
10586     anEventManager->MoveTo (0, 0);
10587     anEventManager->MoveTo (aPixX, aPixY);
10588   }
10589
10590   return 0;
10591 }
10592
10593 //=======================================================================
10594 //function : VXRotate
10595 //purpose  :
10596 //=======================================================================
10597 static Standard_Integer VXRotate (Draw_Interpretor& di,
10598                                    Standard_Integer argc,
10599                                    const char ** argv)
10600 {
10601   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10602   if (aContext.IsNull())
10603   {
10604     di << argv[0] << "ERROR : use 'vinit' command before \n";
10605     return 1;
10606   }
10607   
10608   if (argc != 3)
10609   {
10610     di << "ERROR : Usage : " << argv[0] << " name angle\n";
10611     return 1;
10612   }
10613
10614   TCollection_AsciiString aName (argv[1]);
10615   Standard_Real anAngle = Draw::Atof (argv[2]);
10616
10617   // find object
10618   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
10619   Handle(AIS_InteractiveObject) anIObj;
10620   if (!aMap.IsBound2 (aName) )
10621   {
10622     di << "Use 'vdisplay' before\n";
10623     return 1;
10624   }
10625   else
10626   {
10627     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
10628
10629     gp_Trsf aTransform;
10630     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
10631     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
10632
10633     aContext->SetLocation (anIObj, aTransform);
10634     aContext->UpdateCurrentViewer();
10635   }
10636
10637   return 0;
10638 }
10639
10640 //===============================================================================================
10641 //class   : ViewerTest_AISManipulator
10642 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
10643 //===============================================================================================
10644 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10645
10646 class ViewerTest_AISManipulator : public AIS_Manipulator
10647 {
10648 public:
10649
10650   ViewerTest_AISManipulator() : AIS_Manipulator()
10651   {
10652     GetMapOfAISManipulators().Add (this);
10653   }
10654
10655   virtual ~ViewerTest_AISManipulator()
10656   {
10657     GetMapOfAISManipulators().Remove (this);
10658   }
10659
10660   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10661 };
10662
10663 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10664 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10665
10666 //===============================================================================================
10667 //function : VManipulator
10668 //purpose  :
10669 //===============================================================================================
10670 static int VManipulator (Draw_Interpretor& theDi,
10671                          Standard_Integer  theArgsNb,
10672                          const char**      theArgVec)
10673 {
10674   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10675   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10676   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
10677   if (aView.IsNull()
10678    || aViewer.IsNull())
10679   {
10680     std::cerr << "No active viewer!\n";
10681     return 1;
10682   }
10683
10684   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
10685   Standard_Integer anArgIter = 1;
10686   for (; anArgIter < theArgsNb; ++anArgIter)
10687   {
10688     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
10689   }
10690
10691   ViewerTest_CmdParser aCmd;
10692   aCmd.AddDescription ("Manages manipulator for interactive objects:");
10693   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
10694   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
10695   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
10696   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
10697   aCmd.AddOption ("detach",         "...       - detach manipulator");
10698
10699   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
10700   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
10701   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
10702
10703   aCmd.AddOption ("move",   "... x y z - move object");
10704   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
10705   aCmd.AddOption ("scale",  "... factor - scale object");
10706
10707   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
10708   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
10709   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
10710   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
10711   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
10712   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
10713   aCmd.AddOption ("size",              "... size - set size of manipulator");
10714   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
10715
10716   aCmd.Parse (theArgsNb, theArgVec);
10717
10718   if (aCmd.HasOption ("help"))
10719   {
10720     theDi.PrintHelp (theArgVec[0]);
10721     return 0;
10722   }
10723
10724   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
10725
10726   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
10727
10728   if (aName.IsEmpty())
10729   {
10730     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
10731     return 1;
10732   }
10733
10734   // ----------------------------------
10735   // detach existing manipulator object
10736   // ----------------------------------
10737
10738   if (aCmd.HasOption ("detach"))
10739   {
10740     if (!aMapAIS.IsBound2 (aName))
10741     {
10742       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
10743       return 1;
10744     }
10745
10746     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10747     if (aManipulator.IsNull())
10748     {
10749       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10750       return 1;
10751     }
10752
10753     aManipulator->Detach();
10754     aMapAIS.UnBind2 (aName);
10755     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
10756
10757     return 0;
10758   }
10759
10760   // -----------------------------------------------
10761   // find or create manipulator if it does not exist
10762   // -----------------------------------------------
10763
10764   Handle(AIS_Manipulator) aManipulator;
10765   if (!aMapAIS.IsBound2 (aName))
10766   {
10767     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
10768
10769     aManipulator = new ViewerTest_AISManipulator();
10770     aMapAIS.Bind (aManipulator, aName);
10771   }
10772   else
10773   {
10774     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10775     if (aManipulator.IsNull())
10776     {
10777       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10778       return 1;
10779     }
10780   }
10781
10782   // -----------------------------------------
10783   // change properties of manipulator instance
10784   // -----------------------------------------
10785
10786   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
10787   {
10788     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
10789   }
10790   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
10791   {
10792     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
10793   }
10794   if (aCmd.HasOption ("followRotation", 1, Standard_True))
10795   {
10796     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
10797   }
10798   if (aCmd.HasOption ("gap", 1, Standard_True))
10799   {
10800     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
10801   }
10802   if (aCmd.HasOption ("part", 3, Standard_True))
10803   {
10804     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
10805     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
10806     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
10807     if (aMode < 1 || aMode > 3)
10808     {
10809       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
10810       return 1;
10811     }
10812
10813     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
10814   }
10815   if (aCmd.HasOption ("pos", 3, Standard_True))
10816   {
10817     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
10818     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
10819     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
10820
10821     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
10822   }
10823   if (aCmd.HasOption ("size", 1, Standard_True))
10824   {
10825     aManipulator->SetSize (aCmd.ArgFloat ("size"));
10826   }
10827   if (aCmd.HasOption ("zoomable", 1, Standard_True))
10828   {
10829     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
10830
10831     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
10832     {
10833       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
10834       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
10835     }
10836   }
10837
10838   // ---------------------------------------------------
10839   // attach, detach or access manipulator from an object
10840   // ---------------------------------------------------
10841
10842   if (aCmd.HasOption ("attach"))
10843   {
10844     // Find an object and attach manipulator to it
10845     if (!aCmd.HasOption ("attach", 1, Standard_True))
10846     {
10847       return 1;
10848     }
10849
10850     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
10851     if (!aMapAIS.IsBound2 (anObjName))
10852     {
10853       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
10854       return 1;
10855     }
10856
10857     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
10858     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
10859     for (; anIt.More(); anIt.Next())
10860     {
10861       if (anIt.Value()->IsAttached()
10862        && anIt.Value()->Object() == anObject)
10863       {
10864         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
10865         return 1;
10866       }
10867     }
10868
10869     AIS_Manipulator::OptionsForAttach anOptions;
10870     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
10871     {
10872       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
10873     }
10874     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
10875     {
10876       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
10877     }
10878     if (aCmd.HasOption ("enableModes", 1, Standard_True))
10879     {
10880       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
10881     }
10882
10883     aManipulator->Attach (anObject, anOptions);
10884   }
10885
10886   // --------------------------------------
10887   // apply transformation using manipulator
10888   // --------------------------------------
10889
10890   if (aCmd.HasOption ("startTransform", 2, Standard_True))
10891   {
10892     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
10893   }
10894   if (aCmd.HasOption ("transform", 2, Standard_True))
10895   {
10896     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
10897   }
10898   if (aCmd.HasOption ("stopTransform"))
10899   {
10900     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
10901
10902     aManipulator->StopTransform (toApply);
10903   }
10904
10905   gp_Trsf aT;
10906   if (aCmd.HasOption ("move", 3, Standard_True))
10907   {
10908     aT.SetTranslationPart (aCmd.ArgVec ("move"));
10909   }
10910   if (aCmd.HasOption ("rotate", 7, Standard_True))
10911   {
10912     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
10913   }
10914   if (aCmd.HasOption ("scale", 1))
10915   {
10916     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
10917   }
10918
10919   if (aT.Form() != gp_Identity)
10920   {
10921     aManipulator->Transform (aT);
10922   }
10923
10924   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
10925
10926   return 0;
10927 }
10928
10929 //===============================================================================================
10930 //function : VSelectionProperties
10931 //purpose  :
10932 //===============================================================================================
10933 static int VSelectionProperties (Draw_Interpretor& theDi,
10934                                  Standard_Integer  theArgsNb,
10935                                  const char**      theArgVec)
10936 {
10937   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10938   if (aCtx.IsNull())
10939   {
10940     std::cerr << "No active viewer!\n";
10941     return 1;
10942   }
10943
10944   Standard_Boolean toPrint  = theArgsNb == 1;
10945   Standard_Boolean toRedraw = Standard_False;
10946   Standard_Integer anArgIter = 1;
10947   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
10948   if (anArgIter < theArgsNb)
10949   {
10950     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
10951     anArgFirst.LowerCase();
10952     ++anArgIter;
10953     if (anArgFirst == "dynhighlight"
10954      || anArgFirst == "dynhilight"
10955      || anArgFirst == "dynamichighlight"
10956      || anArgFirst == "dynamichilight")
10957     {
10958       aType = Prs3d_TypeOfHighlight_Dynamic;
10959     }
10960     else if (anArgFirst == "localdynhighlight"
10961           || anArgFirst == "localdynhilight"
10962           || anArgFirst == "localdynamichighlight"
10963           || anArgFirst == "localdynamichilight")
10964     {
10965       aType = Prs3d_TypeOfHighlight_LocalDynamic;
10966     }
10967     else if (anArgFirst == "selhighlight"
10968           || anArgFirst == "selhilight"
10969           || anArgFirst == "selectedhighlight"
10970           || anArgFirst == "selectedhilight")
10971     {
10972       aType = Prs3d_TypeOfHighlight_Selected;
10973     }
10974     else if (anArgFirst == "localselhighlight"
10975           || anArgFirst == "localselhilight"
10976           || anArgFirst == "localselectedhighlight"
10977           || anArgFirst == "localselectedhilight")
10978     {
10979       aType = Prs3d_TypeOfHighlight_LocalSelected;
10980     }
10981     else
10982     {
10983       --anArgIter;
10984     }
10985   }
10986   for (; anArgIter < theArgsNb; ++anArgIter)
10987   {
10988     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10989     anArg.LowerCase();
10990     if (anArg == "-help")
10991     {
10992       theDi.PrintHelp (theArgVec[0]);
10993       return 0;
10994     }
10995     else if (anArg == "-print")
10996     {
10997       toPrint = Standard_True;
10998     }
10999     else if (anArg == "-autoactivate")
11000     {
11001       Standard_Boolean toEnable = Standard_True;
11002       if (anArgIter + 1 < theArgsNb
11003        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11004       {
11005         ++anArgIter;
11006       }
11007       aCtx->SetAutoActivateSelection (toEnable);
11008     }
11009     else if (anArg == "-pickstrategy"
11010           || anArg == "-pickingstrategy")
11011     {
11012       if (++anArgIter >= theArgsNb)
11013       {
11014         std::cout << "Syntax error: type of highlighting is undefined\n";
11015         return 1;
11016       }
11017
11018       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11019       TCollection_AsciiString aVal (theArgVec[anArgIter]);
11020       aVal.LowerCase();
11021       if (aVal == "first"
11022        || aVal == "firstaccepted"
11023        || aVal == "firstacceptable")
11024       {
11025         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11026       }
11027       else if (aVal == "topmost"
11028             || aVal == "onlyTopmost")
11029       {
11030         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
11031       }
11032       else
11033       {
11034         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
11035         return 1;
11036       }
11037
11038       aCtx->SetPickingStrategy (aStrategy);
11039     }
11040     else if (anArg == "-pixtol"
11041           && anArgIter + 1 < theArgsNb)
11042     {
11043       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
11044     }
11045     else if ((anArg == "-mode"
11046            || anArg == "-dispmode")
11047           && anArgIter + 1 < theArgsNb)
11048     {
11049       if (aType == Prs3d_TypeOfHighlight_None)
11050       {
11051         std::cout << "Syntax error: type of highlighting is undefined\n";
11052         return 1;
11053       }
11054
11055       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
11056       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11057       aStyle->SetDisplayMode (aDispMode);
11058       toRedraw = Standard_True;
11059     }
11060     else if (anArg == "-layer"
11061           && anArgIter + 1 < theArgsNb)
11062     {
11063       if (aType == Prs3d_TypeOfHighlight_None)
11064       {
11065         std::cout << "Syntax error: type of highlighting is undefined\n";
11066         return 1;
11067       }
11068
11069       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
11070       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
11071       {
11072         TColStd_SequenceOfInteger aLayers;
11073         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
11074         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
11075         {
11076           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
11077           return 1;
11078         }
11079       }
11080
11081       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11082       aStyle->SetZLayer (aNewLayer);
11083       toRedraw = Standard_True;
11084     }
11085     else if (anArg == "-hicolor"
11086           || anArg == "-selcolor"
11087           || anArg == "-color")
11088     {
11089       if (anArg.StartsWith ("-hi"))
11090       {
11091         aType = Prs3d_TypeOfHighlight_Dynamic;
11092       }
11093       else if (anArg.StartsWith ("-sel"))
11094       {
11095         aType = Prs3d_TypeOfHighlight_Selected;
11096       }
11097       else if (aType == Prs3d_TypeOfHighlight_None)
11098       {
11099         std::cout << "Syntax error: type of highlighting is undefined\n";
11100         return 1;
11101       }
11102
11103       Quantity_Color aColor;
11104       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
11105                                                            theArgVec + anArgIter + 1,
11106                                                            aColor);
11107       if (aNbParsed == 0)
11108       {
11109         std::cout << "Syntax error: need more arguments.\n";
11110         return 1;
11111       }
11112       anArgIter += aNbParsed;
11113
11114       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11115       aStyle->SetColor (aColor);
11116       toRedraw = Standard_True;
11117     }
11118     else if ((anArg == "-transp"
11119            || anArg == "-transparency"
11120            || anArg == "-hitransp"
11121            || anArg == "-seltransp"
11122            || anArg == "-hitransplocal"
11123            || anArg == "-seltransplocal")
11124           && anArgIter + 1 < theArgsNb)
11125     {
11126       if (anArg.StartsWith ("-hi"))
11127       {
11128         aType = Prs3d_TypeOfHighlight_Dynamic;
11129       }
11130       else if (anArg.StartsWith ("-sel"))
11131       {
11132         aType = Prs3d_TypeOfHighlight_Selected;
11133       }
11134       else if (aType == Prs3d_TypeOfHighlight_None)
11135       {
11136         std::cout << "Syntax error: type of highlighting is undefined\n";
11137         return 1;
11138       }
11139
11140       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
11141       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11142       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
11143       toRedraw = Standard_True;
11144     }
11145     else if ((anArg == "-mat"
11146            || anArg == "-material")
11147           && anArgIter + 1 < theArgsNb)
11148     {
11149       if (aType == Prs3d_TypeOfHighlight_None)
11150       {
11151         std::cout << "Syntax error: type of highlighting is undefined\n";
11152         return 1;
11153       }
11154
11155       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11156       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
11157       if (aMatName != Graphic3d_NOM_DEFAULT)
11158       {
11159         ++anArgIter;
11160         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
11161         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
11162         Graphic3d_MaterialAspect aMat (aMatName);
11163         aMat.SetColor (aStyle->Color());
11164         aMat.SetTransparency (aStyle->Transparency());
11165         anAspect->SetFrontMaterial (aMat);
11166         anAspect->SetInteriorColor (aStyle->Color());
11167         aStyle->SetBasicFillAreaAspect (anAspect);
11168       }
11169       else
11170       {
11171         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
11172       }
11173       toRedraw = Standard_True;
11174     }
11175     else
11176     {
11177       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
11178     }
11179   }
11180
11181   if (toPrint)
11182   {
11183     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
11184     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
11185     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
11186     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
11187     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
11188     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
11189     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
11190     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
11191     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
11192     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
11193     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
11194     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
11195   }
11196
11197   if (aCtx->NbSelected() != 0 && toRedraw)
11198   {
11199     aCtx->HilightSelected (Standard_True);
11200   }
11201
11202   return 0;
11203 }
11204
11205 //===============================================================================================
11206 //function : VDumpSelectionImage
11207 //purpose  :
11208 //===============================================================================================
11209 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
11210                                 Standard_Integer  theArgsNb,
11211                                 const char**      theArgVec)
11212 {
11213   if (theArgsNb < 2)
11214   {
11215     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
11216     return 1;
11217   }
11218
11219   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
11220   if (aContext.IsNull())
11221   {
11222     std::cout << "Error: no active view.\n";
11223     return 1;
11224   }
11225
11226   TCollection_AsciiString aFile;
11227   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11228   Image_Format anImgFormat = Image_Format_BGR;
11229   Standard_Integer aPickedIndex = 1;
11230   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
11231   {
11232     TCollection_AsciiString aParam (theArgVec[anArgIter]);
11233     aParam.LowerCase();
11234     if (aParam == "-type")
11235     {
11236       if (++anArgIter >= theArgsNb)
11237       {
11238         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
11239         return 1;
11240       }
11241
11242       TCollection_AsciiString aValue (theArgVec[anArgIter]);
11243       aValue.LowerCase();
11244       if (aValue == "depth"
11245        || aValue == "normdepth"
11246        || aValue == "normalizeddepth")
11247       {
11248         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11249         anImgFormat = Image_Format_GrayF;
11250       }
11251       if (aValue == "depthinverted"
11252        || aValue == "normdepthinverted"
11253        || aValue == "normalizeddepthinverted"
11254        || aValue == "inverted")
11255       {
11256         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
11257         anImgFormat = Image_Format_GrayF;
11258       }
11259       else if (aValue == "unnormdepth"
11260             || aValue == "unnormalizeddepth")
11261       {
11262         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
11263         anImgFormat = Image_Format_GrayF;
11264       }
11265       else if (aValue == "objectcolor"
11266             || aValue == "object"
11267             || aValue == "color")
11268       {
11269         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
11270       }
11271       else if (aValue == "entitycolor"
11272             || aValue == "entity")
11273       {
11274         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
11275       }
11276       else if (aValue == "ownercolor"
11277             || aValue == "owner")
11278       {
11279         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
11280       }
11281       else if (aValue == "selectionmodecolor"
11282             || aValue == "selectionmode"
11283             || aValue == "selmodecolor"
11284             || aValue == "selmode")
11285       {
11286         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
11287       }
11288     }
11289     else if (aParam == "-picked"
11290           || aParam == "-pickeddepth"
11291           || aParam == "-pickedindex")
11292     {
11293       if (++anArgIter >= theArgsNb)
11294       {
11295         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
11296         return 1;
11297       }
11298
11299       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
11300     }
11301     else if (aFile.IsEmpty())
11302     {
11303       aFile = theArgVec[anArgIter];
11304     }
11305     else
11306     {
11307       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
11308       return 1;
11309     }
11310   }
11311   if (aFile.IsEmpty())
11312   {
11313     std::cout << "Syntax error: image file name is missing.\n";
11314     return 1;
11315   }
11316
11317   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
11318   Standard_Integer aWidth = 0, aHeight = 0;
11319   aView->Window()->Size (aWidth, aHeight);
11320
11321   Image_AlienPixMap aPixMap;
11322   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
11323   {
11324     std::cout << "Error: can't allocate image.\n";
11325     return 1;
11326   }
11327   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
11328   {
11329     std::cout << "Error: can't generate selection image.\n";
11330     return 1;
11331   }
11332   if (!aPixMap.Save (aFile))
11333   {
11334     std::cout << "Error: can't save selection image.\n";
11335     return 0;
11336   }
11337   return 0;
11338 }
11339
11340 //=======================================================================
11341 //function : ViewerCommands
11342 //purpose  :
11343 //=======================================================================
11344
11345 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
11346 {
11347
11348   const char *group = "ZeViewer";
11349   theCommands.Add("vinit",
11350           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
11351     "\n\t\t:     [-exitOnClose] [-closeOnEscape]"
11352   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11353     "\n\t\t:     [-display displayName]"
11354   #endif
11355     "\n\t\t: Creates new View window with specified name viewName."
11356     "\n\t\t: By default the new view is created in the viewer and in"
11357     "\n\t\t: graphic driver shared with active view."
11358     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
11359     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
11360     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
11361 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11362     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
11363     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
11364 #endif
11365     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
11366     "\n\t\t:  -width, -height width and heigth of window respectively."
11367     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
11368     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
11369     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
11370     __FILE__,VInit,group);
11371   theCommands.Add("vclose" ,
11372     "[view_id [keep_context=0|1]]\n"
11373     "or vclose ALL - to remove all created views\n"
11374     " - removes view(viewer window) defined by its view_id.\n"
11375     " - keep_context: by default 0; if 1 and the last view is deleted"
11376     " the current context is not removed.",
11377     __FILE__,VClose,group);
11378   theCommands.Add("vactivate" ,
11379     "view_id"
11380     " - activates view(viewer window) defined by its view_id",
11381     __FILE__,VActivate,group);
11382   theCommands.Add("vviewlist",
11383     "vviewlist [format={tree, long}]"
11384     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
11385     " - format: format of result output, if tree the output is a tree view;"
11386     "otherwise it's a list of full view names. By default format = tree",
11387     __FILE__,VViewList,group);
11388   theCommands.Add("vhelp" ,
11389     "vhelp            : display help on the viewer commands",
11390     __FILE__,VHelp,group);
11391   theCommands.Add("vtop" ,
11392     "vtop or <T>      : Top view. Orientation +X+Y" ,
11393     __FILE__,VTop,group);
11394   theCommands.Add("vbottom" ,
11395     "vbottom          : Bottom view. Orientation +X-Y" ,
11396     __FILE__,VBottom,group);
11397   theCommands.Add("vleft" ,
11398     "vleft            : Left view. Orientation -Y+Z" ,
11399     __FILE__,VLeft,group);
11400   theCommands.Add("vright" ,
11401     "vright           : Right view. Orientation +Y+Z" ,
11402     __FILE__,VRight,group);
11403   theCommands.Add("vaxo" ,
11404     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
11405     __FILE__,VAxo,group);
11406   theCommands.Add("vfront" ,
11407     "vfront           : Front view. Orientation +X+Z" ,
11408     __FILE__,VFront,group);
11409   theCommands.Add("vback" ,
11410     "vback            : Back view. Orientation -X+Z" ,
11411     __FILE__,VBack,group);
11412   theCommands.Add("vpick" ,
11413     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
11414     VPick,group);
11415   theCommands.Add("vfit",
11416     "vfit or <F> [-selected] [-noupdate]"
11417     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
11418     __FILE__,VFit,group);
11419   theCommands.Add ("vfitarea",
11420     "vfitarea x1 y1 x2 y2"
11421     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
11422     "\n\t\t: Fit view to show area located between two points"
11423     "\n\t\t: given in world 2D or 3D corrdinates.",
11424     __FILE__, VFitArea, group);
11425   theCommands.Add ("vzfit", "vzfit [scale]\n"
11426     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
11427     "   \"scale\" - specifies factor to scale computed z range.\n",
11428     __FILE__, VZFit, group);
11429   theCommands.Add("vrepaint",
11430             "vrepaint [-immediate]"
11431     "\n\t\t: force redraw",
11432     __FILE__,VRepaint,group);
11433   theCommands.Add("vclear",
11434     "vclear          : vclear"
11435     "\n\t\t: remove all the object from the viewer",
11436     __FILE__,VClear,group);
11437   theCommands.Add("vsetbg",
11438     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
11439     __FILE__,VSetBg,group);
11440   theCommands.Add("vsetbgmode",
11441     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
11442     __FILE__,VSetBgMode,group);
11443   theCommands.Add("vsetgradientbg",
11444     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
11445     __FILE__,VSetGradientBg,group);
11446   theCommands.Add("vsetgrbgmode",
11447     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
11448     __FILE__,VSetGradientBgMode,group);
11449   theCommands.Add("vsetcolorbg",
11450     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
11451     __FILE__,VSetColorBg,group);
11452   theCommands.Add("vsetdefaultbg",
11453     "vsetdefaultbg r g b\n"
11454     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
11455     "\n\t\t: Set default viewer background fill color (flat/gradient).",
11456     __FILE__,VSetDefaultBg,group);
11457   theCommands.Add("vscale",
11458     "vscale          : vscale X Y Z",
11459     __FILE__,VScale,group);
11460   theCommands.Add("vzbufftrihedron",
11461             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
11462     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
11463     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
11464     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
11465     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
11466     "\n\t\t: Displays a trihedron",
11467     __FILE__,VZBuffTrihedron,group);
11468   theCommands.Add("vrotate",
11469     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
11470     "\n                : Option -mouseStart starts rotation according to the mouse position"
11471     "\n                : Option -mouseMove continues rotation with angle computed"
11472     "\n                : from last and new mouse position."
11473     "\n                : vrotate AX AY AZ [X Y Z]",
11474     __FILE__,VRotate,group);
11475   theCommands.Add("vzoom",
11476     "vzoom           : vzoom coef",
11477     __FILE__,VZoom,group);
11478   theCommands.Add("vpan",
11479     "vpan            : vpan dx dy",
11480     __FILE__,VPan,group);
11481   theCommands.Add("vexport",
11482     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
11483     " : exports the view to a vector file of a given format"
11484     " : notice that EMF format requires patched gl2ps",
11485     __FILE__,VExport,group);
11486   theCommands.Add("vcolorscale",
11487     "vcolorscale name [-noupdate|-update] [-demo]"
11488     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
11489     "\n\t\t:       [-font HeightFont=20]"
11490     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
11491     "\n\t\t:       [-smoothTransition {on|off}=off]"
11492     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
11493     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
11494     "\n\t\t:       [-textpos {left|right|center|none}=right]"
11495     "\n\t\t:       [-labelAtBorder {on|off}=on]"
11496     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
11497     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
11498     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
11499     "\n\t\t:       [-xy Left=0 Bottom=0]"
11500     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
11501     "\n\t\t:  -colors   - set colors for all intervals"
11502     "\n\t\t:  -color    - set color for specific interval"
11503     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
11504     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
11505     "\n\t\t:              at border means the value inbetween neighbor intervals,"
11506     "\n\t\t:              at center means the center value within current interval"
11507     "\n\t\t:  -labels   - set labels for all intervals"
11508     "\n\t\t:  -freeLabels - same as -labels but does not require"
11509     "\n\t\t:              matching the number of intervals"
11510     "\n\t\t:  -label    - set label for specific interval"
11511     "\n\t\t:  -title    - set title"
11512     "\n\t\t:  -reversed - setup smooth color transition between intervals"
11513     "\n\t\t:  -smoothTransition - swap colorscale direction"
11514     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
11515     __FILE__, VColorScale, group);
11516   theCommands.Add("vgraduatedtrihedron",
11517     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
11518     "\t[-namefont Name] [-valuesfont Name]\n"
11519     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
11520     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
11521     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
11522     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
11523     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
11524     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
11525     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
11526     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
11527     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
11528     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
11529     " - Displays or erases graduated trihedron"
11530     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
11531     " - namefont - font of axes names. Default: Arial\n"
11532     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
11533     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
11534     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
11535     " - valuesfont - font of axes values. Default: Arial\n"
11536     " - xcolor, ycolor, zcolor - color of axis and values\n"
11537     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
11538     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
11539     __FILE__,VGraduatedTrihedron,group);
11540   theCommands.Add("vtile" ,
11541             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
11542     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
11543     "\n\t\t:  -totalSize the size of virtual bigger viewport"
11544     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
11545     "\n\t\t:  -lowerLeft tile offset as lower left corner"
11546     "\n\t\t:  -upperLeft tile offset as upper left corner",
11547     __FILE__, VTile, group);
11548   theCommands.Add("vzlayer",
11549               "vzlayer [layerId]"
11550       "\n\t\t:         [-add|-delete|-get|-settings]"
11551       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
11552       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
11553       "\n\t\t: ZLayer list management:"
11554       "\n\t\t:   -add      add new z layer to viewer and print its id"
11555       "\n\t\t:   -delete   delete z layer"
11556       "\n\t\t:   -get      print sequence of z layers"
11557       "\n\t\t:   -settings print status of z layer settings"
11558       "\n\t\t:   -disable  disables given setting"
11559       "\n\t\t:   -enable   enables  given setting",
11560     __FILE__,VZLayer,group);
11561   theCommands.Add("vlayerline",
11562     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
11563     __FILE__,VLayerLine,group);
11564   theCommands.Add ("vgrid",
11565     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
11566     " : Mode - rectangular or circular"
11567     " : Type - lines or points",
11568     __FILE__, VGrid, group);
11569   theCommands.Add ("vpriviledgedplane",
11570     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
11571     "\n\t\t:   Ox, Oy, Oz - plane origin"
11572     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
11573     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
11574     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
11575     __FILE__, VPriviledgedPlane, group);
11576   theCommands.Add ("vconvert",
11577     "vconvert v [Mode={window|view}]"
11578     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
11579     "\n\t\t: vconvert x y z [Mode={window|grid}]"
11580     "\n\t\t:   window - convert to window coordinates, pixels"
11581     "\n\t\t:   view   - convert to view projection plane"
11582     "\n\t\t:   grid   - convert to model coordinates, given on grid"
11583     "\n\t\t:   ray    - convert projection ray to model coordiantes"
11584     "\n\t\t: - vconvert v window : convert view to window;"
11585     "\n\t\t: - vconvert v view   : convert window to view;"
11586     "\n\t\t: - vconvert x y window : convert view to window;"
11587     "\n\t\t: - vconvert x y view : convert window to view;"
11588     "\n\t\t: - vconvert x y : convert window to model;"
11589     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
11590     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
11591     "\n\t\t: - vconvert x y z window : convert model to window;"
11592     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
11593     "\n\t\t: Converts the given coordinates to window/view/model space.",
11594     __FILE__, VConvert, group);
11595   theCommands.Add ("vfps",
11596     "vfps [framesNb=100] : estimate average frame rate for active view",
11597     __FILE__, VFps, group);
11598   theCommands.Add ("vgldebug",
11599             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
11600     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
11601     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
11602     "\n\t\t: Debug context can be requested only on Windows"
11603     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
11604     "\n\t\t:  -sync     - request synchronized debug GL context"
11605     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
11606     "\n\t\t:              which are suppressed by default,"
11607     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
11608     "\n\t\t:              which are suppressed by default",
11609     __FILE__, VGlDebug, group);
11610   theCommands.Add ("vvbo",
11611     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
11612     __FILE__, VVbo, group);
11613   theCommands.Add ("vstereo",
11614             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
11615     "\n\t\t:         [-anaglyph Filter]"
11616     "\n\t\t: Control stereo output mode. Available modes for -mode:"
11617     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
11618     "\n\t\t:                     requires driver support."
11619     "\n\t\t:                     Should be called BEFORE vinit!"
11620     "\n\t\t:  anaglyph         - Anaglyph glasses"
11621     "\n\t\t:  rowInterlaced    - row-interlaced display"
11622     "\n\t\t:  columnInterlaced - column-interlaced display"
11623     "\n\t\t:  chessBoard       - chess-board output"
11624     "\n\t\t:  sideBySide       - horizontal pair"
11625     "\n\t\t:  overUnder        - vertical   pair"
11626     "\n\t\t: Available Anaglyph filters for -anaglyph:"
11627     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
11628     "\n\t\t:  greenMagentaSimple",
11629     __FILE__, VStereo, group);
11630   theCommands.Add ("vcaps",
11631             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
11632     "\n\t\t:       [-compatibleProfile {0|1}]"
11633     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
11634     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
11635     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
11636     "\n\t\t: Modify particular graphic driver options:"
11637     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
11638     "\n\t\t:             built-in GLSL programs"
11639     "\n\t\t:            (requires compatible profile)"
11640     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
11641     "\n\t\t:             arrays to GPU memory)"
11642     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
11643     "\n\t\t:  vsync    - switch VSync on or off"
11644     "\n\t\t:  winBuffer - allow using window buffer for rendering"
11645     "\n\t\t: Context creation options:"
11646     "\n\t\t:  softMode          - software OpenGL implementation"
11647     "\n\t\t:  compatibleProfile - backward-compatible profile"
11648     "\n\t\t:  quadbuffer        - QuadBuffer"
11649     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
11650     "\n\t\t: rendering paths producing the same visual result when"
11651     "\n\t\t: possible."
11652     "\n\t\t: Command is intended for testing old hardware compatibility.",
11653     __FILE__, VCaps, group);
11654   theCommands.Add ("vmemgpu",
11655     "vmemgpu [f]: print system-dependent GPU memory information if available;"
11656     " with f option returns free memory in bytes",
11657     __FILE__, VMemGpu, group);
11658   theCommands.Add ("vreadpixel",
11659     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
11660     " : Read pixel value for active view",
11661     __FILE__, VReadPixel, group);
11662   theCommands.Add("diffimage",
11663             "diffimage imageFile1 imageFile2 [diffImageFile]"
11664     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
11665     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
11666     "\n\t\t: Compare two images by content and generate difference image."
11667     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
11668     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
11669     __FILE__, VDiffImage, group);
11670   theCommands.Add ("vselect",
11671     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
11672     "- emulates different types of selection:\n"
11673     "- 1) single click selection\n"
11674     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
11675     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
11676     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
11677     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
11678     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
11679     " (partial inclusion - overlap - is not allowed by default)\n"
11680     "- 5) any of these selections with shift button pressed",
11681     __FILE__, VSelect, group);
11682   theCommands.Add ("vmoveto",
11683     "vmoveto x y"
11684     "- emulates cursor movement to pixel postion (x,y)",
11685     __FILE__, VMoveTo, group);
11686   theCommands.Add ("vviewparams",
11687               "vviewparams [-args] [-scale [s]]"
11688       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
11689       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
11690       "\n\t\t: Manage current view parameters or prints all"
11691       "\n\t\t: current values when called without argument."
11692       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
11693       "\n\t\t:   -eye  [x y z] prints or sets eye location"
11694       "\n\t\t:   -at   [x y z] prints or sets center of look"
11695       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
11696       "\n\t\t:   -proj [x y z] prints or sets direction of look"
11697       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
11698       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
11699       "\n\t\t:                 or changes the size of its maximum dimension"
11700       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
11701     __FILE__, VViewParams, group);
11702
11703   theCommands.Add("vanimation", "Alias for vanim",
11704     __FILE__, VAnimation, group);
11705
11706   theCommands.Add("vanim",
11707             "List existing animations:"
11708     "\n\t\t:  vanim"
11709     "\n\t\t: Animation playback:"
11710     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
11711     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
11712     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
11713     "\n\t\t:   -freeLook skip camera animations"
11714     "\n\t\t:   -lockLoop disable any interactions"
11715     "\n\t\t:"
11716     "\n\t\t: Animation definition:"
11717     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
11718     "\n\t\t:        [start TimeSec] [duration TimeSec]"
11719     "\n\t\t:"
11720     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
11721     "\n\t\t: specifies nested animations."
11722     "\n\t\t: There is no syntax to explicitly add new animation,"
11723     "\n\t\t: and all non-existing animations within the name will be"
11724     "\n\t\t: implicitly created on first use (including parents)."
11725     "\n\t\t:"
11726     "\n\t\t: Each animation might define the SINGLE action (see below),"
11727     "\n\t\t: like camera transition, object transformation or custom callback."
11728     "\n\t\t: Child animations can be used for defining concurrent actions."
11729     "\n\t\t:"
11730     "\n\t\t: Camera animation:"
11731     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
11732     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
11733     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
11734     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
11735     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
11736     "\n\t\t:   -atX    camera Center positions pair"
11737     "\n\t\t:   -upX    camera Up directions pair"
11738     "\n\t\t:   -scaleX camera Scale factors pair"
11739     "\n\t\t: Object animation:"
11740     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
11741     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
11742     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
11743     "\n\t\t:   -locX   object Location points pair (translation)"
11744     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
11745     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
11746     "\n\t\t: Custom callback:"
11747     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
11748     "\n\t\t:   %Pts        overall animation presentation timestamp"
11749     "\n\t\t:   %LocalPts   local animation timestamp"
11750     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
11751     "\n\t\t:"
11752     "\n\t\t: Video recording:"
11753     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
11754     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
11755     "\n\t\t:             [-crf Value] [-preset Preset]"
11756     "\n\t\t:   -fps     video framerate"
11757     "\n\t\t:   -format  file format, container (matroska, etc.)"
11758     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
11759     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
11760     "\n\t\t:   -crf     constant rate factor (specific to codec)"
11761     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
11762     __FILE__, VAnimation, group);
11763
11764   theCommands.Add("vchangeselected",
11765     "vchangeselected shape"
11766     "- adds to shape to selection or remove one from it",
11767                 __FILE__, VChangeSelected, group);
11768   theCommands.Add ("vnbselected",
11769     "vnbselected"
11770     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
11771   theCommands.Add ("vcamera",
11772               "vcamera [-ortho] [-projtype]"
11773       "\n\t\t:         [-persp]"
11774       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
11775       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
11776       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
11777       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
11778       "\n\t\t: Manage camera parameters."
11779       "\n\t\t: Prints current value when option called without argument."
11780       "\n\t\t: Orthographic camera:"
11781       "\n\t\t:   -ortho      activate orthographic projection"
11782       "\n\t\t: Perspective camera:"
11783       "\n\t\t:   -persp      activate perspective  projection (mono)"
11784       "\n\t\t:   -fovy       field of view in y axis, in degrees"
11785       "\n\t\t:   -distance   distance of eye from camera center"
11786       "\n\t\t: Stereoscopic camera:"
11787       "\n\t\t:   -stereo     perspective  projection (stereo)"
11788       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
11789       "\n\t\t:   -rightEye   perspective  projection (right eye)"
11790       "\n\t\t:   -iod        intraocular distance value"
11791       "\n\t\t:   -iodType    distance type, absolute or relative"
11792       "\n\t\t:   -zfocus     stereographic focus value"
11793       "\n\t\t:   -zfocusType focus type, absolute or relative",
11794     __FILE__, VCamera, group);
11795   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
11796     "- vautozfit [on={1|0}] [scale]\n"
11797     "    Prints or changes parameters of automatic z-fit mode:\n"
11798     "   \"on\" - turns automatic z-fit on or off\n"
11799     "   \"scale\" - specifies factor to scale computed z range.\n",
11800     __FILE__, VAutoZFit, group);
11801   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
11802     "   vzrange                - without parameters shows current values\n"
11803     "   vzrange [znear] [zfar] - applies provided values to view",
11804     __FILE__,VZRange, group);
11805   theCommands.Add ("vpurgedisplay",
11806     "vpurgedisplay"
11807     "- removes structures which don't belong to objects displayed in neutral point",
11808     __FILE__, VPurgeDisplay, group);
11809   theCommands.Add("vsetviewsize",
11810     "vsetviewsize size",
11811     __FILE__,VSetViewSize,group);
11812   theCommands.Add("vmoveview",
11813     "vmoveview Dx Dy Dz [Start = 1|0]",
11814     __FILE__,VMoveView,group);
11815   theCommands.Add("vtranslateview",
11816     "vtranslateview Dx Dy Dz [Start = 1|0)]",
11817     __FILE__,VTranslateView,group);
11818   theCommands.Add("vturnview",
11819     "vturnview Ax Ay Az [Start = 1|0]",
11820     __FILE__,VTurnView,group);
11821   theCommands.Add("vtextureenv",
11822     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
11823     "or user-defined file and optionally applying texture mapping parameters\n"
11824     "                  Usage:\n"
11825     "                  vtextureenv off - disables environment mapping\n"
11826     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
11827     "                              std_texture = (0..7)\n"
11828     "                              rep         = {clamp|repeat}\n"
11829     "                              mod         = {decal|modulate}\n"
11830     "                              flt         = {nearest|bilinear|trilinear}\n"
11831     "                              ss, st      - scale factors for s and t texture coordinates\n"
11832     "                              ts, tt      - translation for s and t texture coordinates\n"
11833     "                              rot         - texture rotation angle in degrees",
11834     __FILE__, VTextureEnv, group);
11835   theCommands.Add("vhlr",
11836             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
11837       "\n\t\t: Hidden Line Removal algorithm."
11838       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
11839       "\n\t\t:   -algoType   type of HLR algorithm.\n",
11840     __FILE__,VHLR,group);
11841   theCommands.Add("vhlrtype",
11842               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
11843       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
11844       "\n\t\t:   'algo' - exact HLR algorithm is applied"
11845       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
11846       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
11847     __FILE__,VHLRType,group);
11848   theCommands.Add("vclipplane",
11849               "vclipplane planeName [{0|1}]"
11850       "\n\t\t:   [-equation A B C D]"
11851       "\n\t\t:   [-set|-unset [objects|views]]"
11852       "\n\t\t:   [-maxPlanes]"
11853       "\n\t\t:   [-capping {0|1}]"
11854       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
11855       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
11856       "\n\t\t:       [-texRotate Angle]"
11857       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
11858       "\n\t\t:       [-useObjShader {0|1}]"
11859       "\n\t\t: Clipping planes management:"
11860       "\n\t\t:   -maxPlanes   print plane limit for view"
11861       "\n\t\t:   -delete      delete plane with given name"
11862       "\n\t\t:   {off|on|0|1} turn clipping on/off"
11863       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
11864       "\n\t\t:                applied to active View when list is omitted"
11865       "\n\t\t:   -equation A B C D change plane equation"
11866       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
11867       "\n\t\t: Capping options:"
11868       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
11869       "\n\t\t:   -color R G B          set capping color"
11870       "\n\t\t:   -texName Texture      set capping texture"
11871       "\n\t\t:   -texScale SX SY       set capping tex scale"
11872       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
11873       "\n\t\t:   -texRotate Angle      set capping tex rotation"
11874       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
11875       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
11876       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
11877       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
11878       __FILE__, VClipPlane, group);
11879   theCommands.Add("vdefaults",
11880                "vdefaults [-absDefl value]"
11881        "\n\t\t:           [-devCoeff value]"
11882        "\n\t\t:           [-angDefl value]"
11883        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
11884     , __FILE__, VDefaults, group);
11885   theCommands.Add("vlight",
11886     "tool to manage light sources, without arguments shows list of lights."
11887     "\n    Main commands: "
11888     "\n      'clear' to clear lights"
11889     "\n      '{def}aults' to load deafault lights"
11890     "\n      'add' (or 'new') <type> to add any light source"
11891     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
11892     "\n      'change' <lightId> to edit light source with specified lightId"
11893     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
11894     "\n        {pos}ition X Y Z"
11895     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
11896     "\n        color colorName"
11897     "\n        {head}light 0|1"
11898     "\n        {sm}oothness value"
11899     "\n        {int}ensity value"
11900     "\n        {constAtten}uation value"
11901     "\n        {linearAtten}uation value"
11902     "\n        angle angleDeg"
11903     "\n        {spotexp}onent value"
11904     "\n        local|global"
11905     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
11906     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
11907     __FILE__, VLight, group);
11908   theCommands.Add("vraytrace",
11909             "vraytrace [0|1]"
11910     "\n\t\t: Turns on/off ray-tracing renderer."
11911     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
11912     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
11913     __FILE__, VRenderParams, group);
11914   theCommands.Add("vrenderparams",
11915     "\n    Manages rendering parameters: "
11916     "\n      '-raster'                   Disables GPU ray-tracing"
11917     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
11918     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
11919     "\n      '-rendScale    value        Rendering resolution scale factor"
11920     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
11921     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
11922     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
11923     "\n      '-reflections  on|off'      Enables/disables specular reflections"
11924     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
11925     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
11926     "\n      '-gi           on|off'      Enables/disables global illumination effects"
11927     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
11928     "\n      '-env          on|off'      Enables/disables environment map background"
11929     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
11930     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
11931     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
11932     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
11933     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
11934     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
11935     "\n      '-shadingModel model'       Controls shading model from enumeration"
11936     "\n                                  color, flat, gouraud, phong"
11937     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
11938     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
11939     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
11940     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
11941     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
11942     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
11943     "\n    Unlike vcaps, these parameters dramatically change visual properties."
11944     "\n    Command is intended to control presentation quality depending on"
11945     "\n    hardware capabilities and performance.",
11946     __FILE__, VRenderParams, group);
11947   theCommands.Add("vfrustumculling",
11948     "vfrustumculling [toEnable]: enables/disables objects clipping",
11949     __FILE__,VFrustumCulling,group);
11950   theCommands.Add("vhighlightselected",
11951     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
11952     "Without arguments it shows if highlighting of selected objects is enabled now.",
11953     __FILE__,VHighlightSelected,group);
11954   theCommands.Add ("vplace",
11955             "vplace dx dy"
11956     "\n\t\t: Places the point (in pixels) at the center of the window",
11957     __FILE__, VPlace, group);
11958   theCommands.Add("vxrotate",
11959     "vxrotate",
11960     __FILE__,VXRotate,group);
11961
11962     theCommands.Add("vmanipulator",
11963       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
11964       "\n    tool to create and manage AIS manipulators."
11965       "\n    Options: "
11966       "\n      '-attach AISObject'                 attach manipulator to AISObject"
11967       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
11968       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
11969       "\n      '-enableModes    {0|1}'             enable modes when attaching"
11970       "\n      '-detach'                           detach manipulator"
11971       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
11972       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
11973       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
11974       "\n      '-move x y z'                     - move attached object"
11975       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
11976       "\n      '-scale factor'                   - scale attached object"
11977       "\n      '-autoActivate      {0|1}'        - set activation on detection"
11978       "\n      '-followTranslation {0|1}'        - set following translation transform"
11979       "\n      '-followRotation    {0|1}'        - set following rotation transform"
11980       "\n      '-gap value'                      - set gap between sub-parts"
11981       "\n      '-part axis mode    {0|1}'        - set visual part"
11982       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
11983       "\n      '-size value'                     - set size of manipulator"
11984       "\n      '-zoomable {0|1}'                 - set zoom persistence",
11985     __FILE__, VManipulator, group);
11986
11987   theCommands.Add("vselprops",
11988     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
11989     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
11990     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
11991     "\n    -pickStrategy {first|topmost} : defines picking strategy"
11992     "\n                            'first'   to pick first acceptable (default)"
11993     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
11994     "\n    -pixTol    value        : sets up pixel tolerance"
11995     "\n    -dispMode  dispMode     : sets display mode for highlighting"
11996     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
11997     "\n    -color     {name|r g b} : sets highlight color"
11998     "\n    -transp    value        : sets transparency coefficient for highlight"
11999     "\n    -material  material     : sets highlight material"
12000     "\n    -print                  : prints current state of all mentioned parameters",
12001     __FILE__, VSelectionProperties, group);
12002
12003   theCommands.Add ("vseldump",
12004                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
12005                    "\n\t\t: Generate an image based on detection results:"
12006                    "\n\t\t:   depth       normalized depth values"
12007                    "\n\t\t:   unnormDepth unnormalized depth values"
12008                    "\n\t\t:   object      color of detected object"
12009                    "\n\t\t:   owner       color of detected owner"
12010                    "\n\t\t:   selMode     color of selection mode"
12011                    "\n\t\t:   entity      color of etected entity",
12012                    __FILE__, VDumpSelectionImage, group);
12013
12014 #if defined(_WIN32)
12015   theCommands.Add("vprogressive",
12016     "vprogressive",
12017     __FILE__, VProgressiveMode, group);
12018 #endif
12019 }