523c03bab2de6cb920122b65d8cdeb049a2ef04a
[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_CameraFrustum.hxx>
23 #include <AIS_ColorScale.hxx>
24 #include <AIS_Manipulator.hxx>
25 #include <AIS_RubberBand.hxx>
26 #include <AIS_Shape.hxx>
27 #include <AIS_InteractiveObject.hxx>
28 #include <AIS_ListOfInteractive.hxx>
29 #include <AIS_ListIteratorOfListOfInteractive.hxx>
30 #include <Aspect_Grid.hxx>
31 #include <DBRep.hxx>
32 #include <Draw_ProgressIndicator.hxx>
33 #include <Graphic3d_ArrayOfPolylines.hxx>
34 #include <Graphic3d_AspectMarker3d.hxx>
35 #include <Graphic3d_NameOfTextureEnv.hxx>
36 #include <Graphic3d_GraduatedTrihedron.hxx>
37 #include <Graphic3d_TextureEnv.hxx>
38 #include <Graphic3d_TextureParams.hxx>
39 #include <Graphic3d_TypeOfTextureFilter.hxx>
40 #include <Graphic3d_AspectFillArea3d.hxx>
41 #include <ViewerTest.hxx>
42 #include <ViewerTest_AutoUpdater.hxx>
43 #include <ViewerTest_EventManager.hxx>
44 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
45 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
46 #include <ViewerTest_CmdParser.hxx>
47 #include <V3d_AmbientLight.hxx>
48 #include <V3d_DirectionalLight.hxx>
49 #include <V3d_PositionalLight.hxx>
50 #include <V3d_SpotLight.hxx>
51 #include <Message_ProgressSentry.hxx>
52 #include <NCollection_DoubleMap.hxx>
53 #include <NCollection_List.hxx>
54 #include <NCollection_Vector.hxx>
55 #include <AIS_InteractiveContext.hxx>
56 #include <Draw_Interpretor.hxx>
57 #include <Draw.hxx>
58 #include <Draw_Appli.hxx>
59 #include <Image_AlienPixMap.hxx>
60 #include <Image_VideoRecorder.hxx>
61 #include <OpenGl_GraphicDriver.hxx>
62 #include <OSD.hxx>
63 #include <OSD_Timer.hxx>
64 #include <TColStd_HSequenceOfAsciiString.hxx>
65 #include <TColStd_SequenceOfInteger.hxx>
66 #include <TColStd_HSequenceOfReal.hxx>
67 #include <TColgp_Array1OfPnt2d.hxx>
68 #include <TColStd_MapOfAsciiString.hxx>
69 #include <Aspect_TypeOfLine.hxx>
70 #include <Image_Diff.hxx>
71 #include <Aspect_DisplayConnection.hxx>
72 #include <gp_Pnt.hxx>
73 #include <gp_Dir.hxx>
74 #include <gp_Pln.hxx>
75 #include <PrsMgr_PresentableObject.hxx>
76 #include <Graphic3d_ClipPlane.hxx>
77 #include <NCollection_DataMap.hxx>
78 #include <Graphic3d_Texture2Dmanual.hxx>
79 #include <Prs3d_ShadingAspect.hxx>
80 #include <Prs3d_Drawer.hxx>
81 #include <Prs3d_LineAspect.hxx>
82 #include <Prs3d_Root.hxx>
83 #include <Prs3d_Text.hxx>
84 #include <Select3D_SensitivePrimitiveArray.hxx>
85
86 #include <tcl.h>
87
88 #ifdef _WIN32
89 #undef DrawText
90 #endif
91
92 #include <cstdlib>
93
94 #if defined(_WIN32)
95   #include <WNT_WClass.hxx>
96   #include <WNT_Window.hxx>
97 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
98   #include <Cocoa_Window.hxx>
99 #else
100   #include <Xw_Window.hxx>
101   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
102   #include <X11/Xutil.h>
103   #include <tk.h>
104 #endif
105
106 // Auxiliary definitions
107 static const char THE_KEY_DELETE = 127;
108 static const char THE_KEY_ESCAPE = 27;
109
110 //==============================================================================
111 //  VIEWER GLOBAL VARIABLES
112 //==============================================================================
113
114 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
115 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
116
117 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
118 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
119
120 extern int VErase (Draw_Interpretor& theDI,
121                    Standard_Integer  theArgNb,
122                    const char**      theArgVec);
123
124 #if defined(_WIN32)
125 static Handle(WNT_Window)& VT_GetWindow() {
126   static Handle(WNT_Window) WNTWin;
127   return WNTWin;
128 }
129 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
130 static Handle(Cocoa_Window)& VT_GetWindow()
131 {
132   static Handle(Cocoa_Window) aWindow;
133   return aWindow;
134 }
135 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
136 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
137 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
138
139 #else
140 static Handle(Xw_Window)& VT_GetWindow(){
141   static Handle(Xw_Window) XWWin;
142   return XWWin;
143 }
144
145 static void VProcessEvents(ClientData,int);
146 #endif
147
148 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
149 {
150   static Handle(Aspect_DisplayConnection) aDisplayConnection;
151   return aDisplayConnection;
152 }
153
154 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
155 {
156   GetDisplayConnection() = theDisplayConnection;
157 }
158
159 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
160 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
161 {
162   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
163 #if defined(_WIN32)
164   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
165   if (!aWindow.IsNull())
166     return aWindow->HWindow();
167 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
168   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
169   if (!aWindow.IsNull())
170   return aWindow->XWindow();
171 #endif
172   return aWindowHandle;
173 }
174 #endif
175
176 //! Setting additional flag to store 2D mode of the View to avoid scene rotation by mouse/key events
177 class ViewerTest_V3dView : public V3d_View
178 {
179   DEFINE_STANDARD_RTTI_INLINE(ViewerTest_V3dView, V3d_View)
180 public:
181   //! Initializes the view.
182   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType = V3d_ORTHOGRAPHIC,
183                       bool theIs2dMode = false)
184   : V3d_View (theViewer, theType), myIs2dMode (theIs2dMode) {}
185
186   //! Initializes the view by copying.
187   ViewerTest_V3dView (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)& theView)
188   : V3d_View (theViewer, theView), myIs2dMode (false)
189   {
190     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (theView))
191     {
192       myIs2dMode = aV3dView->IsViewIn2DMode();
193     }
194   }
195
196   //! Returns true if 2D mode is set for the view
197   bool IsViewIn2DMode() const { return myIs2dMode; }
198
199   //! Sets 2D mode for the view
200   void SetView2DMode (bool the2dMode) { myIs2dMode = the2dMode; }
201
202 public:
203
204   //! Returns true if active view in 2D mode.
205   static bool IsCurrentViewIn2DMode()
206   {
207     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
208     {
209       return aV3dView->IsViewIn2DMode();
210     }
211     return false;
212   }
213
214   //! Set if active view in 2D mode.
215   static void SetCurrentView2DMode (bool theIs2d)
216   {
217     if (Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView()))
218     {
219       aV3dView->SetView2DMode (theIs2d);
220     }
221   }
222
223 private:
224
225   Standard_Boolean myIs2dMode; //!< 2D mode flag
226
227 };
228
229 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
230 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
231 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
232 static OpenGl_Caps ViewerTest_myDefaultCaps;
233
234 static void OSWindowSetup();
235
236 static struct
237 {
238   Quantity_Color FlatColor;
239   Quantity_Color GradientColor1;
240   Quantity_Color GradientColor2;
241   Aspect_GradientFillMethod FillMethod;
242 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
243
244 //==============================================================================
245 //  EVENT GLOBAL VARIABLES
246 //==============================================================================
247
248 static int Start_Rot = 0;
249 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
250 int X_Motion = 0; // Current cursor position
251 int Y_Motion = 0;
252 int X_ButtonPress = 0; // Last ButtonPress position
253 int Y_ButtonPress = 0;
254 Standard_Boolean IsDragged = Standard_False;
255 Standard_Boolean DragFirst = Standard_False;
256 Standard_Boolean TheIsAnimating = Standard_False;
257 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
258 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
259
260 namespace
261 {
262
263   //! Checks if some set is a subset of other set
264   //! @tparam TheSuperSet the type of the superset
265   //! @tparam TheSubSet the type of the subset
266   //! @param theSuperSet the superset
267   //! @param theSubSet the subset to be checked
268   //! @return true if the superset includes subset, or false otherwise
269   template <typename TheSuperSet, typename TheSubSet>
270   static bool includes (const TheSuperSet& theSuperSet, const TheSubSet& theSubSet)
271   {
272     return std::includes (theSuperSet.begin(), theSuperSet.end(), theSubSet.begin(), theSubSet.end());
273   }
274
275   //! A variable set of keys for command-line options.
276   //! It includes a set of mandatory keys and a set of all possible keys.
277   class CommandOptionKeyVariableSet
278   {
279   public:
280     //! Default constructor
281     CommandOptionKeyVariableSet()
282     {
283     }
284
285     //! Constructor
286     //! @param theMandatoryKeySet the set of the mandatory option keys
287     //! @param theAdditionalKeySet the set of additional options that could be omitted
288     CommandOptionKeyVariableSet (
289       const ViewerTest_CommandOptionKeySet& theMandatoryKeySet,
290       const ViewerTest_CommandOptionKeySet& theAdditionalKeySet = ViewerTest_CommandOptionKeySet())
291     : myMandatoryKeySet (theMandatoryKeySet)
292     {
293       std::set_union (theMandatoryKeySet.begin(),
294                       theMandatoryKeySet.end(),
295                       theAdditionalKeySet.begin(),
296                       theAdditionalKeySet.end(),
297                       std::inserter (myFullKeySet, myFullKeySet.begin()));
298     }
299
300     //! Checks if the set of option keys fits to the current variable set (it must contain all mandatory keys
301     //! and be contained in the full key set)
302     //! @param theCheckedKeySet the set of option keys to be checked
303     bool IsInSet (const ViewerTest_CommandOptionKeySet& theCheckedKeySet) const
304     {
305       return includes (theCheckedKeySet, myMandatoryKeySet) && includes (myFullKeySet, theCheckedKeySet);
306     }
307
308   private:
309     //! A set of mandatory command-line option keys
310     ViewerTest_CommandOptionKeySet myMandatoryKeySet;
311
312     //! A full set of command-line option keys (includes mandatory and additional option keys)
313     ViewerTest_CommandOptionKeySet myFullKeySet;
314   };
315
316   //! Gets some code by its name
317   //! @tparam TheCode the type of a code to be found
318   //! @param theCodeNameMap the map from code names to codes
319   //! @param theCodeName the name of a code to be found
320   //! @param theCode the code to be found
321   //! @return true if a code is found, or false otherwise
322   template <typename TheCode>
323   static bool getSomeCodeByName (const std::map<TCollection_AsciiString, TheCode>& theCodeNameMap,
324                                  TCollection_AsciiString                           theCodeName,
325                                  TheCode&                                          theCode)
326   {
327     theCodeName.LowerCase();
328     const typename std::map<TCollection_AsciiString, TheCode>::const_iterator aCodeIterator = theCodeNameMap.find (
329       theCodeName);
330     if (aCodeIterator == theCodeNameMap.end())
331     {
332       return false;
333     }
334     theCode = aCodeIterator->second;
335     return true;
336   }
337
338   // Defines possible commands related to background changing
339   enum BackgroundCommand
340   {
341     BackgroundCommand_Main,         //!< The main command that manages other commands through options
342     BackgroundCommand_Image,        //!< Sets an image as a background
343     BackgroundCommand_ImageMode,    //!< Changes a background image mode
344     BackgroundCommand_Gradient,     //!< Sets a gradient as a background
345     BackgroundCommand_GradientMode, //!< Changes a background gradient mode
346     BackgroundCommand_Color,        //!< Fills background with a specified color
347     BackgroundCommand_Default       //!< Sets the background default color or gradient
348   };
349
350   //! Map from background command names to its codes
351   typedef std::map<TCollection_AsciiString, BackgroundCommand> BackgroundCommandNameMap;
352
353   //! Creates a map from background command names to its codes
354   //! @return a map from background command names to its codes
355   static BackgroundCommandNameMap createBackgroundCommandNameMap()
356   {
357     BackgroundCommandNameMap aBackgroundCommandNameMap;
358     aBackgroundCommandNameMap["vbackground"]    = BackgroundCommand_Main;
359     aBackgroundCommandNameMap["vsetbg"]         = BackgroundCommand_Image;
360     aBackgroundCommandNameMap["vsetbgmode"]     = BackgroundCommand_ImageMode;
361     aBackgroundCommandNameMap["vsetgradientbg"] = BackgroundCommand_Gradient;
362     aBackgroundCommandNameMap["vsetgrbgmode"]   = BackgroundCommand_GradientMode;
363     aBackgroundCommandNameMap["vsetcolorbg"]    = BackgroundCommand_Color;
364     aBackgroundCommandNameMap["vsetdefaultbg"]  = BackgroundCommand_Default;
365     return aBackgroundCommandNameMap;
366   }
367
368   //! Gets a background command by its name
369   //! @param theBackgroundCommandName the name of the background command
370   //! @param theBackgroundCommand the background command to be found
371   //! @return true if a background command is found, or false otherwise
372   static bool getBackgroundCommandByName (const TCollection_AsciiString& theBackgroundCommandName,
373                                           BackgroundCommand&             theBackgroundCommand)
374   {
375     static const BackgroundCommandNameMap THE_BACKGROUND_COMMAND_NAME_MAP = createBackgroundCommandNameMap();
376     return getSomeCodeByName (THE_BACKGROUND_COMMAND_NAME_MAP, theBackgroundCommandName, theBackgroundCommand);
377   }
378
379   //! Map from background image fill method names to its codes
380   typedef std::map<TCollection_AsciiString, Aspect_FillMethod> BackgroundImageFillMethodNameMap;
381
382   //! Creates a map from background image fill method names to its codes
383   //! @return a map from background image fill method names to its codes
384   static BackgroundImageFillMethodNameMap createBackgroundImageFillMethodNameMap()
385   {
386     BackgroundImageFillMethodNameMap aBackgroundImageFillMethodNameMap;
387     aBackgroundImageFillMethodNameMap["none"]     = Aspect_FM_NONE;
388     aBackgroundImageFillMethodNameMap["centered"] = Aspect_FM_CENTERED;
389     aBackgroundImageFillMethodNameMap["tiled"]    = Aspect_FM_TILED;
390     aBackgroundImageFillMethodNameMap["stretch"]  = Aspect_FM_STRETCH;
391     return aBackgroundImageFillMethodNameMap;
392   }
393
394   //! Gets a background image fill method by its name
395   //! @param theBackgroundImageFillMethodName the name of the background image fill method
396   //! @param theBackgroundImageFillMethod the background image fill method to be found
397   //! @return true if a background image fill method is found, or false otherwise
398   static bool getBackgroundImageFillMethodByName (const TCollection_AsciiString& theBackgroundImageFillMethodName,
399                                                   Aspect_FillMethod&             theBackgroundImageFillMethod)
400   {
401     static const BackgroundImageFillMethodNameMap THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP =
402       createBackgroundImageFillMethodNameMap();
403     return getSomeCodeByName (THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP,
404                               theBackgroundImageFillMethodName,
405                               theBackgroundImageFillMethod);
406   }
407
408   //! Map from background gradient fill method names to its codes
409   typedef std::map<TCollection_AsciiString, Aspect_GradientFillMethod> BackgroundGradientFillMethodNameMap;
410
411   //! Creates a map from background gradient fill method names to its codes
412   //! @return a map from background gradient fill method names to its codes
413   static BackgroundGradientFillMethodNameMap createBackgroundGradientFillMethodNameMap()
414   {
415     BackgroundGradientFillMethodNameMap aBackgroundGradientFillMethodNameMap;
416     aBackgroundGradientFillMethodNameMap["none"]       = Aspect_GFM_NONE;
417     aBackgroundGradientFillMethodNameMap["hor"]        = Aspect_GFM_HOR;
418     aBackgroundGradientFillMethodNameMap["horizontal"] = Aspect_GFM_HOR;
419     aBackgroundGradientFillMethodNameMap["ver"]        = Aspect_GFM_VER;
420     aBackgroundGradientFillMethodNameMap["vertical"]   = Aspect_GFM_VER;
421     aBackgroundGradientFillMethodNameMap["diag1"]      = Aspect_GFM_DIAG1;
422     aBackgroundGradientFillMethodNameMap["diagonal1"]  = Aspect_GFM_DIAG1;
423     aBackgroundGradientFillMethodNameMap["diag2"]      = Aspect_GFM_DIAG2;
424     aBackgroundGradientFillMethodNameMap["diagonal2"]  = Aspect_GFM_DIAG2;
425     aBackgroundGradientFillMethodNameMap["corner1"]    = Aspect_GFM_CORNER1;
426     aBackgroundGradientFillMethodNameMap["corner2"]    = Aspect_GFM_CORNER2;
427     aBackgroundGradientFillMethodNameMap["corner3"]    = Aspect_GFM_CORNER3;
428     aBackgroundGradientFillMethodNameMap["corner4"]    = Aspect_GFM_CORNER4;
429     return aBackgroundGradientFillMethodNameMap;
430   }
431
432   //! Gets a gradient fill method by its name
433   //! @param theBackgroundGradientFillMethodName the name of the gradient fill method
434   //! @param theBackgroundGradientFillMethod the gradient fill method to be found
435   //! @return true if a gradient fill method is found, or false otherwise
436   static bool getBackgroundGradientFillMethodByName (const TCollection_AsciiString& theBackgroundGradientFillMethodName,
437                                                      Aspect_GradientFillMethod&     theBackgroundGradientFillMethod)
438   {
439     static const BackgroundGradientFillMethodNameMap THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP =
440       createBackgroundGradientFillMethodNameMap();
441     return getSomeCodeByName (THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP,
442                               theBackgroundGradientFillMethodName,
443                               theBackgroundGradientFillMethod);
444   }
445
446   //! Changes the background in accordance with passed command line options
447   class BackgroundChanger
448   {
449   public:
450     //! Constructor. Prepares the command parser
451     BackgroundChanger()
452     {
453       prepareCommandParser();
454     }
455
456     //! Processes the command line and changes the background
457     //! @param theDrawInterpretor the interpreter of the Draw Harness application
458     //! @param theNumberOfCommandLineArguments the number of passed command line arguments
459     //! @param theCommandLineArguments the array of command line arguments
460     bool ProcessCommandLine (Draw_Interpretor&        theDrawInterpretor,
461                              const Standard_Integer   theNumberOfCommandLineArguments,
462                              const char* const* const theCommandLineArguments)
463     {
464       const char* const aBackgroundCommandName = theCommandLineArguments[0];
465       BackgroundCommand aBackgroundCommand = BackgroundCommand_Main;
466       if (!getBackgroundCommandByName (aBackgroundCommandName, aBackgroundCommand))
467       {
468         return false;
469       }
470       addCommandDescription (aBackgroundCommand);
471       myCommandParser.Parse (theNumberOfCommandLineArguments, theCommandLineArguments);
472       return processCommandOptions (aBackgroundCommandName, aBackgroundCommand, theDrawInterpretor);
473     }
474
475   private:
476     //! The type of functions that are able to set gradient background filling
477     typedef void SetGradientFunction (const Quantity_Color& /* theColor1 */,
478                                       const Quantity_Color& /* theColor2 */,
479                                       const Aspect_GradientFillMethod /* theGradientMode */);
480
481     //! The type of functions that are able to fill a background with a specific color
482     typedef void SetColorFunction (const Quantity_Color& /* theColor */);
483
484     //! the command parser used to parse command line options and its arguments
485     ViewerTest_CmdParser myCommandParser;
486
487     //! the option key for the command that sets an image as a background
488     ViewerTest_CommandOptionKey myImageOptionKey;
489
490     //! the option key for the command that sets a background image fill type
491     ViewerTest_CommandOptionKey myImageModeOptionKey;
492
493     //! the option key for the command that sets a gradient filling for the background
494     ViewerTest_CommandOptionKey myGradientOptionKey;
495
496     //! the option key for the command that sets a background gradient filling method
497     ViewerTest_CommandOptionKey myGradientModeOptionKey;
498
499     //! the option key for the command that fills background with a specific color
500     ViewerTest_CommandOptionKey myColorOptionKey;
501
502     //! the option key for the command that sets default background gradient or color
503     ViewerTest_CommandOptionKey myDefaultOptionKey;
504
505     //! the variable set of options that are allowed for the old scenario (without any option passed)
506     CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
507
508     //! the variable set of options that are allowed for setting an image as a background
509     CommandOptionKeyVariableSet myImageOptionVariableSet;
510
511     //! the variable set of options that are allowed for setting a background image fill type
512     CommandOptionKeyVariableSet myImageModeOptionVariableSet;
513
514     //! the variable set of options that are allowed for setting a gradient filling for the background
515     CommandOptionKeyVariableSet myGradientOptionVariableSet;
516
517     //! the variable set of options that are allowed for setting a background gradient filling method
518     CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
519
520     //! the variable set of options that are allowed for filling a background with a specific color
521     CommandOptionKeyVariableSet myColorOptionVariableSet;
522
523     //! the variable set of options that are allowed for setting a default background gradient
524     CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
525
526     //! the variable set of options that are allowed for setting a default background color
527     CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
528
529     //! the variable set of options that are allowed for printing help
530     CommandOptionKeyVariableSet myHelpOptionVariableSet;
531
532     //! Adds options to command parser
533     void addOptionsToCommandParser()
534     {
535       myImageOptionKey     = myCommandParser.AddOption ("imageFile|image|imgFile|img",
536                                                     "filename of image used as background");
537       myImageModeOptionKey = myCommandParser.AddOption (
538         "imageMode|imgMode", "image fill type, should be one of CENTERED, TILED, STRETCH, NONE");
539       myGradientOptionKey = myCommandParser.AddOption ("gradient|grad|gr",
540                                                        "sets background gradient starting and ending colors");
541       myGradientModeOptionKey =
542         myCommandParser.AddOption ("gradientMode|gradMode|gradMd|grMode|grMd",
543                                    "gradient fill method, should be one of NONE, HOR[IZONTAL], VER[TICAL], "
544                                    "DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, CORNER4");
545       myColorOptionKey   = myCommandParser.AddOption ("color|col", "background color");
546       myDefaultOptionKey = myCommandParser.AddOption ("default|def", "sets background default gradient or color");
547     }
548
549     //! Creates option sets used to determine if a passed option set is valid or not
550     void createOptionSets()
551     {
552       ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
553       anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
554       myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
555
556       ViewerTest_CommandOptionKeySet anImageOptionSet;
557       anImageOptionSet.insert (myImageOptionKey);
558       ViewerTest_CommandOptionKeySet anImageModeOptionSet;
559       anImageModeOptionSet.insert (myImageModeOptionKey);
560       myImageOptionVariableSet     = CommandOptionKeyVariableSet (anImageOptionSet, anImageModeOptionSet);
561       myImageModeOptionVariableSet = CommandOptionKeyVariableSet (anImageModeOptionSet);
562
563       ViewerTest_CommandOptionKeySet aGradientOptionSet;
564       aGradientOptionSet.insert (myGradientOptionKey);
565       ViewerTest_CommandOptionKeySet aGradientModeOptionSet;
566       aGradientModeOptionSet.insert (myGradientModeOptionKey);
567       myGradientOptionVariableSet     = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
568       myGradientModeOptionVariableSet = CommandOptionKeyVariableSet (aGradientModeOptionSet);
569
570       ViewerTest_CommandOptionKeySet aColorOptionSet;
571       aColorOptionSet.insert (myColorOptionKey);
572       myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
573
574       aGradientOptionSet.insert (myDefaultOptionKey);
575       myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
576       aColorOptionSet.insert (myDefaultOptionKey);
577       myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
578
579       ViewerTest_CommandOptionKeySet aHelpOptionSet;
580       aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
581       myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
582     }
583
584     //! Prepares the command parser. Adds options and creates option sets used to determine
585     //! if a passed option set is valid or not
586     void prepareCommandParser()
587     {
588       addOptionsToCommandParser();
589       createOptionSets();
590     }
591
592     //! Adds a command description to the command parser
593     //! @param theBackgroundCommand the key of the command which description is added to the command parser
594     void addCommandDescription (const BackgroundCommand theBackgroundCommand)
595     {
596       std::string aDescription;
597       bool        isMainCommand = false;
598       switch (theBackgroundCommand)
599       {
600         case BackgroundCommand_Main:
601           aDescription  = "Command: vbackground (changes background or some background settings)";
602           isMainCommand = true;
603           break;
604         case BackgroundCommand_Image:
605           aDescription = "Command: vsetbg (loads image as a background)";
606           break;
607         case BackgroundCommand_ImageMode:
608           aDescription = "Command: vsetbgmode (changes background fill type)";
609           break;
610         case BackgroundCommand_Gradient:
611           aDescription = "Command: vsetgradientbg (mounts gradient background)";
612           break;
613         case BackgroundCommand_GradientMode:
614           aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
615           break;
616         case BackgroundCommand_Color:
617           aDescription = "Command: vsetcolorbg (sets color background)";
618           break;
619         case BackgroundCommand_Default:
620           aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
621           break;
622         default:
623           return;
624       }
625       if (!isMainCommand)
626       {
627         aDescription += "\nThis command is obsolete. Use vbackground instead.";
628       }
629       myCommandParser.SetDescription (aDescription);
630     }
631
632     //! Check if a viewer is needed to be initialized
633     //! @param theBackgroundCommand the key of the command that changes the background
634     //! @return true if processing was successful, or false otherwise
635     bool checkViewerIsNeeded (const BackgroundCommand theBackgroundCommand) const
636     {
637       const bool                           isMain             = (theBackgroundCommand == BackgroundCommand_Main);
638       const ViewerTest_CommandOptionKeySet aUsedOptions       = myCommandParser.GetUsedOptions();
639       const bool                           aViewerIsNotNeeded =
640         (theBackgroundCommand == BackgroundCommand_Default)
641         || (myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
642         || (myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
643         || myHelpOptionVariableSet.IsInSet (aUsedOptions);
644       return !aViewerIsNotNeeded;
645     }
646
647     //! Check if a viewer is initialized
648     //! @param theBackgroundCommandName the name of the command that changes the background
649     //! @param theDrawInterpretor the interpreter of the Draw Harness application
650     //! @return true if a viewer is initialized, or false otherwise
651     static bool checkViewerIsInitialized (const char* const theBackgroundCommandName,
652                                           Draw_Interpretor& theDrawInterpretor)
653     {
654       const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
655       if (anAISContext.IsNull())
656       {
657         theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
658         return false;
659       }
660       return true;
661     }
662
663     //! Processes command options
664     //! @param theBackgroundCommandName the name of the command that changes the background
665     //! @param theBackgroundCommand the key of the command that changes the background
666     //! @param theDrawInterpretor the interpreter of the Draw Harness application
667     //! @return true if processing was successful, or false otherwise
668     bool processCommandOptions (const char* const       theBackgroundCommandName,
669                                 const BackgroundCommand theBackgroundCommand,
670                                 Draw_Interpretor&       theDrawInterpretor) const
671     {
672       if (myCommandParser.HasNoOption())
673       {
674         return printHelp (theBackgroundCommandName, theDrawInterpretor);
675       }
676       if (checkViewerIsNeeded (theBackgroundCommand)
677           && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
678       {
679         return false;
680       }
681       if (myCommandParser.HasOnlyUnnamedOption())
682       {
683         return processUnnamedOption (theBackgroundCommand);
684       }
685       return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
686     }
687
688     //! Processes the unnamed option
689     //! @param theBackgroundCommand the key of the command that changes the background
690     //! @return true if processing was successful, or false otherwise
691     bool processUnnamedOption (const BackgroundCommand theBackgroundCommand) const
692     {
693       switch (theBackgroundCommand)
694       {
695         case BackgroundCommand_Main:
696           return false;
697         case BackgroundCommand_Image:
698           return processImageUnnamedOption();
699         case BackgroundCommand_ImageMode:
700           return processImageModeUnnamedOption();
701         case BackgroundCommand_Gradient:
702           return processGradientUnnamedOption();
703         case BackgroundCommand_GradientMode:
704           return processGradientModeUnnamedOption();
705         case BackgroundCommand_Color:
706           return processColorUnnamedOption();
707         case BackgroundCommand_Default:
708           return processDefaultUnnamedOption();
709         default:
710           return false;
711       }
712     }
713
714     //! Processes the image unnamed option
715     //! @return true if processing was successful, or false otherwise
716     bool processImageUnnamedOption() const
717     {
718       const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
719         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
720       if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
721       {
722         return false;
723       }
724       std::string anImageFileName;
725       if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
726       {
727         return false;
728       }
729       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
730       if (aNumberOfImageUnnamedOptionArguments == 2)
731       {
732         std::string anImageModeString;
733         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
734         {
735           return false;
736         }
737         if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
738         {
739           return false;
740         }
741       }
742       setImage (anImageFileName.c_str(), anImageMode);
743       return true;
744     }
745
746     //! Processes the image mode unnamed option
747     //! @return true if processing was successful, or false otherwise
748     bool processImageModeUnnamedOption() const
749     {
750       return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
751     }
752
753     //! Processes the gradient unnamed option
754     //! @param theSetGradient the function used to set a background gradient filling
755     //! @return true if processing was successful, or false otherwise
756     bool processGradientUnnamedOption (SetGradientFunction* const theSetGradient = setGradient) const
757     {
758       const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
759         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
760       if (aNumberOfGradientUnnamedOptionArguments < 2)
761       {
762         return false;
763       }
764
765       Standard_Integer anArgumentIndex = 0;
766       Quantity_Color   aColor1;
767       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
768       {
769         return false;
770       }
771       if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
772       {
773         return false;
774       }
775
776       Quantity_Color aColor2;
777       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
778       {
779         return false;
780       }
781       if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
782       {
783         return false;
784       }
785
786       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
787       if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
788       {
789         std::string anGradientModeString;
790
791         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
792                                   anArgumentIndex,
793                                   anGradientModeString))
794         {
795           return false;
796         }
797         if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
798         {
799           return false;
800         }
801         ++anArgumentIndex;
802       }
803       if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
804       {
805         return false;
806       }
807       theSetGradient (aColor1, aColor2, aGradientMode);
808       return true;
809     }
810
811     //! Processes the gradient mode unnamed option
812     //! @return true if processing was successful, or false otherwise
813     bool processGradientModeUnnamedOption() const
814     {
815       return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
816     }
817
818     //! Processes the color unnamed option
819     //! @param theSetColor the function used to set a background color
820     //! @return true if processing was successful, or false otherwise
821     bool processColorUnnamedOption (SetColorFunction* const theSetColor = setColor) const
822     {
823       return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
824     }
825
826     //! Processes the default back unnamed option
827     //! @return true if processing was successful, or false otherwise
828     bool processDefaultUnnamedOption() const
829     {
830       if (processGradientUnnamedOption (setDefaultGradient))
831       {
832         return true;
833       }
834       return processColorUnnamedOption (setDefaultColor);
835     }
836
837     //! Processes named options
838     //! @param theBackgroundCommandName the name of the command that changes the background
839     //! @param theBackgroundCommand the key of the command that changes the background
840     //! @param theDrawInterpretor the interpreter of the Draw Harness application
841     //! @return true if processing was successful, or false otherwise
842     bool processNamedOptions (const char* const       theBackgroundCommandName,
843                               const BackgroundCommand theBackgroundCommand,
844                               Draw_Interpretor&       theDrawInterpretor) const
845     {
846       const bool                           isMain       = (theBackgroundCommand == BackgroundCommand_Main);
847       const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
848       if (myImageOptionVariableSet.IsInSet (aUsedOptions)
849           && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
850       {
851         return processImageOptionSet();
852       }
853       if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
854           && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
855       {
856         return processImageModeOptionSet();
857       }
858       if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
859           && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
860       {
861         return processGradientOptionSet();
862       }
863       if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
864           && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
865       {
866         return processGradientModeOptionSet();
867       }
868       if (myColorOptionVariableSet.IsInSet (aUsedOptions)
869           && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
870       {
871         return processColorOptionSet();
872       }
873       if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
874           || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
875               && (theBackgroundCommand == BackgroundCommand_Default)))
876       {
877         return processDefaultGradientOptionSet();
878       }
879       if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
880           || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
881       {
882         return processDefaultColorOptionSet();
883       }
884       if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
885       {
886         return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
887       }
888       return false;
889     }
890
891     //! Processes the image option set
892     //! @return true if processing was successful, or false otherwise
893     bool processImageOptionSet() const
894     {
895       std::string anImageFileName;
896       if (!processImageOption (anImageFileName))
897       {
898         return false;
899       }
900       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
901       if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
902       {
903         return false;
904       }
905       setImage (anImageFileName.c_str(), anImageMode);
906       return true;
907     }
908
909     //! Processes the image mode option set
910     //! @return true if processing was successful, or false otherwise
911     bool processImageModeOptionSet() const
912     {
913       return processImageModeOptionSet (myImageModeOptionKey);
914     }
915
916     //! Processes the image mode option set
917     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
918     //! @return true if processing was successful, or false otherwise
919     bool processImageModeOptionSet (const ViewerTest_CommandOptionKey theImageModeOptionKey) const
920     {
921       Aspect_FillMethod anImageMode = Aspect_FM_NONE;
922       if (!processImageModeOption (theImageModeOptionKey, anImageMode))
923       {
924         return false;
925       }
926       setImageMode (anImageMode);
927       return true;
928     }
929
930     //! Processes the gradient option set
931     //! @param theSetGradient the function used to set a background gradient filling
932     //! @return true if processing was successful, or false otherwise
933     bool processGradientOptionSet (SetGradientFunction* const theSetGradient = setGradient) const
934     {
935       Quantity_Color aColor1;
936       Quantity_Color aColor2;
937       if (!processGradientOption (aColor1, aColor2))
938       {
939         return false;
940       }
941       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
942       if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
943       {
944         return false;
945       }
946       theSetGradient (aColor1, aColor2, aGradientMode);
947       return true;
948     }
949
950     //! Processes the gradient mode option set
951     //! @return true if processing was successful, or false otherwise
952     bool processGradientModeOptionSet() const
953     {
954       return processGradientModeOptionSet (myGradientModeOptionKey);
955     }
956
957     //! Processes the gradient mode option set
958     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
959     //! @return true if processing was successful, or false otherwise
960     bool processGradientModeOptionSet (const ViewerTest_CommandOptionKey theGradientModeOptionKey) const
961     {
962       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
963       if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
964       {
965         return false;
966       }
967       setGradientMode (aGradientMode);
968       return true;
969     }
970
971     //! Processes the color option set
972     //! @param theSetColor the function used to set a background color
973     //! @return true if processing was successful, or false otherwise
974     bool processColorOptionSet (SetColorFunction* const theSetColor = setColor) const
975     {
976       return processColorOptionSet (myColorOptionKey, theSetColor);
977     }
978
979     //! Processes the default color option set
980     //! @return true if processing was successful, or false otherwise
981     bool processDefaultGradientOptionSet() const
982     {
983       return processGradientOptionSet (setDefaultGradient);
984     }
985
986     //! Processes the default gradient option set
987     //! @return true if processing was successful, or false otherwise
988     bool processDefaultColorOptionSet() const
989     {
990       return processColorOptionSet (setDefaultColor);
991     }
992
993     //! Processes the color option set
994     //! @param theColorOptionKey the key of the option that is interpreted as a color option
995     //! @param theSetColor the function used to set a background color
996     //! @return true if processing was successful, or false otherwise
997     bool processColorOptionSet (const ViewerTest_CommandOptionKey theColorOptionKey,
998                                 SetColorFunction* const           theSetColor = setColor) const
999     {
1000       Quantity_Color aColor;
1001       if (!processColorOption (theColorOptionKey, aColor))
1002       {
1003         return false;
1004       }
1005       theSetColor (aColor);
1006       return true;
1007     }
1008
1009     //! Processes the help option set
1010     //! @param theBackgroundCommandName the name of the command that changes the background
1011     //! @param theDrawInterpretor the interpreter of the Draw Harness application
1012     //! @return true if processing was successful, or false otherwise
1013     bool processHelpOptionSet (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor) const
1014     {
1015       const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1016         ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
1017       if (aNumberOfHelpOptionArguments != 0)
1018       {
1019         return false;
1020       }
1021       return printHelp (theBackgroundCommandName, theDrawInterpretor);
1022     }
1023
1024     //! Processes the image option
1025     //! @param theImageFileName the filename of the image to be used as a background
1026     //! @return true if processing was successful, or false otherwise
1027     bool processImageOption (std::string& theImageFileName) const
1028     {
1029       const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1030         myImageOptionKey);
1031       if (aNumberOfImageOptionArguments != 1)
1032       {
1033         return false;
1034       }
1035       std::string anImageFileName;
1036       if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
1037       {
1038         return false;
1039       }
1040       theImageFileName = anImageFileName;
1041       return true;
1042     }
1043
1044     //! Processes the image mode option
1045     //! @param theImageMode the fill type used for a background image
1046     //! @return true if processing was successful, or false otherwise
1047     bool processImageModeOption (Aspect_FillMethod& theImageMode) const
1048     {
1049       return processImageModeOption (myImageModeOptionKey, theImageMode);
1050     }
1051
1052     //! Processes the image mode option
1053     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
1054     //! @param theImageMode the fill type used for a background image
1055     //! @return true if processing was successful, or false otherwise
1056     bool processImageModeOption (const ViewerTest_CommandOptionKey theImageModeOptionKey,
1057                                  Aspect_FillMethod&                theImageMode) const
1058     {
1059       return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
1060     }
1061
1062     //! Processes the gradient option
1063     //! @param theColor1 the gradient starting color
1064     //! @param theColor2 the gradient ending color
1065     //! @return true if processing was successful, or false otherwise
1066     bool processGradientOption (Quantity_Color& theColor1, Quantity_Color& theColor2) const
1067     {
1068       Standard_Integer anArgumentIndex = 0;
1069       Quantity_Color   aColor1;
1070       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
1071       {
1072         return false;
1073       }
1074       Quantity_Color aColor2;
1075       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
1076       {
1077         return false;
1078       }
1079       const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1080         myGradientOptionKey);
1081       if (anArgumentIndex != aNumberOfGradientOptionArguments)
1082       {
1083         return false;
1084       }
1085       theColor1 = aColor1;
1086       theColor2 = aColor2;
1087       return true;
1088     }
1089
1090     //! Processes the gradient mode option
1091     //! @param theGradientMode the fill method used for a background gradient filling
1092     //! @return true if processing was successful, or false otherwise
1093     bool processGradientModeOption (Aspect_GradientFillMethod& theGradientMode) const
1094     {
1095       return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
1096     }
1097
1098     //! Processes the gradient mode option
1099     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
1100     //! @param theGradientMode the fill method used for a background gradient filling
1101     //! @return true if processing was successful, or false otherwise
1102     bool processGradientModeOption (const ViewerTest_CommandOptionKey theGradientModeOptionKey,
1103                                     Aspect_GradientFillMethod&        theGradientMode) const
1104     {
1105       return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1106     }
1107
1108     //! Processes some mode option
1109     //! @tparam TheMode the type of a mode to be processed
1110     //! @param theModeOptionKey the key of the option that is interpreted as a mode option
1111     //! @param theMode a mode to be processed
1112     //! @return true if processing was successful, or false otherwise
1113     template <typename TheMode>
1114     bool processModeOption (const ViewerTest_CommandOptionKey theModeOptionKey,
1115                             bool (*const theGetModeByName) (const TCollection_AsciiString& /* theModeName */,
1116                                                             TheMode& /* theMode */),
1117                             TheMode& theMode) const
1118     {
1119       const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1120         theModeOptionKey);
1121       if (aNumberOfModeOptionArguments != 1)
1122       {
1123         return false;
1124       }
1125       std::string aModeString;
1126       if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1127       {
1128         return false;
1129       }
1130       TheMode aMode = TheMode();
1131       if (!theGetModeByName (aModeString.c_str(), aMode))
1132       {
1133         return false;
1134       }
1135       theMode = aMode;
1136       return true;
1137     }
1138
1139     //! Processes the color option
1140     //! @param theColor a color used for filling a background
1141     //! @return true if processing was successful, or false otherwise
1142     bool processColorOption (Quantity_Color& theColor) const
1143     {
1144       return processColorOption (myColorOptionKey, theColor);
1145     }
1146
1147     //! Processes the color option
1148     //! @param theColorOptionKey the key of the option that is interpreted as a color option
1149     //! @param theColor a color used for filling a background
1150     //! @return true if processing was successful, or false otherwise
1151     bool processColorOption (const ViewerTest_CommandOptionKey theColorOptionKey, Quantity_Color& theColor) const
1152     {
1153       Standard_Integer anArgumentIndex = 0;
1154       Quantity_Color   aColor;
1155       if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1156       {
1157         return false;
1158       }
1159       const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1160         theColorOptionKey);
1161       if (anArgumentIndex != aNumberOfColorOptionArguments)
1162       {
1163         return false;
1164       }
1165       theColor = aColor;
1166       return true;
1167     }
1168
1169     //! Prints helping message
1170     //! @param theBackgroundCommandName the name of the command that changes the background
1171     //! @param theDrawInterpretor the interpreter of the Draw Harness application
1172     //! @return true if printing was successful, or false otherwise
1173     static bool printHelp (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor)
1174     {
1175       return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1176     }
1177
1178     //! Sets the image as a background
1179     //! @param theImageFileName the filename of the image to be used as a background
1180     //! @param theImageMode the fill type used for a background image
1181     static void setImage (const Standard_CString theImageFileName, const Aspect_FillMethod theImageMode)
1182     {
1183       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1184       aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1185     }
1186
1187     //! Sets the fill type used for a background image
1188     //! @param theImageMode the fill type used for a background image
1189     static void setImageMode (const Aspect_FillMethod theImageMode)
1190     {
1191       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1192       aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1193     }
1194
1195     //! Sets the gradient filling for a background
1196     //! @param theColor1 the gradient starting color
1197     //! @param theColor2 the gradient ending color
1198     //! @param theGradientMode the fill method used for a background gradient filling
1199     static void setGradient (const Quantity_Color&           theColor1,
1200                              const Quantity_Color&           theColor2,
1201                              const Aspect_GradientFillMethod theGradientMode)
1202     {
1203       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1204       aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1205     }
1206
1207     //! Sets the fill method used for a background gradient filling
1208     //! @param theGradientMode the fill method used for a background gradient filling
1209     static void setGradientMode (const Aspect_GradientFillMethod theGradientMode)
1210     {
1211       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1212       aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1213     }
1214
1215     //! Sets the color used for filling a background
1216     //! @param theColor the color used for filling a background
1217     static void setColor (const Quantity_Color& theColor)
1218     {
1219       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1220       aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1221       aCurrentView->SetBackgroundColor (theColor);
1222       aCurrentView->Update();
1223     }
1224
1225     //! Sets the gradient filling for a background in a default viewer
1226     //! @param theColor1 the gradient starting color
1227     //! @param theColor2 the gradient ending color
1228     //! @param theGradientMode the fill method used for a background gradient filling
1229     static void setDefaultGradient (const Quantity_Color&           theColor1,
1230                                     const Quantity_Color&           theColor2,
1231                                     const Aspect_GradientFillMethod theGradientMode)
1232     {
1233       ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1234       ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1235       ViewerTest_DefaultBackground.FillMethod     = theGradientMode;
1236       setDefaultGradient();
1237     }
1238
1239     //! Sets the color used for filling a background in a default viewer
1240     //! @param theColor the color used for filling a background
1241     static void setDefaultColor (const Quantity_Color& theColor)
1242     {
1243       ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
1244       ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
1245       ViewerTest_DefaultBackground.FillMethod     = Aspect_GFM_NONE;
1246       ViewerTest_DefaultBackground.FlatColor      = theColor;
1247       setDefaultGradient();
1248       setDefaultColor();
1249     }
1250
1251     //! Sets the gradient filling for a background in a default viewer.
1252     //! Gradient settings are taken from ViewerTest_DefaultBackground structure
1253     static void setDefaultGradient()
1254     {
1255       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1256              anInteractiveContextIterator (ViewerTest_myContexts);
1257            anInteractiveContextIterator.More();
1258            anInteractiveContextIterator.Next())
1259       {
1260         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1261         aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1262                                              ViewerTest_DefaultBackground.GradientColor2,
1263                                              ViewerTest_DefaultBackground.FillMethod);
1264       }
1265     }
1266
1267     //! Sets the color used for filling a background in a default viewer.
1268     //! The color value is taken from ViewerTest_DefaultBackground structure
1269     static void setDefaultColor()
1270     {
1271       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1272              anInteractiveContextIterator (ViewerTest_myContexts);
1273            anInteractiveContextIterator.More();
1274            anInteractiveContextIterator.Next())
1275       {
1276         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1277         aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1278       }
1279     }
1280   };
1281
1282 } // namespace
1283
1284 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
1285 {
1286   static Handle(AIS_RubberBand) aBand;
1287   if (aBand.IsNull())
1288   {
1289     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
1290     aBand->SetDisplayMode (0);
1291   }
1292   return aBand;
1293 }
1294
1295 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
1296
1297 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
1298 {
1299   static ViewerTest_MapOfAISManipulators aMap;
1300   return aMap;
1301 }
1302
1303 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
1304 {
1305   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
1306   for (; anIt.More(); anIt.Next())
1307   {
1308     if (anIt.Value()->HasActiveMode())
1309     {
1310       return anIt.Value();
1311     }
1312   }
1313   return NULL;
1314 }
1315
1316 //==============================================================================
1317
1318 #ifdef _WIN32
1319 static LRESULT WINAPI ViewerWindowProc(
1320                                        HWND hwnd,
1321                                        UINT uMsg,
1322                                        WPARAM wParam,
1323                                        LPARAM lParam );
1324 static LRESULT WINAPI AdvViewerWindowProc(
1325   HWND hwnd,
1326   UINT uMsg,
1327   WPARAM wParam,
1328   LPARAM lParam );
1329 #endif
1330
1331
1332 //==============================================================================
1333 //function : WClass
1334 //purpose  :
1335 //==============================================================================
1336
1337 const Handle(Standard_Transient)& ViewerTest::WClass()
1338 {
1339   static Handle(Standard_Transient) theWClass;
1340 #if defined(_WIN32)
1341   if (theWClass.IsNull())
1342   {
1343     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
1344                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
1345                                 ::LoadCursor (NULL, IDC_ARROW));
1346   }
1347 #endif
1348   return theWClass;
1349 }
1350
1351 //==============================================================================
1352 //function : CreateName
1353 //purpose  : Create numerical name for new object in theMap
1354 //==============================================================================
1355 template <typename ObjectType>
1356 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1357                                     const TCollection_AsciiString& theDefaultString)
1358 {
1359   if (theObjectMap.IsEmpty())
1360     return theDefaultString + TCollection_AsciiString(1);
1361
1362   Standard_Integer aNextKey = 1;
1363   Standard_Boolean isFound = Standard_False;
1364   while (!isFound)
1365   {
1366     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1367     // Look for objects with default names
1368     if (theObjectMap.IsBound1(aStringKey))
1369     {
1370       aNextKey++;
1371     }
1372     else
1373       isFound = Standard_True;
1374   }
1375
1376   return theDefaultString + TCollection_AsciiString(aNextKey);
1377 }
1378
1379 //==============================================================================
1380 //structure : ViewerTest_Names
1381 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
1382 //==============================================================================
1383 struct ViewerTest_Names
1384 {
1385 private:
1386   TCollection_AsciiString myDriverName;
1387   TCollection_AsciiString myViewerName;
1388   TCollection_AsciiString myViewName;
1389
1390 public:
1391
1392   const TCollection_AsciiString& GetDriverName () const
1393   {
1394     return myDriverName;
1395   }
1396   void SetDriverName (const TCollection_AsciiString& theDriverName)
1397   {
1398     myDriverName = theDriverName;
1399   }
1400   const TCollection_AsciiString& GetViewerName () const
1401   {
1402     return myViewerName;
1403   }
1404   void SetViewerName (const TCollection_AsciiString& theViewerName)
1405   {
1406     myViewerName = theViewerName;
1407   }
1408   const TCollection_AsciiString& GetViewName () const
1409   {
1410     return myViewName;
1411   }
1412   void SetViewName (const TCollection_AsciiString& theViewName)
1413   {
1414     myViewName = theViewName;
1415   }
1416
1417   //===========================================================================
1418   //function : Constructor for ViewerTest_Names
1419   //purpose  : Get view, viewer, driver names from custom string
1420   //===========================================================================
1421
1422   ViewerTest_Names (const TCollection_AsciiString& theInputString)
1423   {
1424     TCollection_AsciiString aName(theInputString);
1425     if (theInputString.IsEmpty())
1426     {
1427       // Get current configuration
1428       if (ViewerTest_myDrivers.IsEmpty())
1429         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1430           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1431       else
1432         myDriverName = ViewerTest_myDrivers.Find2
1433         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1434
1435       if(ViewerTest_myContexts.IsEmpty())
1436       {
1437         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1438           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1439       }
1440       else
1441       {
1442         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
1443       }
1444
1445       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
1446     }
1447     else
1448     {
1449       // There is at least view name
1450       Standard_Integer aParserNumber = 0;
1451       for (Standard_Integer i = 0; i < 3; ++i)
1452       {
1453         Standard_Integer aParserPos = aName.SearchFromEnd("/");
1454         if(aParserPos != -1)
1455         {
1456           aParserNumber++;
1457           aName.Split(aParserPos-1);
1458         }
1459         else
1460           break;
1461       }
1462       if (aParserNumber == 0)
1463       {
1464         // Only view name
1465         if (!ViewerTest::GetAISContext().IsNull())
1466         {
1467           myDriverName = ViewerTest_myDrivers.Find2
1468           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1469           myViewerName = ViewerTest_myContexts.Find2
1470           (ViewerTest::GetAISContext());
1471         }
1472         else
1473         {
1474           // There is no opened contexts here, need to create names for viewer and driver
1475           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1476             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1477
1478           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1479             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1480         }
1481         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1482       }
1483       else if (aParserNumber == 1)
1484       {
1485         // Here is viewerName/viewName
1486         if (!ViewerTest::GetAISContext().IsNull())
1487           myDriverName = ViewerTest_myDrivers.Find2
1488           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1489         else
1490         {
1491           // There is no opened contexts here, need to create name for driver
1492           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1493             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1494         }
1495         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1496
1497         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1498       }
1499       else
1500       {
1501         //Here is driverName/viewerName/viewName
1502         myDriverName = TCollection_AsciiString(aName);
1503
1504         TCollection_AsciiString aViewerName(theInputString);
1505         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1506         myViewerName = TCollection_AsciiString(aViewerName);
1507
1508         myViewName = TCollection_AsciiString(theInputString);
1509       }
1510     }
1511   }
1512 };
1513
1514 //==============================================================================
1515 //function : FindContextByView
1516 //purpose  : Find AIS_InteractiveContext by View
1517 //==============================================================================
1518
1519 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1520 {
1521   Handle(AIS_InteractiveContext) anAISContext;
1522
1523   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1524        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1525   {
1526     if (anIter.Value()->CurrentViewer() == theView->Viewer())
1527        return anIter.Key2();
1528   }
1529   return anAISContext;
1530 }
1531
1532
1533 //==============================================================================
1534 //function : SetWindowTitle
1535 //purpose  : Set window title
1536 //==============================================================================
1537
1538 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
1539                      Standard_CString theTitle)
1540 {
1541 #if defined(_WIN32)
1542   const TCollection_ExtendedString theTitleW (theTitle);
1543   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
1544 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1545   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
1546 #else
1547   if(GetDisplayConnection()->GetDisplay())
1548   {
1549     Window aWindow =
1550       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
1551     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
1552   }
1553 #endif
1554 }
1555
1556 //==============================================================================
1557 //function : IsWindowOverlapped
1558 //purpose  : Check if theWindow overlapp another view
1559 //==============================================================================
1560
1561 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
1562                                      const Standard_Integer thePxTop,
1563                                      const Standard_Integer thePxRight,
1564                                      const Standard_Integer thePxBottom,
1565                                      TCollection_AsciiString& theViewId)
1566 {
1567   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1568       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1569   {
1570     Standard_Integer aTop = 0,
1571       aLeft = 0,
1572       aRight = 0,
1573       aBottom = 0;
1574     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
1575     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1576         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
1577         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1578         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
1579     {
1580       theViewId = anIter.Key1();
1581       return Standard_True;
1582     }
1583   }
1584   return Standard_False;
1585 }
1586
1587 // Workaround: to create and delete non-orthographic views outside ViewerTest
1588 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1589 {
1590   ViewerTest_myViews.UnBind1 (theName);
1591 }
1592
1593 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1594                                const Handle(V3d_View)& theView)
1595 {
1596   ViewerTest_myViews.Bind (theName, theView);
1597 }
1598
1599 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1600 {
1601   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1602 }
1603
1604 //! Auxiliary tool performing continuous redraws of specified window.
1605 class ViewerTest_ContinuousRedrawer
1606 {
1607 public:
1608   //! Return global instance.
1609   static ViewerTest_ContinuousRedrawer& Instance()
1610   {
1611     static ViewerTest_ContinuousRedrawer aRedrawer;
1612     return aRedrawer;
1613   }
1614 public:
1615
1616   //! Destructor.
1617   ~ViewerTest_ContinuousRedrawer()
1618   {
1619     Stop();
1620   }
1621
1622   //! Start thread.
1623   void Start (const Handle(Aspect_Window)& theWindow,
1624               Standard_Real theTargetFps)
1625   {
1626     if (myWindow != theWindow
1627      || myTargetFps != theTargetFps)
1628     {
1629       Stop();
1630       myWindow = theWindow;
1631       myTargetFps = theTargetFps;
1632     }
1633     if (myThread.GetId() == 0)
1634     {
1635       myToStop = false;
1636       myThread.Run (this);
1637     }
1638   }
1639
1640   //! Stop thread.
1641   void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1642   {
1643     if (!theWindow.IsNull()
1644       && myWindow != theWindow)
1645     {
1646       return;
1647     }
1648
1649     {
1650       Standard_Mutex::Sentry aLock (myMutex);
1651       myToStop = true;
1652     }
1653     myThread.Wait();
1654     myToStop = false;
1655     myWindow.Nullify();
1656   }
1657
1658 private:
1659
1660   //! Thread loop.
1661   void doThreadLoop()
1662   {
1663     Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1664     OSD_Timer aTimer;
1665     aTimer.Start();
1666     Standard_Real aTimeOld = 0.0;
1667     const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1668     for (;;)
1669     {
1670       {
1671         Standard_Mutex::Sentry aLock (myMutex);
1672         if (myToStop)
1673         {
1674           return;
1675         }
1676       }
1677       if (myTargetFps > 0.0)
1678       {
1679         const Standard_Real aTimeNew  = aTimer.ElapsedTime();
1680         const Standard_Real aDuration = aTimeNew - aTimeOld;
1681         if (aDuration >= aTargetDur)
1682         {
1683           myWindow->InvalidateContent (aDisp);
1684           aTimeOld = aTimeNew;
1685         }
1686       }
1687       else
1688       {
1689         myWindow->InvalidateContent (aDisp);
1690       }
1691
1692       OSD::MilliSecSleep (1);
1693     }
1694   }
1695
1696   //! Thread creation callback.
1697   static Standard_Address doThreadWrapper (Standard_Address theData)
1698   {
1699     ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1700     aThis->doThreadLoop();
1701     return 0;
1702   }
1703
1704   //! Empty constructor.
1705   ViewerTest_ContinuousRedrawer()
1706   : myThread (doThreadWrapper),
1707     myTargetFps (0.0),
1708     myToStop (false) {}
1709
1710 private:
1711   Handle(Aspect_Window) myWindow;
1712   OSD_Thread      myThread;
1713   Standard_Mutex  myMutex;
1714   Standard_Real   myTargetFps;
1715   volatile bool   myToStop;
1716 };
1717
1718 //==============================================================================
1719 //function : ViewerInit
1720 //purpose  : Create the window viewer and initialize all the global variable
1721 //==============================================================================
1722
1723 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1724                                                 const Standard_Integer thePxTop,
1725                                                 const Standard_Integer thePxWidth,
1726                                                 const Standard_Integer thePxHeight,
1727                                                 const TCollection_AsciiString& theViewName,
1728                                                 const TCollection_AsciiString& theDisplayName,
1729                                                 const Handle(V3d_View)& theViewToClone)
1730 {
1731   // Default position and dimension of the viewer window.
1732   // Note that left top corner is set to be sufficiently small to have
1733   // window fit in the small screens (actual for remote desktops, see #23003).
1734   // The position corresponds to the window's client area, thus some
1735   // gap is added for window frame to be visible.
1736   Standard_Integer aPxLeft   = 20;
1737   Standard_Integer aPxTop    = 40;
1738   Standard_Integer aPxWidth  = 409;
1739   Standard_Integer aPxHeight = 409;
1740   Standard_Boolean toCreateViewer = Standard_False;
1741   if (!theViewToClone.IsNull())
1742   {
1743     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1744   }
1745
1746   Handle(OpenGl_GraphicDriver) aGraphicDriver;
1747   ViewerTest_Names aViewNames(theViewName);
1748   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1749     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1750
1751   if (thePxLeft != 0)
1752     aPxLeft = thePxLeft;
1753   if (thePxTop != 0)
1754     aPxTop = thePxTop;
1755   if (thePxWidth != 0)
1756     aPxWidth = thePxWidth;
1757   if (thePxHeight != 0)
1758     aPxHeight = thePxHeight;
1759
1760   // Get graphic driver (create it or get from another view)
1761   const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1762   if (isNewDriver)
1763   {
1764     // Get connection string
1765   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1766     if (!theDisplayName.IsEmpty())
1767     {
1768       SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1769     }
1770     else
1771     {
1772       ::Display* aDispX = NULL;
1773       // create dedicated display connection instead of reusing Tk connection
1774       // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
1775       /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
1776       Tcl_Interp* aTclInterp = aCommands.Interp();
1777       Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
1778       aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
1779       SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
1780     }
1781   #else
1782     (void)theDisplayName; // avoid warning on unused argument
1783     SetDisplayConnection (new Aspect_DisplayConnection ());
1784   #endif
1785
1786     if (Draw_VirtualWindows)
1787     {
1788       // don't waste the time waiting for VSync when window is not displayed on the screen
1789       ViewerTest_myDefaultCaps.swapInterval = 0;
1790       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
1791       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
1792     }
1793     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
1794     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
1795
1796     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1797     toCreateViewer = Standard_True;
1798   }
1799   else
1800   {
1801     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
1802   }
1803
1804   //Dispose the window if input parameters are default
1805   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
1806   {
1807     Standard_Integer aTop = 0,
1808                      aLeft = 0,
1809                      aRight = 0,
1810                      aBottom = 0,
1811                      aScreenWidth = 0,
1812                      aScreenHeight = 0;
1813
1814     // Get screen resolution
1815 #if defined(_WIN32) || defined(__WIN32__)
1816     RECT aWindowSize;
1817     GetClientRect(GetDesktopWindow(), &aWindowSize);
1818     aScreenHeight = aWindowSize.bottom;
1819     aScreenWidth = aWindowSize.right;
1820 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1821     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1822 #else
1823     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1824     aScreenWidth = WidthOfScreen(aScreen);
1825     aScreenHeight = HeightOfScreen(aScreen);
1826 #endif
1827
1828     TCollection_AsciiString anOverlappedViewId("");
1829
1830     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
1831     {
1832       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1833
1834       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1835         && aRight + 2*aPxWidth + 40 > aScreenWidth)
1836       {
1837         if (aBottom + aPxHeight + 40 > aScreenHeight)
1838         {
1839           aPxLeft = 20;
1840           aPxTop = 40;
1841           break;
1842         }
1843         aPxLeft = 20;
1844         aPxTop = aBottom + 40;
1845       }
1846       else
1847         aPxLeft = aRight + 20;
1848     }
1849   }
1850
1851   // Get viewer name
1852   TCollection_AsciiString aTitle("3D View - ");
1853   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1854
1855   // Change name of current active window
1856   if (!ViewerTest::CurrentView().IsNull())
1857   {
1858     TCollection_AsciiString anActiveWindowTitle("3D View - ");
1859     anActiveWindowTitle = anActiveWindowTitle
1860       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1861     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
1862   }
1863
1864   // Create viewer
1865   Handle(V3d_Viewer) a3DViewer;
1866   // If it's the single view, we first look for empty context
1867   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1868   {
1869     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1870       anIter(ViewerTest_myContexts);
1871     if (anIter.More())
1872       ViewerTest::SetAISContext (anIter.Value());
1873     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1874   }
1875   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1876   {
1877     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1878     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1879   }
1880   else if (a3DViewer.IsNull())
1881   {
1882     toCreateViewer = Standard_True;
1883     a3DViewer = new V3d_Viewer(aGraphicDriver);
1884     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1885     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1886                                            ViewerTest_DefaultBackground.GradientColor2,
1887                                            ViewerTest_DefaultBackground.FillMethod);
1888   }
1889
1890   // AIS context setup
1891   if (ViewerTest::GetAISContext().IsNull() ||
1892       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1893   {
1894     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
1895     ViewerTest::SetAISContext (aContext);
1896     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1897   }
1898   else
1899   {
1900     ViewerTest::ResetEventManager();
1901   }
1902
1903   // Create window
1904 #if defined(_WIN32)
1905   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
1906                                     Handle(WNT_WClass)::DownCast (WClass()),
1907                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
1908                                     aPxLeft, aPxTop,
1909                                     aPxWidth, aPxHeight,
1910                                     Quantity_NOC_BLACK);
1911 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1912   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1913                                      aPxLeft, aPxTop,
1914                                      aPxWidth, aPxHeight);
1915   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
1916 #else
1917   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1918                                   aTitle.ToCString(),
1919                                   aPxLeft, aPxTop,
1920                                   aPxWidth, aPxHeight);
1921 #endif
1922   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
1923
1924   // View setup
1925   Handle(V3d_View) aView;
1926   if (!theViewToClone.IsNull())
1927   {
1928     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
1929   }
1930   else
1931   {
1932     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
1933   }
1934
1935   aView->SetWindow (VT_GetWindow());
1936   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
1937
1938   ViewerTest::CurrentView(aView);
1939   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
1940
1941   // Setup for X11 or NT
1942   OSWindowSetup();
1943
1944   // Set parameters for V3d_View and V3d_Viewer
1945   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1946   aV3dView->SetComputedMode(Standard_False);
1947
1948   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1949   if (toCreateViewer)
1950   {
1951     a3DViewer->SetDefaultLights();
1952     a3DViewer->SetLightOn();
1953   }
1954
1955 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1956   if (isNewDriver)
1957   {
1958     ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1959     Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1960   }
1961 #endif
1962
1963   VT_GetWindow()->Map();
1964
1965   // Set the handle of created view in the event manager
1966   ViewerTest::ResetEventManager();
1967
1968   ViewerTest::CurrentView()->Redraw();
1969
1970   aView.Nullify();
1971   a3DViewer.Nullify();
1972
1973   return aViewNames.GetViewName();
1974 }
1975
1976 //==============================================================================
1977 //function : RedrawAllViews
1978 //purpose  : Redraw all created views
1979 //==============================================================================
1980 void ViewerTest::RedrawAllViews()
1981 {
1982   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
1983   for (; aViewIt.More(); aViewIt.Next())
1984   {
1985     const Handle(V3d_View)& aView = aViewIt.Key2();
1986     aView->Redraw();
1987   }
1988 }
1989
1990 //==============================================================================
1991 //function : Vinit
1992 //purpose  : Create the window viewer and initialize all the global variable
1993 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
1994 //==============================================================================
1995
1996 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1997 {
1998   TCollection_AsciiString aViewName, aDisplayName;
1999   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
2000   Handle(V3d_View) aCopyFrom;
2001   TCollection_AsciiString aName, aValue;
2002   int is2dMode = -1;
2003   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
2004   {
2005     const TCollection_AsciiString anArg = theArgVec[anArgIt];
2006     TCollection_AsciiString anArgCase = anArg;
2007     anArgCase.LowerCase();
2008     if (anArgIt + 1 < theArgsNb
2009      && anArgCase == "-name")
2010     {
2011       aViewName = theArgVec[++anArgIt];
2012     }
2013     else if (anArgIt + 1 < theArgsNb
2014           && (anArgCase == "-left"
2015            || anArgCase == "-l"))
2016     {
2017       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2018     }
2019     else if (anArgIt + 1 < theArgsNb
2020           && (anArgCase == "-top"
2021            || anArgCase == "-t"))
2022     {
2023       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2024     }
2025     else if (anArgIt + 1 < theArgsNb
2026           && (anArgCase == "-width"
2027            || anArgCase == "-w"))
2028     {
2029       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2030     }
2031     else if (anArgIt + 1 < theArgsNb
2032           && (anArgCase == "-height"
2033            || anArgCase == "-h"))
2034     {
2035       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2036     }
2037     else if (anArgCase == "-exitonclose")
2038     {
2039       Draw_ToExitOnCloseView = true;
2040       if (anArgIt + 1 < theArgsNb
2041        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
2042       {
2043         ++anArgIt;
2044       }
2045     }
2046     else if (anArgCase == "-closeonescape"
2047           || anArgCase == "-closeonesc")
2048     {
2049       Draw_ToCloseViewOnEsc = true;
2050       if (anArgIt + 1 < theArgsNb
2051        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
2052       {
2053         ++anArgIt;
2054       }
2055     }
2056     else if (anArgCase == "-2d_mode"
2057           || anArgCase == "-2dmode"
2058           || anArgCase == "-2d")
2059     {
2060       bool toEnable = true;
2061       if (anArgIt + 1 < theArgsNb
2062        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2063       {
2064         ++anArgIt;
2065       }
2066       is2dMode = toEnable ? 1 : 0;
2067     }
2068     else if (anArgIt + 1 < theArgsNb
2069           && (anArgCase == "-disp"
2070            || anArgCase == "-display"))
2071     {
2072       aDisplayName = theArgVec[++anArgIt];
2073     }
2074     else if (!ViewerTest::CurrentView().IsNull()
2075           &&  aCopyFrom.IsNull()
2076           && (anArgCase == "-copy"
2077            || anArgCase == "-clone"
2078            || anArgCase == "-cloneactive"
2079            || anArgCase == "-cloneactiveview"))
2080     {
2081       aCopyFrom = ViewerTest::CurrentView();
2082     }
2083     // old syntax
2084     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2085     {
2086       aName.LowerCase();
2087       if (aName == "name")
2088       {
2089         aViewName = aValue;
2090       }
2091       else if (aName == "l"
2092             || aName == "left")
2093       {
2094         aPxLeft = aValue.IntegerValue();
2095       }
2096       else if (aName == "t"
2097             || aName == "top")
2098       {
2099         aPxTop = aValue.IntegerValue();
2100       }
2101       else if (aName == "disp"
2102             || aName == "display")
2103       {
2104         aDisplayName = aValue;
2105       }
2106       else if (aName == "w"
2107             || aName == "width")
2108       {
2109         aPxWidth = aValue.IntegerValue();
2110       }
2111       else if (aName == "h"
2112             || aName == "height")
2113       {
2114         aPxHeight = aValue.IntegerValue();
2115       }
2116       else
2117       {
2118         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2119         return 1;
2120       }
2121     }
2122     else if (aViewName.IsEmpty())
2123     {
2124       aViewName = anArg;
2125     }
2126     else
2127     {
2128       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2129       return 1;
2130     }
2131   }
2132
2133 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2134   if (!aDisplayName.IsEmpty())
2135   {
2136     aDisplayName.Clear();
2137     std::cout << "Warning: display parameter will be ignored.\n";
2138   }
2139 #endif
2140
2141   ViewerTest_Names aViewNames (aViewName);
2142   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
2143   {
2144     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2145     theDi.Eval (aCommand.ToCString());
2146     if (is2dMode != -1)
2147     {
2148       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2149     }
2150     return 0;
2151   }
2152
2153   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
2154                                                             aViewName, aDisplayName, aCopyFrom);
2155   if (is2dMode != -1)
2156   {
2157     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2158   }
2159   theDi << aViewId;
2160   return 0;
2161 }
2162
2163 //! Parse HLR algo type.
2164 static Standard_Boolean parseHlrAlgoType (const char* theName,
2165                                           Prs3d_TypeOfHLR& theType)
2166 {
2167   TCollection_AsciiString aName (theName);
2168   aName.LowerCase();
2169   if (aName == "polyalgo")
2170   {
2171     theType = Prs3d_TOH_PolyAlgo;
2172   }
2173   else if (aName == "algo")
2174   {
2175     theType = Prs3d_TOH_Algo;
2176   }
2177   else
2178   {
2179     return Standard_False;
2180   }
2181   return Standard_True;
2182 }
2183
2184 //==============================================================================
2185 //function : VHLR
2186 //purpose  : hidden lines removal algorithm
2187 //==============================================================================
2188
2189 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2190 {
2191   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2192   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2193   if (aView.IsNull())
2194   {
2195     std::cerr << "Error: No opened viewer!\n";
2196     return 1;
2197   }
2198
2199   Standard_Boolean hasHlrOnArg = Standard_False;
2200   Standard_Boolean hasShowHiddenArg = Standard_False;
2201   Standard_Boolean isHLROn = Standard_False;
2202   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2203   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
2204   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2205   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2206   {
2207     TCollection_AsciiString anArg (argv[anArgIter]);
2208     anArg.LowerCase();
2209     if (anUpdateTool.parseRedrawMode (anArg))
2210     {
2211       continue;
2212     }
2213     else if (anArg == "-showhidden"
2214           && anArgIter + 1 < argc
2215           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2216     {
2217       ++anArgIter;
2218       hasShowHiddenArg = Standard_True;
2219       continue;
2220     }
2221     else if ((anArg == "-type"
2222            || anArg == "-algo"
2223            || anArg == "-algotype")
2224           && anArgIter + 1 < argc
2225           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2226     {
2227       ++anArgIter;
2228       continue;
2229     }
2230     else if (!hasHlrOnArg
2231           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2232     {
2233       hasHlrOnArg = Standard_True;
2234       continue;
2235     }
2236     // old syntax
2237     else if (!hasShowHiddenArg
2238           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2239     {
2240       hasShowHiddenArg = Standard_True;
2241       continue;
2242     }
2243     else
2244     {
2245       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2246       return 1;
2247     }
2248   }
2249   if (!hasHlrOnArg)
2250   {
2251     di << "HLR:        " << aView->ComputedMode() << "\n";
2252     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2253     di << "HlrAlgo:    ";
2254     switch (aCtx->DefaultDrawer()->TypeOfHLR())
2255     {
2256       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
2257       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2258       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
2259     }
2260     anUpdateTool.Invalidate();
2261     return 0;
2262   }
2263
2264   Standard_Boolean toRecompute = Standard_False;
2265   if (aTypeOfHLR != Prs3d_TOH_NotSet
2266    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
2267   {
2268     toRecompute = Standard_True;
2269     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2270   }
2271   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2272   {
2273     toRecompute = Standard_True;
2274     if (toShowHidden)
2275     {
2276       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
2277     }
2278     else
2279     {
2280       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
2281     }
2282   }
2283
2284   // redisplay shapes
2285   if (aView->ComputedMode() && isHLROn && toRecompute)
2286   {
2287     AIS_ListOfInteractive aListOfShapes;
2288     aCtx->DisplayedObjects (aListOfShapes);
2289     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
2290     {
2291       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
2292       {
2293         aCtx->Redisplay (aShape, Standard_False);
2294       }
2295     }
2296   }
2297
2298   aView->SetComputedMode (isHLROn);
2299   return 0;
2300 }
2301
2302 //==============================================================================
2303 //function : VHLRType
2304 //purpose  : change type of using HLR algorithm
2305 //==============================================================================
2306
2307 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
2308 {
2309   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2310   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2311   if (aView.IsNull())
2312   {
2313     std::cerr << "Error: No opened viewer!\n";
2314     return 1;
2315   }
2316
2317   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2318   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2319   AIS_ListOfInteractive aListOfShapes;
2320   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2321   {
2322     TCollection_AsciiString anArg (argv[anArgIter]);
2323     anArg.LowerCase();
2324     if (anUpdateTool.parseRedrawMode (anArg))
2325     {
2326       continue;
2327     }
2328     else if ((anArg == "-type"
2329            || anArg == "-algo"
2330            || anArg == "-algotype")
2331           && anArgIter + 1 < argc
2332           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2333     {
2334       ++anArgIter;
2335       continue;
2336     }
2337     // old syntax
2338     else if (aTypeOfHLR == Prs3d_TOH_NotSet
2339           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2340     {
2341       continue;
2342     }
2343     else
2344     {
2345       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
2346       TCollection_AsciiString aName (argv[anArgIter]);
2347       if (!aMap.IsBound2 (aName))
2348       {
2349         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2350         return 1;
2351       }
2352
2353       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2354       if (aShape.IsNull())
2355       {
2356         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2357         return 1;
2358       }
2359       aListOfShapes.Append (aShape);
2360       continue;
2361     }
2362   }
2363   if (aTypeOfHLR == Prs3d_TOH_NotSet)
2364   {
2365     std::cout << "Syntax error: wrong number of arguments!\n";
2366     return 1;
2367   }
2368
2369   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2370   if (isGlobal)
2371   {
2372     aCtx->DisplayedObjects (aListOfShapes);
2373     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2374   }
2375
2376   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2377   {
2378     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2379     if (aShape.IsNull())
2380     {
2381       continue;
2382     }
2383
2384     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2385                             && aView->ComputedMode();
2386     if (!isGlobal
2387      || aShape->TypeOfHLR() != aTypeOfHLR)
2388     {
2389       aShape->SetTypeOfHLR (aTypeOfHLR);
2390     }
2391     if (toUpdateShape)
2392     {
2393       aCtx->Redisplay (aShape, Standard_False);
2394     }
2395   }
2396   return 0;
2397 }
2398
2399 //==============================================================================
2400 //function : FindViewIdByWindowHandle
2401 //purpose  : Find theView Id in the map of views by window handle
2402 //==============================================================================
2403 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2404 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
2405 {
2406   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2407        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2408   {
2409     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
2410     if (aWindowHandle == theWindowHandle)
2411       return anIter.Key1();
2412   }
2413   return TCollection_AsciiString("");
2414 }
2415 #endif
2416
2417 //! Make the view active
2418 void ActivateView (const TCollection_AsciiString& theViewName,
2419                    Standard_Boolean theToUpdate = Standard_True)
2420 {
2421   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2422   if (aView.IsNull())
2423   {
2424     return;
2425   }
2426
2427   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2428   if (!anAISContext.IsNull())
2429   {
2430     if (!ViewerTest::CurrentView().IsNull())
2431     {
2432       TCollection_AsciiString aTitle("3D View - ");
2433       aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
2434       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
2435     }
2436
2437     ViewerTest::CurrentView (aView);
2438     ViewerTest::SetAISContext (anAISContext);
2439     TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
2440     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
2441 #if defined(_WIN32)
2442     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
2443 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
2444     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
2445 #else
2446     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
2447 #endif
2448     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2449     if (theToUpdate)
2450     {
2451       ViewerTest::CurrentView()->Redraw();
2452     }
2453   }
2454 }
2455
2456 //==============================================================================
2457 //function : RemoveView
2458 //purpose  :
2459 //==============================================================================
2460 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2461                              const Standard_Boolean  theToRemoveContext)
2462 {
2463   if (!ViewerTest_myViews.IsBound2 (theView))
2464   {
2465     return;
2466   }
2467
2468   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2469   RemoveView (aViewName, theToRemoveContext);
2470 }
2471
2472 //==============================================================================
2473 //function : RemoveView
2474 //purpose  : Close and remove view from display, clear maps if neccessary
2475 //==============================================================================
2476 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2477 {
2478   if (!ViewerTest_myViews.IsBound1(theViewName))
2479   {
2480     cout << "Wrong view name\n";
2481     return;
2482   }
2483
2484   // Activate another view if it's active now
2485   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2486   {
2487     if (ViewerTest_myViews.Extent() > 1)
2488     {
2489       TCollection_AsciiString aNewViewName;
2490       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2491            anIter.More(); anIter.Next())
2492       {
2493         if (anIter.Key1() != theViewName)
2494         {
2495           aNewViewName = anIter.Key1();
2496           break;
2497         }
2498       }
2499       ActivateView (aNewViewName);
2500     }
2501     else
2502     {
2503       VT_GetWindow().Nullify();
2504       ViewerTest::CurrentView (Handle(V3d_View)());
2505       if (isContextRemoved)
2506       {
2507         Handle(AIS_InteractiveContext) anEmptyContext;
2508         ViewerTest::SetAISContext(anEmptyContext);
2509       }
2510     }
2511   }
2512
2513   // Delete view
2514   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2515   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
2516   ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2517   aRedrawer.Stop (aView->Window());
2518
2519   // Remove view resources
2520   ViewerTest_myViews.UnBind1(theViewName);
2521   aView->Window()->Unmap();
2522   aView->Remove();
2523
2524 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2525   XFlush (GetDisplayConnection()->GetDisplay());
2526 #endif
2527
2528   // Keep context opened only if the closed view is last to avoid
2529   // unused empty contexts
2530   if (!aCurrentContext.IsNull())
2531   {
2532     // Check if there are more difined views in the viewer
2533     aCurrentContext->CurrentViewer()->InitDefinedViews();
2534     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
2535     {
2536       // Remove driver if there is no viewers that use it
2537       Standard_Boolean isRemoveDriver = Standard_True;
2538       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2539           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2540       {
2541         if (aCurrentContext != anIter.Key2() &&
2542           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2543         {
2544           isRemoveDriver = Standard_False;
2545           break;
2546         }
2547       }
2548
2549       aCurrentContext->RemoveAll (Standard_False);
2550       if(isRemoveDriver)
2551       {
2552         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2553       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2554         Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
2555       #endif
2556       }
2557
2558       ViewerTest_myContexts.UnBind2(aCurrentContext);
2559     }
2560   }
2561   cout << "3D View - " << theViewName << " was deleted.\n";
2562   if (Draw_ToExitOnCloseView)
2563   {
2564     Draw_Interprete ("exit");
2565   }
2566 }
2567
2568 //==============================================================================
2569 //function : VClose
2570 //purpose  : Remove the view defined by its name
2571 //==============================================================================
2572
2573 static int VClose (Draw_Interpretor& /*theDi*/,
2574                    Standard_Integer  theArgsNb,
2575                    const char**      theArgVec)
2576 {
2577   NCollection_List<TCollection_AsciiString> aViewList;
2578   if (theArgsNb > 1)
2579   {
2580     TCollection_AsciiString anArg (theArgVec[1]);
2581     anArg.UpperCase();
2582     if (anArg.IsEqual ("ALL")
2583      || anArg.IsEqual ("*"))
2584     {
2585       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2586            anIter.More(); anIter.Next())
2587       {
2588         aViewList.Append (anIter.Key1());
2589       }
2590       if (aViewList.IsEmpty())
2591       {
2592         std::cout << "No view to close\n";
2593         return 0;
2594       }
2595     }
2596     else
2597     {
2598       ViewerTest_Names aViewName (theArgVec[1]);
2599       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2600       {
2601         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2602         return 1;
2603       }
2604       aViewList.Append (aViewName.GetViewName());
2605     }
2606   }
2607   else
2608   {
2609     // close active view
2610     if (ViewerTest::CurrentView().IsNull())
2611     {
2612       std::cerr << "No active view!\n";
2613       return 1;
2614     }
2615     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2616   }
2617
2618   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
2619   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2620        anIter.More(); anIter.Next())
2621   {
2622     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
2623   }
2624
2625   return 0;
2626 }
2627
2628 //==============================================================================
2629 //function : VActivate
2630 //purpose  : Activate the view defined by its ID
2631 //==============================================================================
2632
2633 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2634 {
2635   if (theArgsNb == 1)
2636   {
2637     theDi.Eval("vviewlist");
2638     return 0;
2639   }
2640
2641   TCollection_AsciiString aNameString;
2642   Standard_Boolean toUpdate = Standard_True;
2643   Standard_Boolean toActivate = Standard_True;
2644   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
2645   {
2646     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2647     anArg.LowerCase();
2648     if (toUpdate
2649      && anArg == "-noupdate")
2650     {
2651       toUpdate = Standard_False;
2652     }
2653     else if (toActivate
2654           && aNameString.IsEmpty()
2655           && anArg == "none")
2656     {
2657       TCollection_AsciiString aTitle("3D View - ");
2658       aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
2659       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
2660       VT_GetWindow().Nullify();
2661       ViewerTest::CurrentView (Handle(V3d_View)());
2662       ViewerTest::ResetEventManager();
2663       theDi << theArgVec[0] << ": all views are inactive\n";
2664       toActivate = Standard_False;
2665     }
2666     else if (toActivate
2667           && aNameString.IsEmpty())
2668     {
2669       aNameString = theArgVec[anArgIter];
2670     }
2671     else
2672     {
2673       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2674       return 1;
2675     }
2676   }
2677
2678   if (!toActivate)
2679   {
2680     return 0;
2681   }
2682   else if (aNameString.IsEmpty())
2683   {
2684     std::cout << "Syntax error: wrong number of arguments\n";
2685     return 1;
2686   }
2687
2688   // Check if this view exists in the viewer with the driver
2689   ViewerTest_Names aViewNames (aNameString);
2690   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2691   {
2692     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
2693     return 1;
2694   }
2695
2696   // Check if it is active already
2697   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2698   {
2699     theDi << theArgVec[0] << ": the view is active already\n";
2700     return 0;
2701   }
2702
2703   ActivateView (aViewNames.GetViewName(), toUpdate);
2704   return 0;
2705 }
2706
2707 //==============================================================================
2708 //function : VViewList
2709 //purpose  : Print current list of views per viewer and graphic driver ID
2710 //           shared between viewers
2711 //==============================================================================
2712
2713 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2714 {
2715   if (theArgsNb > 2)
2716   {
2717     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
2718           << "Usage: " << theArgVec[0] << " name";
2719     return 1;
2720   }
2721   if (ViewerTest_myContexts.Size() < 1)
2722     return 0;
2723
2724   Standard_Boolean isTreeView =
2725     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
2726
2727   if (isTreeView)
2728   {
2729     theDi << theArgVec[0] <<":\n";
2730   }
2731
2732   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2733        aDriverIter.More(); aDriverIter.Next())
2734   {
2735     if (isTreeView)
2736       theDi << aDriverIter.Key1() << ":\n";
2737
2738     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2739       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2740     {
2741       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
2742       {
2743         if (isTreeView)
2744         {
2745           TCollection_AsciiString aContextName(aContextIter.Key1());
2746           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2747         }
2748
2749         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2750              aViewIter.More(); aViewIter.Next())
2751         {
2752           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
2753           {
2754             TCollection_AsciiString aViewName(aViewIter.Key1());
2755             if (isTreeView)
2756             {
2757               if (aViewIter.Value() == ViewerTest::CurrentView())
2758                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
2759               else
2760                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2761             }
2762             else
2763             {
2764               theDi << aViewName << " ";
2765             }
2766           }
2767         }
2768       }
2769     }
2770   }
2771   return 0;
2772 }
2773
2774 //==============================================================================
2775 //function : VT_ProcessKeyPress
2776 //purpose  : Handle KeyPress event from a CString
2777 //==============================================================================
2778 void VT_ProcessKeyPress (const char* buf_ret)
2779 {
2780   //cout << "KeyPress" << endl;
2781   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2782   // Letter in alphabetic order
2783
2784   if (!strcasecmp (buf_ret, "A")
2785    && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2786   {
2787     // AXO
2788     aView->SetProj(V3d_XposYnegZpos);
2789   }
2790   else if (!strcasecmp (buf_ret, "D")
2791         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2792   {
2793     // Reset
2794     aView->Reset();
2795   }
2796   else if (!strcasecmp (buf_ret, "F"))
2797   {
2798     if (ViewerTest::GetAISContext()->NbSelected() > 0)
2799     {
2800       ViewerTest::GetAISContext()->FitSelected (aView);
2801     }
2802     else
2803     {
2804       // FitAll
2805       aView->FitAll();
2806     }
2807   }
2808   else if (!strcasecmp (buf_ret, "H"))
2809   {
2810     // HLR
2811     std::cout << "HLR" << std::endl;
2812     aView->SetComputedMode (!aView->ComputedMode());
2813     aView->Redraw();
2814   }
2815   else if (!strcasecmp (buf_ret, "P"))
2816   {
2817     // Type of HLR
2818     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
2819     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
2820       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
2821     else
2822       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
2823     if (aContext->NbSelected()==0)
2824     {
2825       AIS_ListOfInteractive aListOfShapes;
2826       aContext->DisplayedObjects(aListOfShapes);
2827       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
2828         anIter.More(); anIter.Next())
2829       {
2830         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2831         if (aShape.IsNull())
2832           continue;
2833         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
2834           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
2835         else
2836           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
2837         aContext->Redisplay (aShape, Standard_False);
2838       }
2839     }
2840     else
2841     {
2842       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
2843       {
2844         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
2845         if (aShape.IsNull())
2846           continue;
2847         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
2848           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
2849         else
2850           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
2851         aContext->Redisplay (aShape, Standard_False);
2852       }
2853     }
2854
2855     aContext->UpdateCurrentViewer();
2856
2857   }
2858   else if (!strcasecmp (buf_ret, "S"))
2859   {
2860     std::cout << "setup Shaded display mode" << std::endl;
2861
2862     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
2863     if(Ctx->NbSelected()==0)
2864       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
2865     else{
2866       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
2867         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
2868       Ctx->UpdateCurrentViewer();
2869     }
2870   }
2871   else if (!strcasecmp (buf_ret, "U"))
2872   {
2873     // Unset display mode
2874     std::cout << "reset display mode to defaults" << std::endl;
2875
2876     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
2877     if(Ctx->NbSelected()==0)
2878       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
2879     else{
2880       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
2881         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
2882       Ctx->UpdateCurrentViewer();
2883     }
2884
2885   }
2886   else if (!strcasecmp (buf_ret, "T")
2887         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2888   {
2889     // Top
2890     aView->SetProj(V3d_Zpos);
2891   }
2892   else if (!strcasecmp (buf_ret, "B")
2893         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2894   {
2895     // Bottom
2896     aView->SetProj(V3d_Zneg);
2897   }
2898   else if (!strcasecmp (buf_ret, "L")
2899         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2900   {
2901     // Left
2902     aView->SetProj(V3d_Xneg);
2903   }
2904   else if (!strcasecmp (buf_ret, "R")
2905         && !ViewerTest_V3dView::IsCurrentViewIn2DMode())
2906   {
2907     // Right
2908     aView->SetProj(V3d_Xpos);
2909   }
2910   else if (!strcasecmp (buf_ret, "W"))
2911   {
2912     std::cout << "setup WireFrame display mode" << std::endl;
2913     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
2914     if(Ctx->NbSelected()==0)
2915       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
2916     else{
2917       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
2918         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
2919       Ctx->UpdateCurrentViewer();
2920     }
2921   }
2922   else if (!strcasecmp (buf_ret, ","))
2923   {
2924     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
2925   }
2926   else if (!strcasecmp (buf_ret, "."))
2927   {
2928     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
2929   }
2930   else if (!strcasecmp (buf_ret, "/"))
2931   {
2932     Handle(Graphic3d_Camera) aCamera = aView->Camera();
2933     if (aCamera->IsStereo())
2934     {
2935       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
2936       aView->Redraw();
2937     }
2938   }
2939   else if (!strcasecmp (buf_ret, "*"))
2940   {
2941     Handle(Graphic3d_Camera) aCamera = aView->Camera();
2942     if (aCamera->IsStereo())
2943     {
2944       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
2945       aView->Redraw();
2946     }
2947   }
2948   else if (*buf_ret == THE_KEY_DELETE)
2949   {
2950     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2951     if (!aCtx.IsNull()
2952      && aCtx->NbSelected() > 0)
2953     {
2954       Draw_Interprete ("verase");
2955     }
2956   }
2957   else if (*buf_ret == THE_KEY_ESCAPE)
2958   {
2959     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2960     if (!aCtx.IsNull()
2961      && Draw_ToCloseViewOnEsc)
2962     {
2963       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
2964     }
2965   }
2966   else if (*buf_ret >= '0' && *buf_ret <= '7') // Number
2967   {
2968     const Standard_Integer aSelMode = Draw::Atoi (buf_ret);
2969     bool toEnable = true;
2970     if (const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext())
2971     {
2972       AIS_ListOfInteractive aPrsList;
2973       aCtx->DisplayedObjects (aPrsList);
2974       for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
2975       {
2976         TColStd_ListOfInteger aModes;
2977         aCtx->ActivatedModes (aPrsIter.Value(), aModes);
2978         for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
2979         {
2980           if (aModeIter.Value() == aSelMode)
2981           {
2982             toEnable = false;
2983           }
2984         }
2985       }
2986     }
2987     TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
2988     Draw_Interprete (aCmd.ToCString());
2989   }
2990 }
2991
2992 //==============================================================================
2993 //function : VT_ProcessExpose
2994 //purpose  : Redraw the View on an Expose Event
2995 //==============================================================================
2996 void VT_ProcessExpose()
2997 {
2998   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
2999   if (!aView3d.IsNull())
3000   {
3001     aView3d->Redraw();
3002   }
3003 }
3004
3005 //==============================================================================
3006 //function : VT_ProcessConfigure
3007 //purpose  : Resize the View on an Configure Event
3008 //==============================================================================
3009 void VT_ProcessConfigure()
3010 {
3011   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
3012   if (aView3d.IsNull())
3013   {
3014     return;
3015   }
3016
3017   aView3d->MustBeResized();
3018   aView3d->Update();
3019   aView3d->Redraw();
3020 }
3021
3022 //==============================================================================
3023 //function : VT_ProcessButton1Press
3024 //purpose  : Picking
3025 //==============================================================================
3026 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
3027                                          const char**     theArgVec,
3028                                          Standard_Boolean theToPick,
3029                                          Standard_Boolean theIsShift)
3030 {
3031   if (TheIsAnimating)
3032   {
3033     TheIsAnimating = Standard_False;
3034     return Standard_False;
3035   }
3036
3037   if (theToPick)
3038   {
3039     Standard_Real X, Y, Z;
3040     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
3041
3042     Draw::Set (theArgVec[1], X);
3043     Draw::Set (theArgVec[2], Y);
3044     Draw::Set (theArgVec[3], Z);
3045   }
3046
3047   if (theIsShift)
3048   {
3049     ViewerTest::CurrentEventManager()->ShiftSelect();
3050   }
3051   else
3052   {
3053     ViewerTest::CurrentEventManager()->Select();
3054   }
3055
3056   return Standard_False;
3057 }
3058
3059 //==============================================================================
3060 //function : VT_ProcessButton1Release
3061 //purpose  : End selecting
3062 //==============================================================================
3063 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
3064 {
3065   if (IsDragged)
3066   {
3067     IsDragged = Standard_False;
3068     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
3069     if (theIsShift)
3070     {
3071       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
3072                        X_Motion, Y_Motion);
3073     }
3074     else
3075     {
3076       EM->Select (X_ButtonPress, Y_ButtonPress,
3077                   X_Motion, Y_Motion);
3078     }
3079   }
3080 }
3081
3082 //==============================================================================
3083 //function : VT_ProcessButton3Press
3084 //purpose  : Start Rotation
3085 //==============================================================================
3086 void VT_ProcessButton3Press()
3087 {
3088   if (ViewerTest_V3dView::IsCurrentViewIn2DMode())
3089   {
3090     return;
3091   }
3092
3093   Start_Rot = 1;
3094   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
3095   if (HasHlrOnBeforeRotation)
3096   {
3097     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
3098   }
3099   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
3100 }
3101
3102 //==============================================================================
3103 //function : VT_ProcessButton3Release
3104 //purpose  : End rotation
3105 //==============================================================================
3106 void VT_ProcessButton3Release()
3107 {
3108   if (Start_Rot)
3109   {
3110     Start_Rot = 0;
3111     if (HasHlrOnBeforeRotation)
3112     {
3113       HasHlrOnBeforeRotation = Standard_False;
3114       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
3115       ViewerTest::CurrentView()->Redraw();
3116     }
3117   }
3118 }
3119
3120 //==============================================================================
3121 //function : ProcessControlButton1Motion
3122 //purpose  : Zoom
3123 //==============================================================================
3124
3125 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
3126 static void ProcessControlButton1Motion()
3127 {
3128   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
3129
3130   X_ButtonPress = X_Motion;
3131   Y_ButtonPress = Y_Motion;
3132 }
3133 #endif
3134
3135 //==============================================================================
3136 //function : VT_ProcessControlButton2Motion
3137 //purpose  : Panning
3138 //==============================================================================
3139 void VT_ProcessControlButton2Motion()
3140 {
3141   Standard_Integer aDx = X_Motion - X_ButtonPress;
3142   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
3143
3144   aDy = -aDy; // Xwindow Y axis is from top to Bottom
3145
3146   ViewerTest::CurrentView()->Pan (aDx, aDy);
3147
3148   X_ButtonPress = X_Motion;
3149   Y_ButtonPress = Y_Motion;
3150 }
3151
3152 //==============================================================================
3153 //function : VT_ProcessControlButton3Motion
3154 //purpose  : Rotation
3155 //==============================================================================
3156 void VT_ProcessControlButton3Motion()
3157 {
3158   if (Start_Rot)
3159   {
3160     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
3161   }
3162 }
3163
3164 //==============================================================================
3165 //function : VT_ProcessMotion
3166 //purpose  :
3167 //==============================================================================
3168 void VT_ProcessMotion()
3169 {
3170   //pre-hilights detected objects at mouse position
3171
3172   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
3173   EM->MoveTo(X_Motion, Y_Motion);
3174 }
3175
3176
3177 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
3178 {
3179   Xpix = X_Motion;Ypix=Y_Motion;
3180 }
3181
3182 //==============================================================================
3183 //function : VViewProj
3184 //purpose  : Switch view projection
3185 //==============================================================================
3186 static int VViewProj (Draw_Interpretor& ,
3187                       Standard_Integer theNbArgs,
3188                       const char** theArgVec)
3189 {
3190   static Standard_Boolean isYup = Standard_False;
3191   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3192   if (aView.IsNull())
3193   {
3194     std::cout << "Error: no active view\n";
3195     return 1;
3196   }
3197
3198   TCollection_AsciiString aCmdName (theArgVec[0]);
3199   Standard_Boolean isGeneralCmd = Standard_False;
3200   if (aCmdName == "vfront")
3201   {
3202     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
3203   }
3204   else if (aCmdName == "vback")
3205   {
3206     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
3207   }
3208   else if (aCmdName == "vtop")
3209   {
3210     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
3211   }
3212   else if (aCmdName == "vbottom")
3213   {
3214     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
3215   }
3216   else if (aCmdName == "vleft")
3217   {
3218     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
3219   }
3220   else if (aCmdName == "vright")
3221   {
3222     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
3223   }
3224   else if (aCmdName == "vaxo")
3225   {
3226     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
3227   }
3228   else
3229   {
3230     isGeneralCmd = Standard_True;
3231     for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
3232     {
3233       TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3234       anArgCase.LowerCase();
3235       if (anArgCase == "-zup")
3236       {
3237         isYup = Standard_False;
3238       }
3239       else if (anArgCase == "-yup")
3240       {
3241         isYup = Standard_True;
3242       }
3243       else if (anArgCase == "-front"
3244             || anArgCase == "front"
3245             || anArgCase == "-f"
3246             || anArgCase == "f")
3247       {
3248         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
3249       }
3250       else if (anArgCase == "-back"
3251             || anArgCase == "back"
3252             || anArgCase == "-b"
3253             || anArgCase == "b")
3254       {
3255         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
3256       }
3257       else if (anArgCase == "-top"
3258             || anArgCase == "top"
3259             || anArgCase == "-t"
3260             || anArgCase == "t")
3261       {
3262         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
3263       }
3264       else if (anArgCase == "-bottom"
3265             || anArgCase == "bottom"
3266             || anArgCase == "-bot"
3267             || anArgCase == "bot"
3268             || anArgCase == "-b"
3269             || anArgCase == "b")
3270       {
3271         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
3272       }
3273       else if (anArgCase == "-left"
3274             || anArgCase == "left"
3275             || anArgCase == "-l"
3276             || anArgCase == "l")
3277       {
3278         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
3279       }
3280       else if (anArgCase == "-right"
3281             || anArgCase == "right"
3282             || anArgCase == "-r"
3283             || anArgCase == "r")
3284       {
3285         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
3286       }
3287       else if (anArgCase == "-axoleft"
3288             || anArgCase == "-leftaxo"
3289             || anArgCase == "axoleft"
3290             || anArgCase == "leftaxo")
3291       {
3292         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
3293       }
3294       else if (anArgCase == "-axo"
3295             || anArgCase == "axo"
3296             || anArgCase == "-a"
3297             || anArgCase == "a"
3298             || anArgCase == "-axoright"
3299             || anArgCase == "-rightaxo"
3300             || anArgCase == "axoright"
3301             || anArgCase == "rightaxo")
3302       {
3303         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
3304       }
3305       else if (anArgCase == "+x")
3306       {
3307         aView->SetProj (V3d_Xpos, isYup);
3308       }
3309       else if (anArgCase == "-x")
3310       {
3311         aView->SetProj (V3d_Xneg, isYup);
3312       }
3313       else if (anArgCase == "+y")
3314       {
3315         aView->SetProj (V3d_Ypos, isYup);
3316       }
3317       else if (anArgCase == "-y")
3318       {
3319         aView->SetProj (V3d_Yneg, isYup);
3320       }
3321       else if (anArgCase == "+z")
3322       {
3323         aView->SetProj (V3d_Zpos, isYup);
3324       }
3325       else if (anArgCase == "-z")
3326       {
3327         aView->SetProj (V3d_Zneg, isYup);
3328       }
3329       else if (anArgCase == "+x+y+z")
3330       {
3331         aView->SetProj (V3d_XposYposZpos, isYup);
3332       }
3333       else if (anArgCase == "+x+y-z")
3334       {
3335         aView->SetProj (V3d_XposYposZneg, isYup);
3336       }
3337       else if (anArgCase == "+x-y+z")
3338       {
3339         aView->SetProj (V3d_XposYnegZpos, isYup);
3340       }
3341       else if (anArgCase == "+x-y-z")
3342       {
3343         aView->SetProj (V3d_XposYnegZneg, isYup);
3344       }
3345       else if (anArgCase == "-x+y+z")
3346       {
3347         aView->SetProj (V3d_XnegYposZpos, isYup);
3348       }
3349       else if (anArgCase == "-x+y-z")
3350       {
3351         aView->SetProj (V3d_XnegYposZneg, isYup);
3352       }
3353       else if (anArgCase == "-x-y+z")
3354       {
3355         aView->SetProj (V3d_XnegYnegZpos, isYup);
3356       }
3357       else if (anArgCase == "-x-y-z")
3358       {
3359         aView->SetProj (V3d_XnegYnegZneg, isYup);
3360       }
3361       else if (anArgCase == "+x+y")
3362       {
3363         aView->SetProj (V3d_XposYpos, isYup);
3364       }
3365       else if (anArgCase == "+x-y")
3366       {
3367         aView->SetProj (V3d_XposYneg, isYup);
3368       }
3369       else if (anArgCase == "-x+y")
3370       {
3371         aView->SetProj (V3d_XnegYpos, isYup);
3372       }
3373       else if (anArgCase == "-x-y")
3374       {
3375         aView->SetProj (V3d_XnegYneg, isYup);
3376       }
3377       else if (anArgCase == "+x+z")
3378       {
3379         aView->SetProj (V3d_XposZpos, isYup);
3380       }
3381       else if (anArgCase == "+x-z")
3382       {
3383         aView->SetProj (V3d_XposZneg, isYup);
3384       }
3385       else if (anArgCase == "-x+z")
3386       {
3387         aView->SetProj (V3d_XnegZpos, isYup);
3388       }
3389       else if (anArgCase == "-x-z")
3390       {
3391         aView->SetProj (V3d_XnegZneg, isYup);
3392       }
3393       else if (anArgCase == "+y+z")
3394       {
3395         aView->SetProj (V3d_YposZpos, isYup);
3396       }
3397       else if (anArgCase == "+y-z")
3398       {
3399         aView->SetProj (V3d_YposZneg, isYup);
3400       }
3401       else if (anArgCase == "-y+z")
3402       {
3403         aView->SetProj (V3d_YnegZpos, isYup);
3404       }
3405       else if (anArgCase == "-y-z")
3406       {
3407         aView->SetProj (V3d_YnegZneg, isYup);
3408       }
3409       else if (anArgIter + 1 < theNbArgs
3410             && anArgCase == "-frame"
3411             && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
3412       {
3413         TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
3414         aFrameDef.LowerCase();
3415         gp_Dir aRight, anUp;
3416         if (aFrameDef.Value (2) == aFrameDef.Value (4))
3417         {
3418           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3419           return 1;
3420         }
3421
3422         if (aFrameDef.Value (2) == 'x')
3423         {
3424           aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
3425         }
3426         else if (aFrameDef.Value (2) == 'y')
3427         {
3428           aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
3429         }
3430         else if (aFrameDef.Value (2) == 'z')
3431         {
3432           aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
3433         }
3434         else
3435         {
3436           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3437           return 1;
3438         }
3439
3440         if (aFrameDef.Value (4) == 'x')
3441         {
3442           anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
3443         }
3444         else if (aFrameDef.Value (4) == 'y')
3445         {
3446           anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
3447         }
3448         else if (aFrameDef.Value (4) == 'z')
3449         {
3450           anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
3451         }
3452         else
3453         {
3454           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3455           return 1;
3456         }
3457
3458         const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
3459         const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
3460         const gp_Dir aDir = anUp.Crossed (aRight);
3461         aCamera->SetCenter (gp_Pnt (0, 0, 0));
3462         aCamera->SetDirection (aDir);
3463         aCamera->SetUp (anUp);
3464         aCamera->OrthogonalizeUp();
3465
3466         aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
3467         aView->Update();
3468       }
3469       else
3470       {
3471         std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3472         return 1;
3473       }
3474     }
3475   }
3476
3477   if (!isGeneralCmd
3478     && theNbArgs != 1)
3479   {
3480     std::cout << "Syntax error: wrong number of arguments\n";
3481     return 1;
3482   }
3483   return 0;
3484 }
3485
3486 //==============================================================================
3487 //function : VHelp
3488 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
3489 //Draw arg : No args
3490 //==============================================================================
3491
3492 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3493 {
3494
3495   di << "Q : Quit the application\n";
3496
3497   di << "=========================\n";
3498   di << "F : FitAll\n";
3499   di << "T : TopView\n";
3500   di << "B : BottomView\n";
3501   di << "R : RightView\n";
3502   di << "L : LeftView\n";
3503   di << "A : AxonometricView\n";
3504   di << "D : ResetView\n";
3505
3506   di << "=========================\n";
3507   di << "S : Shading\n";
3508   di << "W : Wireframe\n";
3509   di << "H : HidelLineRemoval\n";
3510   di << "U : Unset display mode\n";
3511   di << "Delete : Remove selection from viewer\n";
3512
3513   di << "=========================\n";
3514   di << "Selection mode \n";
3515   di << "0 : Shape\n";
3516   di << "1 : Vertex\n";
3517   di << "2 : Edge\n";
3518   di << "3 : Wire\n";
3519   di << "4 : Face\n";
3520   di << "5 : Shell\n";
3521   di << "6 : Solid\n";
3522   di << "7 : Compound\n";
3523
3524   di << "=========================\n";
3525   di << "Z : Switch Z clipping On/Off\n";
3526   di << ", : Hilight next detected\n";
3527   di << ". : Hilight previous detected\n";
3528
3529   return 0;
3530 }
3531
3532 #ifdef _WIN32
3533
3534 static Standard_Boolean Ppick = 0;
3535 static Standard_Integer Pargc = 0;
3536 static const char**           Pargv = NULL;
3537
3538
3539 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
3540                                           UINT Msg,
3541                                           WPARAM wParam,
3542                                           LPARAM lParam )
3543 {
3544   if (!ViewerTest_myViews.IsEmpty()) {
3545
3546     WPARAM fwKeys = wParam;
3547
3548     switch( Msg ) {
3549     case WM_CLOSE:
3550        {
3551          // Delete view from map of views
3552          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
3553          return 0;
3554        }
3555        break;
3556     case WM_ACTIVATE:
3557       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
3558         || ViewerTest::CurrentView().IsNull())
3559       {
3560         // Activate inactive window
3561         if(GetWindowHandle(VT_GetWindow()) != hwnd)
3562         {
3563           ActivateView (FindViewIdByWindowHandle(hwnd));
3564         }
3565       }
3566       break;
3567
3568     case WM_LBUTTONUP:
3569       if (IsDragged && !DragFirst)
3570       {
3571         if (!GetActiveAISManipulator().IsNull())
3572         {
3573           GetActiveAISManipulator()->StopTransform();
3574           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
3575         }
3576
3577         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
3578         {
3579           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
3580           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
3581         }
3582
3583         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
3584       }
3585       IsDragged = Standard_False;
3586       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3587
3588     case WM_RBUTTONUP:
3589       if (IsDragged && !DragFirst)
3590       {
3591         if (!GetActiveAISManipulator().IsNull())
3592         {
3593           GetActiveAISManipulator()->StopTransform (Standard_False);
3594           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
3595         }
3596         IsDragged = Standard_False;
3597       }
3598       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
3599
3600     case WM_LBUTTONDOWN:
3601       if (!GetActiveAISManipulator().IsNull())
3602       {
3603         IsDragged = ( fwKeys == MK_LBUTTON );
3604       }
3605       else
3606       {
3607         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
3608       }
3609
3610       if (IsDragged)
3611       {
3612         DragFirst = Standard_True;
3613         X_ButtonPress = LOWORD(lParam);
3614         Y_ButtonPress = HIWORD(lParam);
3615       }
3616       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3617
3618     case WM_MOUSEMOVE:
3619       if (IsDragged)
3620       {
3621         X_Motion = LOWORD (lParam);
3622         Y_Motion = HIWORD (lParam);
3623         if (!GetActiveAISManipulator().IsNull())
3624         {
3625           if (DragFirst)
3626           {
3627             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
3628           }
3629           else
3630           {
3631             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
3632             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
3633           }
3634         }
3635         else
3636         {
3637           bool toRedraw = false;
3638           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
3639           {
3640             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
3641             toRedraw = true;
3642           }
3643
3644           RECT aRect;
3645           if (GetClientRect (hwnd, &aRect))
3646           {
3647             int aHeight = aRect.bottom - aRect.top;
3648             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
3649             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
3650             toRedraw = true;
3651           }
3652           if (toRedraw)
3653           {
3654             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
3655           }
3656         }
3657
3658         DragFirst = Standard_False;
3659       }
3660       else
3661         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3662       break;
3663
3664     default:
3665       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3666     }
3667     return 0;
3668   }
3669   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3670 }
3671
3672
3673 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
3674                                        UINT Msg,
3675                                        WPARAM wParam,
3676                                        LPARAM lParam )
3677 {
3678   static int Up = 1;
3679   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3680   if (aView.IsNull())
3681   {
3682     return DefWindowProcW (hwnd, Msg, wParam, lParam);
3683   }
3684
3685     PAINTSTRUCT    ps;
3686
3687     switch( Msg ) {
3688     case WM_PAINT:
3689       BeginPaint(hwnd, &ps);
3690       EndPaint(hwnd, &ps);
3691       VT_ProcessExpose();
3692       break;
3693
3694     case WM_SIZE:
3695       VT_ProcessConfigure();
3696       break;
3697     case WM_MOVE:
3698     case WM_MOVING:
3699     case WM_SIZING:
3700       switch (aView->RenderingParams().StereoMode)
3701       {
3702         case Graphic3d_StereoMode_RowInterlaced:
3703         case Graphic3d_StereoMode_ColumnInterlaced:
3704         case Graphic3d_StereoMode_ChessBoard:
3705           VT_ProcessConfigure(); // track window moves to reverse stereo pair
3706           break;
3707         default:
3708           break;
3709       }
3710       break;
3711
3712     case WM_KEYDOWN:
3713       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
3714       {
3715         char c[2];
3716         c[0] = (char) wParam;
3717         c[1] = '\0';
3718         if (wParam == VK_DELETE)
3719         {
3720           c[0] = THE_KEY_DELETE;
3721         }
3722         else if (wParam == VK_ESCAPE)
3723         {
3724           c[0] = THE_KEY_ESCAPE;
3725         }
3726         // comma
3727         else if (wParam == VK_OEM_COMMA)
3728         {
3729           c[0] = ',';
3730         }
3731         // dot
3732         else if (wParam == VK_OEM_PERIOD)
3733         {
3734           c[0] = '.';
3735         }
3736         else if (wParam == VK_DIVIDE)
3737         {
3738           c[0] = '/';
3739         }
3740         // dot
3741         else if (wParam == VK_MULTIPLY)
3742         {
3743           c[0] = '*';
3744         }
3745         VT_ProcessKeyPress (c);
3746       }
3747       break;
3748
3749     case WM_LBUTTONUP:
3750     case WM_MBUTTONUP:
3751     case WM_RBUTTONUP:
3752       Up = 1;
3753       VT_ProcessButton3Release();
3754       break;
3755
3756     case WM_LBUTTONDOWN:
3757     case WM_MBUTTONDOWN:
3758     case WM_RBUTTONDOWN:
3759       {
3760         WPARAM fwKeys = wParam;
3761
3762         Up = 0;
3763
3764         X_ButtonPress = LOWORD(lParam);
3765         Y_ButtonPress = HIWORD(lParam);
3766
3767         if (Msg == WM_LBUTTONDOWN)
3768         {
3769           if ((fwKeys & MK_CONTROL) != 0)
3770           {
3771             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
3772           }
3773           else
3774           {
3775             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
3776           }
3777         }
3778         else if (Msg == WM_RBUTTONDOWN)
3779         {
3780           // Start rotation
3781           VT_ProcessButton3Press();
3782         }
3783       }
3784       break;
3785
3786     case WM_MOUSEWHEEL:
3787     {
3788       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3789       if (wParam & MK_CONTROL)
3790       {
3791         if (aView->Camera()->IsStereo())
3792         {
3793           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
3794           if (aFocus > 0.2
3795            && aFocus < 2.0)
3796           {
3797             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
3798             aView->Redraw();
3799           }
3800         }
3801       }
3802       else
3803       {
3804         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
3805       }
3806       break;
3807     }
3808
3809     case WM_MOUSEMOVE:
3810       {
3811         //cout << "\t WM_MOUSEMOVE" << endl;
3812         WPARAM fwKeys = wParam;
3813         X_Motion = LOWORD(lParam);
3814         Y_Motion = HIWORD(lParam);
3815
3816         if ( Up &&
3817           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
3818           {
3819             Up = 0;
3820             X_ButtonPress = LOWORD(lParam);
3821             Y_ButtonPress = HIWORD(lParam);
3822
3823             if ((fwKeys & MK_RBUTTON) != 0) {
3824               // Start rotation
3825               VT_ProcessButton3Press();
3826             }
3827           }
3828
3829           if ((fwKeys & MK_CONTROL) != 0)
3830           {
3831             if ((fwKeys & MK_LBUTTON) != 0)
3832             {
3833               ProcessControlButton1Motion();
3834             }
3835             else if ((fwKeys & MK_MBUTTON) != 0
3836                  || ((fwKeys & MK_LBUTTON) != 0
3837                   && (fwKeys & MK_RBUTTON) != 0))
3838             {
3839               VT_ProcessControlButton2Motion();
3840             }
3841             else if ((fwKeys & MK_RBUTTON) != 0)
3842             {
3843               VT_ProcessControlButton3Motion();
3844             }
3845           }
3846           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
3847           {
3848             VT_ProcessMotion();
3849           }
3850       }
3851       break;
3852
3853     default:
3854       return DefWindowProcW (hwnd, Msg, wParam, lParam);
3855     }
3856     return 0L;
3857 }
3858
3859 //==============================================================================
3860 //function : ViewerMainLoop
3861 //purpose  : Get a Event on the view and dispatch it
3862 //==============================================================================
3863
3864
3865 int ViewerMainLoop(Standard_Integer argc, const char** argv)
3866 {
3867   Ppick = (argc > 0)? 1 : 0;
3868   Pargc = argc;
3869   Pargv = argv;
3870
3871   if ( Ppick ) {
3872     MSG msg;
3873     msg.wParam = 1;
3874
3875     cout << "Start picking" << endl;
3876
3877     while ( Ppick == 1 ) {
3878       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
3879       if (GetMessageW (&msg, NULL, 0, 0))
3880       {
3881         TranslateMessage (&msg);
3882         DispatchMessageW (&msg);
3883       }
3884     }
3885
3886     cout << "Picking done" << endl;
3887   }
3888
3889   return Ppick;
3890 }
3891
3892 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
3893
3894 int min( int a, int b )
3895 {
3896   if( a<b )
3897     return a;
3898   else
3899     return b;
3900 }
3901
3902 int max( int a, int b )
3903 {
3904   if( a>b )
3905     return a;
3906   else
3907     return b;
3908 }
3909
3910 int ViewerMainLoop (Standard_Integer argc, const char** argv)
3911 {
3912   static XEvent aReport;
3913   const Standard_Boolean toPick = argc > 0;
3914   Standard_Boolean toPickMore = toPick;
3915   Display* aDisplay = GetDisplayConnection()->GetDisplay();
3916   XNextEvent (aDisplay, &aReport);
3917
3918   // Handle event for the chosen display connection
3919   switch (aReport.type)
3920   {
3921     case ClientMessage:
3922     {
3923       if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
3924       {
3925         // Close the window
3926         ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
3927         return toPick ? 0 : 1;
3928       }
3929       break;
3930     }
3931     case FocusIn:
3932     {
3933       // Activate inactive view
3934       Window aWindow = GetWindowHandle(VT_GetWindow());
3935       if (aWindow != aReport.xfocus.window)
3936       {
3937         ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
3938       }
3939       break;
3940     }
3941     case Expose:
3942     {
3943       Window anXWindow = GetWindowHandle (VT_GetWindow());
3944       if (anXWindow == aReport.xexpose.window)
3945       {
3946         VT_ProcessExpose();
3947       }
3948
3949       // remove all the ExposureMask and process them at once
3950       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3951       {
3952         if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
3953         {
3954           break;
3955         }
3956       }
3957
3958       break;
3959     }
3960     case ConfigureNotify:
3961     {
3962       // remove all the StructureNotifyMask and process them at once
3963       Window anXWindow = GetWindowHandle (VT_GetWindow());
3964       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3965       {
3966         if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
3967         {
3968           break;
3969         }
3970       }
3971
3972       if (anXWindow == aReport.xconfigure.window)
3973       {
3974         VT_ProcessConfigure();
3975       }
3976       break;
3977     }
3978     case KeyPress:
3979     {
3980       KeySym aKeySym;
3981       char aKeyBuf[11];
3982       XComposeStatus status_in_out;
3983       int aKeyLen = XLookupString ((XKeyEvent* )&aReport, (char* )aKeyBuf, 10, &aKeySym, &status_in_out);
3984       aKeyBuf[aKeyLen] = '\0';
3985       if (aKeyLen != 0)
3986       {
3987         VT_ProcessKeyPress (aKeyBuf);
3988       }
3989       break;
3990     }
3991     case ButtonPress:
3992     {
3993       X_ButtonPress = aReport.xbutton.x;
3994       Y_ButtonPress = aReport.xbutton.y;
3995       if (aReport.xbutton.button == Button1)
3996       {
3997         if (aReport.xbutton.state & ControlMask)
3998         {
3999           toPickMore = VT_ProcessButton1Press (argc, argv, toPick, (aReport.xbutton.state & ShiftMask) != 0);
4000         }
4001         else
4002         {
4003           IsDragged = Standard_True;
4004           DragFirst = Standard_True;
4005         }
4006       }
4007       else if (aReport.xbutton.button == Button3)
4008       {
4009         // Start rotation
4010         VT_ProcessButton3Press();
4011       }
4012       break;
4013     }
4014     case ButtonRelease:
4015     {
4016       if (!IsDragged)
4017       {
4018         VT_ProcessButton3Release();
4019         break;
4020       }
4021
4022       Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4023       if (aContext.IsNull())
4024       {
4025         std::cout << "Error: No active view.\n";
4026         return 0;
4027       }
4028
4029       if (!DragFirst
4030         && aContext->IsDisplayed (GetRubberBand()))
4031       {
4032         aContext->Remove (GetRubberBand(), Standard_False);
4033         aContext->CurrentViewer()->RedrawImmediate();
4034       }
4035
4036       if (aReport.xbutton.button != Button1)
4037       {
4038         break;
4039       }
4040
4041       const Standard_Boolean isShiftPressed = (aReport.xbutton.state & ShiftMask) != 0;
4042       if (DragFirst)
4043       {
4044         if (isShiftPressed)
4045         {
4046           aContext->ShiftSelect (Standard_True);
4047         }
4048         else
4049         {
4050           aContext->Select (Standard_True);
4051         }
4052       }
4053       else
4054       {
4055         if (isShiftPressed)
4056         {
4057           aContext->ShiftSelect (Min (X_ButtonPress, X_Motion), Min (Y_ButtonPress, Y_Motion),
4058                                  Max (X_ButtonPress, X_Motion), Max (Y_ButtonPress, Y_Motion),
4059                                  ViewerTest::CurrentView(), Standard_True);
4060         }
4061         else
4062         {
4063           aContext->Select (Min (X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
4064                             Max (X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
4065                             ViewerTest::CurrentView(), Standard_True);
4066         }
4067       }
4068       IsDragged = Standard_False;
4069       break;
4070     }
4071     case MotionNotify:
4072     {
4073       Window anXWindow = GetWindowHandle (VT_GetWindow());
4074       if (anXWindow != aReport.xmotion.window)
4075       {
4076         break;
4077       }
4078
4079       // remove all the ButtonMotionMask and process them at once
4080       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
4081       {
4082         if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
4083         {
4084           break;
4085         }
4086       }
4087
4088       if (IsDragged)
4089       {
4090         if (!DragFirst
4091           && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
4092         {
4093           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
4094         }
4095
4096         X_Motion = aReport.xmotion.x;
4097         Y_Motion = aReport.xmotion.y;
4098         DragFirst = Standard_False;
4099
4100         Window aWindow = GetWindowHandle(VT_GetWindow());
4101         Window aRoot;
4102         int anX, anY;
4103         unsigned int aWidth, aHeight, aBorderWidth, aDepth;
4104         XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
4105         GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
4106         ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
4107         ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
4108       }
4109       else
4110       {
4111         X_Motion = aReport.xmotion.x;
4112         Y_Motion = aReport.xmotion.y;
4113         if ((aReport.xmotion.state & ControlMask) != 0)
4114         {
4115           if ((aReport.xmotion.state & Button1Mask) != 0)
4116           {
4117             ProcessControlButton1Motion();
4118           }
4119           else if ((aReport.xmotion.state & Button2Mask) != 0)
4120           {
4121             VT_ProcessControlButton2Motion();
4122           }
4123           else if ((aReport.xmotion.state & Button3Mask) != 0)
4124           {
4125             VT_ProcessControlButton3Motion();
4126           }
4127         }
4128         else
4129         {
4130           VT_ProcessMotion();
4131         }
4132       }
4133       break;
4134     }
4135   }
4136   return (!toPick || toPickMore) ? 1 : 0;
4137 }
4138
4139 //==============================================================================
4140 //function : VProcessEvents
4141 //purpose  : manage the event in the Viewer window (see Tcl_CreateFileHandler())
4142 //==============================================================================
4143 static void VProcessEvents (ClientData theDispX, int)
4144 {
4145   Display* aDispX = (Display* )theDispX;
4146   Handle(Aspect_DisplayConnection) aDispConn;
4147   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
4148        aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
4149   {
4150     const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
4151     if (aDispConnTmp->GetDisplay() == aDispX)
4152     {
4153       aDispConn = aDispConnTmp;
4154       break;
4155     }
4156   }
4157   if (aDispConn.IsNull())
4158   {
4159     std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
4160     return;
4161   }
4162
4163   // process new events in queue
4164   SetDisplayConnection (aDispConn);
4165   int aNbRemain = 0;
4166   for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
4167   {
4168     const int anEventResult = ViewerMainLoop (0, NULL);
4169     if (anEventResult == 0)
4170     {
4171       return;
4172     }
4173
4174     aNbRemain = XPending (aDispX);
4175     if (++anEventIter >= aNbEventsMax
4176      || aNbRemain <= 0)
4177     {
4178       break;
4179     }
4180   }
4181
4182   // Listening X events through Tcl_CreateFileHandler() callback is fragile,
4183   // it is possible that new events will arrive to queue before the end of this callback
4184   // so that either this callback should go into an infinite loop (blocking processing of other events)
4185   // or to keep unprocessed events till the next queue update (which can arrive not soon).
4186   // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
4187   if (aNbRemain != 0)
4188   {
4189     XEvent aDummyEvent;
4190     memset (&aDummyEvent, 0, sizeof(aDummyEvent));
4191     aDummyEvent.type = ClientMessage;
4192     aDummyEvent.xclient.format = 32;
4193     XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
4194     XFlush (aDispX);
4195   }
4196
4197   if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
4198   {
4199     SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
4200   }
4201 }
4202 #endif
4203
4204 //==============================================================================
4205 //function : OSWindowSetup
4206 //purpose  : Setup for the X11 window to be able to cath the event
4207 //==============================================================================
4208
4209
4210 static void OSWindowSetup()
4211 {
4212 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
4213   // X11
4214
4215   Window  window   = VT_GetWindow()->XWindow();
4216   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
4217   Display *aDisplay = GetDisplayConnection()->GetDisplay();
4218   XSynchronize(aDisplay, 1);
4219
4220   // X11 : For keyboard on SUN
4221   XWMHints wmhints;
4222   wmhints.flags = InputHint;
4223   wmhints.input = 1;
4224
4225   XSetWMHints( aDisplay, window, &wmhints);
4226
4227   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
4228     ButtonPressMask | ButtonReleaseMask |
4229     StructureNotifyMask |
4230     PointerMotionMask |
4231     Button1MotionMask | Button2MotionMask |
4232     Button3MotionMask | FocusChangeMask
4233     );
4234   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
4235   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
4236
4237   XSynchronize(aDisplay, 0);
4238
4239 #else
4240   // _WIN32
4241 #endif
4242
4243 }
4244
4245 //==============================================================================
4246 //function : VFit
4247 //purpose  :
4248 //==============================================================================
4249
4250 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
4251 {
4252   const Handle(V3d_View) aView = ViewerTest::CurrentView();
4253   if (aView.IsNull())
4254   {
4255     std::cout << "Error: no active viewer!\n";
4256     return 1;
4257   }
4258
4259   Standard_Boolean toFit = Standard_True;
4260   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
4261   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4262   {
4263     TCollection_AsciiString anArg (theArgv[anArgIter]);
4264     anArg.LowerCase();
4265     if (anUpdateTool.parseRedrawMode (anArg))
4266     {
4267       continue;
4268     }
4269     else if (anArg == "-selected")
4270     {
4271       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
4272       toFit = Standard_False;
4273     }
4274     else
4275     {
4276       std::cout << "Syntax error at '" << anArg << "'\n";
4277     }
4278   }
4279
4280   if (toFit)
4281   {
4282     aView->FitAll (0.01, Standard_False);
4283   }
4284   return 0;
4285 }
4286
4287 //=======================================================================
4288 //function : VFitArea
4289 //purpose  : Fit view to show area located between two points
4290 //         : given in world 2D or 3D coordinates.
4291 //=======================================================================
4292 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
4293 {
4294   Handle(V3d_View) aView = ViewerTest::CurrentView();
4295   if (aView.IsNull())
4296   {
4297     std::cerr << theArgVec[0] << "Error: No active view.\n";
4298     return 1;
4299   }
4300
4301   // Parse arguments.
4302   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
4303   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
4304
4305   if (theArgNb == 5)
4306   {
4307     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
4308     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
4309     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
4310     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
4311   }
4312   else if (theArgNb == 7)
4313   {
4314     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
4315     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
4316     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
4317     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
4318     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
4319     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
4320   }
4321   else
4322   {
4323     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
4324     theDI.PrintHelp(theArgVec[0]);
4325     return 1;
4326   }
4327
4328   // Convert model coordinates to view space
4329   Handle(Graphic3d_Camera) aCamera = aView->Camera();
4330   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
4331   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
4332
4333   // Determine fit area
4334   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
4335   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
4336
4337   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
4338
4339   if (aDiagonal < Precision::Confusion())
4340   {
4341     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
4342     return 1;
4343   }
4344
4345   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
4346   return 0;
4347 }
4348
4349 //==============================================================================
4350 //function : VZFit
4351 //purpose  : ZFitall, no DRAW arguments
4352 //Draw arg : No args
4353 //==============================================================================
4354 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
4355 {
4356   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
4357
4358   if (aCurrentView.IsNull())
4359   {
4360     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
4361     return 1;
4362   }
4363
4364   if (theArgsNb == 1)
4365   {
4366     aCurrentView->ZFitAll();
4367     aCurrentView->Redraw();
4368     return 0;
4369   }
4370
4371   Standard_Real aScale = 1.0;
4372
4373   if (theArgsNb >= 2)
4374   {
4375     aScale = Draw::Atoi (theArgVec[1]);
4376   }
4377
4378   aCurrentView->ZFitAll (aScale);
4379   aCurrentView->Redraw();
4380
4381   return 0;
4382 }
4383
4384 //==============================================================================
4385 //function : VRepaint
4386 //purpose  :
4387 //==============================================================================
4388 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
4389 {
4390   Handle(V3d_View) aView = ViewerTest::CurrentView();
4391   if (aView.IsNull())
4392   {
4393     std::cout << "Error: no active viewer!\n";
4394     return 1;
4395   }
4396
4397   Standard_Boolean isImmediateUpdate = Standard_False;
4398   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4399   {
4400     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4401     anArg.LowerCase();
4402     if (anArg == "-immediate"
4403      || anArg == "-imm")
4404     {
4405       isImmediateUpdate = Standard_True;
4406       if (anArgIter + 1 < theArgNb
4407        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
4408       {
4409         ++anArgIter;
4410       }
4411     }
4412     else if (anArg == "-continuous"
4413           || anArg == "-cont"
4414           || anArg == "-fps"
4415           || anArg == "-framerate")
4416     {
4417       Standard_Real aFps = -1.0;
4418       if (anArgIter + 1 < theArgNb
4419        && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
4420       {
4421         aFps = Draw::Atof (theArgVec[++anArgIter]);
4422       }
4423
4424       ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
4425       if (Abs (aFps) >= 1.0)
4426       {
4427         aRedrawer.Start (aView->Window(), aFps);
4428       }
4429       else
4430       {
4431         aRedrawer.Stop();
4432       }
4433     }
4434     else
4435     {
4436       std::cout << "Syntax error at '" << anArg << "'\n";
4437       return 1;
4438     }
4439   }
4440
4441   if (isImmediateUpdate)
4442   {
4443     aView->RedrawImmediate();
4444   }
4445   else
4446   {
4447     aView->Redraw();
4448   }
4449   return 0;
4450 }
4451
4452 //==============================================================================
4453 //function : VClear
4454 //purpose  : Remove all the object from the viewer
4455 //Draw arg : No args
4456 //==============================================================================
4457
4458 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
4459 {
4460   Handle(V3d_View) V = ViewerTest::CurrentView();
4461   if(!V.IsNull())
4462     ViewerTest::Clear();
4463   return 0;
4464 }
4465
4466 //==============================================================================
4467 //function : VPick
4468 //purpose  :
4469 //==============================================================================
4470
4471 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4472 { if (ViewerTest::CurrentView().IsNull() ) return 1;
4473
4474 if ( argc < 4 ) {
4475   di << argv[0] << "Invalid number of arguments\n";
4476   return 1;
4477 }
4478
4479 while (ViewerMainLoop( argc, argv)) {
4480 }
4481
4482 return 0;
4483 }
4484
4485 namespace
4486 {
4487
4488   //! Changes the background
4489   //! @param theDrawInterpretor the interpreter of the Draw Harness application
4490   //! @param theNumberOfCommandLineArguments the number of passed command line arguments
4491   //! @param theCommandLineArguments the array of command line arguments
4492   //! @return TCL_OK if changing was successful, or TCL_ERROR otherwise
4493   static int vbackground (Draw_Interpretor&      theDrawInterpretor,
4494                           const Standard_Integer theNumberOfCommandLineArguments,
4495                           const char** const     theCommandLineArguments)
4496   {
4497     if (theNumberOfCommandLineArguments < 1)
4498     {
4499       return TCL_ERROR;
4500     }
4501     BackgroundChanger aBackgroundChanger;
4502     if (!aBackgroundChanger.ProcessCommandLine (theDrawInterpretor,
4503                                                 theNumberOfCommandLineArguments,
4504                                                 theCommandLineArguments))
4505     {
4506       theDrawInterpretor << "Wrong command arguments.\n"
4507                             "Type 'help "
4508                          << theCommandLineArguments[0] << "' for information about command options and its arguments.\n";
4509       return TCL_ERROR;
4510     }
4511     return TCL_OK;
4512   }
4513
4514 } // namespace
4515
4516 //==============================================================================
4517 //function : VScale
4518 //purpose  : View Scaling
4519 //==============================================================================
4520
4521 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4522 {
4523   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4524   if ( V3dView.IsNull() ) return 1;
4525
4526   if ( argc != 4 ) {
4527     di << argv[0] << "Invalid number of arguments\n";
4528     return 1;
4529   }
4530   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
4531   return 0;
4532 }
4533 //==============================================================================
4534 //function : VZBuffTrihedron
4535 //purpose  :
4536 //==============================================================================
4537
4538 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
4539                             Standard_Integer  theArgNb,
4540                             const char**      theArgVec)
4541 {
4542   Handle(V3d_View) aView = ViewerTest::CurrentView();
4543   if (aView.IsNull())
4544   {
4545     std::cout << "Error: no active viewer!\n";
4546     return 1;
4547   }
4548
4549   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4550
4551   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
4552   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
4553   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
4554   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
4555   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
4556   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
4557   Standard_Real                 aScale        = 0.1;
4558   Standard_Real                 aSizeRatio    = 0.8;
4559   Standard_Real                 anArrowDiam   = 0.05;
4560   Standard_Integer              aNbFacets     = 12;
4561   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4562   {
4563     Standard_CString        anArg = theArgVec[anArgIter];
4564     TCollection_AsciiString aFlag (anArg);
4565     aFlag.LowerCase();
4566     if (anUpdateTool.parseRedrawMode (aFlag))
4567     {
4568       continue;
4569     }
4570     else if (aFlag == "-on")
4571     {
4572       continue;
4573     }
4574     else if (aFlag == "-off")
4575     {
4576       aView->TriedronErase();
4577       return 0;
4578     }
4579     else if (aFlag == "-pos"
4580           || aFlag == "-position"
4581           || aFlag == "-corner")
4582     {
4583       if (++anArgIter >= theArgNb)
4584       {
4585         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4586         return 1;
4587       }
4588
4589       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
4590       aPosName.LowerCase();
4591       if (aPosName == "center")
4592       {
4593         aPosition = Aspect_TOTP_CENTER;
4594       }
4595       else if (aPosName == "left_lower"
4596             || aPosName == "lower_left"
4597             || aPosName == "leftlower"
4598             || aPosName == "lowerleft")
4599       {
4600         aPosition = Aspect_TOTP_LEFT_LOWER;
4601       }
4602       else if (aPosName == "left_upper"
4603             || aPosName == "upper_left"
4604             || aPosName == "leftupper"
4605             || aPosName == "upperleft")
4606       {
4607         aPosition = Aspect_TOTP_LEFT_UPPER;
4608       }
4609       else if (aPosName == "right_lower"
4610             || aPosName == "lower_right"
4611             || aPosName == "rightlower"
4612             || aPosName == "lowerright")
4613       {
4614         aPosition = Aspect_TOTP_RIGHT_LOWER;
4615       }
4616       else if (aPosName == "right_upper"
4617             || aPosName == "upper_right"
4618             || aPosName == "rightupper"
4619             || aPosName == "upperright")
4620       {
4621         aPosition = Aspect_TOTP_RIGHT_UPPER;
4622       }
4623       else
4624       {
4625         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
4626         return 1;
4627       }
4628     }
4629     else if (aFlag == "-type")
4630     {
4631       if (++anArgIter >= theArgNb)
4632       {
4633         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4634         return 1;
4635       }
4636
4637       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
4638       aTypeName.LowerCase();
4639       if (aTypeName == "wireframe"
4640        || aTypeName == "wire")
4641       {
4642         aVisType = V3d_WIREFRAME;
4643       }
4644       else if (aTypeName == "zbuffer"
4645             || aTypeName == "shaded")
4646       {
4647         aVisType = V3d_ZBUFFER;
4648       }
4649       else
4650       {
4651         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
4652       }
4653     }
4654     else if (aFlag == "-scale")
4655     {
4656       if (++anArgIter >= theArgNb)
4657       {
4658         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4659         return 1;
4660       }
4661
4662       aScale = Draw::Atof (theArgVec[anArgIter]);
4663     }
4664     else if (aFlag == "-size"
4665           || aFlag == "-sizeratio")
4666     {
4667       if (++anArgIter >= theArgNb)
4668       {
4669         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4670         return 1;
4671       }
4672
4673       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
4674     }
4675     else if (aFlag == "-arrowdiam"
4676           || aFlag == "-arrowdiameter")
4677     {
4678       if (++anArgIter >= theArgNb)
4679       {
4680         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4681         return 1;
4682       }
4683
4684       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
4685     }
4686     else if (aFlag == "-nbfacets")
4687     {
4688       if (++anArgIter >= theArgNb)
4689       {
4690         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4691         return 1;
4692       }
4693
4694       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
4695     }
4696     else if (aFlag == "-colorlabel"
4697           || aFlag == "-colorlabels")
4698     {
4699       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4700                                                            theArgVec + anArgIter + 1,
4701                                                            aLabelsColor);
4702       if (aNbParsed == 0)
4703       {
4704         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4705         return 1;
4706       }
4707       anArgIter += aNbParsed;
4708     }
4709     else if (aFlag == "-colorarrowx")
4710     {
4711       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4712                                                            theArgVec + anArgIter + 1,
4713                                                            anArrowColorX);
4714       if (aNbParsed == 0)
4715       {
4716         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4717         return 1;
4718       }
4719       anArgIter += aNbParsed;
4720     }
4721     else if (aFlag == "-colorarrowy")
4722     {
4723       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4724                                                            theArgVec + anArgIter + 1,
4725                                                            anArrowColorY);
4726       if (aNbParsed == 0)
4727       {
4728         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4729         return 1;
4730       }
4731       anArgIter += aNbParsed;
4732     }
4733     else if (aFlag == "-colorarrowz")
4734     {
4735       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4736                                                            theArgVec + anArgIter + 1,
4737                                                            anArrowColorZ);
4738       if (aNbParsed == 0)
4739       {
4740         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4741         return 1;
4742       }
4743       anArgIter += aNbParsed;
4744     }
4745     else
4746     {
4747       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4748       return 1;
4749     }
4750   }
4751
4752   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
4753                                aSizeRatio, anArrowDiam, aNbFacets);
4754   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
4755   aView->ZFitAll();
4756   return 0;
4757 }
4758
4759 //==============================================================================
4760 //function : VRotate
4761 //purpose  : Camera Rotating
4762 //==============================================================================
4763
4764 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
4765 {
4766   Handle(V3d_View) aView = ViewerTest::CurrentView();
4767   if (aView.IsNull())
4768   {
4769     std::cout << "No active view!\n";
4770     return 1;
4771   }
4772
4773   Standard_Boolean hasFlags = Standard_False;
4774   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4775   {
4776     Standard_CString        anArg (theArgVec[anArgIter]);
4777     TCollection_AsciiString aFlag (anArg);
4778     aFlag.LowerCase();
4779     if (aFlag == "-mousestart"
4780      || aFlag == "-mousefrom")
4781     {
4782       hasFlags = Standard_True;
4783       if (anArgIter + 2 >= theArgNb)
4784       {
4785         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4786         return 1;
4787       }
4788
4789       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4790       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4791       aView->StartRotation (anX, anY);
4792     }
4793     else if (aFlag == "-mousemove")
4794     {
4795       hasFlags = Standard_True;
4796       if (anArgIter + 2 >= theArgNb)
4797       {
4798         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4799         return 1;
4800       }
4801
4802       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4803       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4804       aView->Rotation (anX, anY);
4805     }
4806     else if (theArgNb != 4
4807           && theArgNb != 7)
4808     {
4809       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4810       return 1;
4811     }
4812   }
4813
4814   if (hasFlags)
4815   {
4816     return 0;
4817   }
4818   else if (theArgNb == 4)
4819   {
4820     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4821     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4822     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4823     aView->Rotate (anAX, anAY, anAZ);
4824     return 0;
4825   }
4826   else if (theArgNb == 7)
4827   {
4828     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4829     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4830     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4831
4832     Standard_Real anX = Draw::Atof (theArgVec[4]);
4833     Standard_Real anY = Draw::Atof (theArgVec[5]);
4834     Standard_Real anZ = Draw::Atof (theArgVec[6]);
4835
4836     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
4837     return 0;
4838   }
4839
4840   std::cout << "Error: Invalid number of arguments\n";
4841   return 1;
4842 }
4843
4844 //==============================================================================
4845 //function : VZoom
4846 //purpose  : View zoom in / out (relative to current zoom)
4847 //==============================================================================
4848
4849 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4850   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4851   if ( V3dView.IsNull() ) {
4852     return 1;
4853   }
4854
4855   if ( argc == 2 ) {
4856     Standard_Real coef = Draw::Atof(argv[1]);
4857     if ( coef <= 0.0 ) {
4858       di << argv[1] << "Invalid value\n";
4859       return 1;
4860     }
4861     V3dView->SetZoom( Draw::Atof(argv[1]) );
4862     return 0;
4863   } else {
4864     di << argv[0] << " Invalid number of arguments\n";
4865     return 1;
4866   }
4867 }
4868
4869 //==============================================================================
4870 //function : VPan
4871 //purpose  : View panning (in pixels)
4872 //==============================================================================
4873
4874 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4875   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4876   if ( V3dView.IsNull() ) return 1;
4877
4878   if ( argc == 3 ) {
4879     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
4880     return 0;
4881   } else {
4882     di << argv[0] << " Invalid number of arguments\n";
4883     return 1;
4884   }
4885 }
4886
4887 //==============================================================================
4888 //function : VPlace
4889 //purpose  : Place the point (in pixels) at the center of the window
4890 //==============================================================================
4891 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
4892 {
4893   Handle(V3d_View) aView = ViewerTest::CurrentView();
4894   if (aView.IsNull())
4895   {
4896     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
4897     return 1;
4898   }
4899
4900   if (theArgNb != 3)
4901   {
4902     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
4903     return 1;
4904   }
4905
4906   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
4907
4908   return 0;
4909 }
4910
4911 static int VColorScale (Draw_Interpretor& theDI,
4912                         Standard_Integer  theArgNb,
4913                         const char**      theArgVec)
4914 {
4915   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4916   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
4917   if (aContext.IsNull())
4918   {
4919     std::cout << "Error: no active view!\n";
4920     return 1;
4921   }
4922   if (theArgNb <= 1)
4923   {
4924     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
4925     return 1;
4926   }
4927
4928   Handle(AIS_ColorScale) aColorScale;
4929   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
4930   {
4931     // find existing object
4932     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
4933     if (aColorScale.IsNull())
4934     {
4935       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
4936       return 1;
4937     }
4938   }
4939
4940   if (theArgNb <= 2)
4941   {
4942     if (aColorScale.IsNull())
4943     {
4944       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
4945       return 1;
4946     }
4947
4948     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
4949           << "Min range: "            << aColorScale->GetMin() << "\n"
4950           << "Max range: "            << aColorScale->GetMax() << "\n"
4951           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
4952           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
4953           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
4954           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
4955           << "Label position: ";
4956     switch (aColorScale->GetLabelPosition())
4957     {
4958       case Aspect_TOCSP_NONE:
4959         theDI << "None\n";
4960         break;
4961       case Aspect_TOCSP_LEFT:
4962         theDI << "Left\n";
4963         break;
4964       case Aspect_TOCSP_RIGHT:
4965         theDI << "Right\n";
4966         break;
4967       case Aspect_TOCSP_CENTER:
4968         theDI << "Center\n";
4969         break;
4970     }
4971     return 0;
4972   }
4973
4974   if (aColorScale.IsNull())
4975   {
4976     aColorScale = new AIS_ColorScale();
4977     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4978     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4979   }
4980
4981   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
4982   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
4983   {
4984     Standard_CString        anArg = theArgVec[anArgIter];
4985     TCollection_AsciiString aFlag (anArg);
4986     aFlag.LowerCase();
4987     if (anUpdateTool.parseRedrawMode (aFlag))
4988     {
4989       continue;
4990     }
4991     else if (aFlag == "-range")
4992     {
4993       if (anArgIter + 3 >= theArgNb)
4994       {
4995         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4996         return 1;
4997       }
4998
4999       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
5000       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
5001       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
5002       if (!aRangeMin.IsRealValue()
5003        || !aRangeMax.IsRealValue())
5004       {
5005         std::cout << "Error: the range values should be real!\n";
5006         return 1;
5007       }
5008       else if (!aNbIntervals.IsIntegerValue())
5009       {
5010         std::cout << "Error: the number of intervals should be integer!\n";
5011         return 1;
5012       }
5013
5014       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
5015       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
5016     }
5017     else if (aFlag == "-font")
5018     {
5019       if (anArgIter + 1 >= theArgNb)
5020       {
5021         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5022         return 1;
5023       }
5024       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
5025       if (!aFontArg.IsIntegerValue())
5026       {
5027         std::cout << "Error: HeightFont value should be integer!\n";
5028         return 1;
5029       }
5030
5031       aColorScale->SetTextHeight (aFontArg.IntegerValue());
5032       anArgIter += 1;
5033     }
5034     else if (aFlag == "-textpos")
5035     {
5036       if (anArgIter + 1 >= theArgNb)
5037       {
5038         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5039         return 1;
5040       }
5041
5042       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
5043       aTextPosArg.LowerCase();
5044       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
5045       if (aTextPosArg == "none")
5046       {
5047         aLabPosition = Aspect_TOCSP_NONE;
5048       }
5049       else if (aTextPosArg == "left")
5050       {
5051         aLabPosition = Aspect_TOCSP_LEFT;
5052       }
5053       else if (aTextPosArg == "right")
5054       {
5055         aLabPosition = Aspect_TOCSP_RIGHT;
5056       }
5057       else if (aTextPosArg == "center")
5058       {
5059         aLabPosition = Aspect_TOCSP_CENTER;
5060       }
5061       else
5062       {
5063         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
5064         return 1;
5065       }
5066       aColorScale->SetLabelPosition (aLabPosition);
5067     }
5068     else if (aFlag == "-logarithmic"
5069           || aFlag == "-log")
5070     {
5071       if (anArgIter + 1 >= theArgNb)
5072       {
5073         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5074         return 1;
5075       }
5076
5077       Standard_Boolean IsLog;
5078       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
5079       {
5080         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5081         return 1;
5082       }
5083       aColorScale->SetLogarithmic (IsLog);
5084     }
5085     else if (aFlag == "-huerange"
5086           || aFlag == "-hue")
5087     {
5088       if (anArgIter + 2 >= theArgNb)
5089       {
5090         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5091         return 1;
5092       }
5093
5094       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
5095       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
5096       aColorScale->SetHueRange (aHueMin, aHueMax);
5097     }
5098     else if (aFlag == "-colorrange")
5099     {
5100       Quantity_Color aColorMin, aColorMax;
5101       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
5102                                                             theArgVec + (anArgIter + 1),
5103                                                             aColorMin);
5104       anArgIter += aNbParsed1;
5105       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
5106                                                             theArgVec + (anArgIter + 1),
5107                                                             aColorMax);
5108       anArgIter += aNbParsed2;
5109       if (aNbParsed1 == 0
5110        || aNbParsed2 == 0)
5111       {
5112         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
5113         return 1;
5114       }
5115
5116       aColorScale->SetColorRange (aColorMin, aColorMax);
5117     }
5118     else if (aFlag == "-reversed"
5119           || aFlag == "-inverted"
5120           || aFlag == "-topdown"
5121           || aFlag == "-bottomup")
5122     {
5123       Standard_Boolean toEnable = Standard_True;
5124       if (anArgIter + 1 < theArgNb
5125        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
5126       {
5127         ++anArgIter;
5128       }
5129       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
5130     }
5131     else if (aFlag == "-smooth"
5132           || aFlag == "-smoothtransition")
5133     {
5134       Standard_Boolean toEnable = Standard_True;
5135       if (anArgIter + 1 < theArgNb
5136        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
5137       {
5138         ++anArgIter;
5139       }
5140       aColorScale->SetSmoothTransition (toEnable);
5141     }
5142     else if (aFlag == "-xy")
5143     {
5144       if (anArgIter + 2 >= theArgNb)
5145       {
5146         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5147         return 1;
5148       }
5149
5150       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
5151       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
5152       if (!anX.IsIntegerValue()
5153        || !anY.IsIntegerValue())
5154       {
5155         std::cout << "Error: coordinates should be integer values!\n";
5156         return 1;
5157       }
5158
5159       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
5160     }
5161     else if (aFlag == "-width"
5162           || aFlag == "-w"
5163           || aFlag == "-breadth")
5164     {
5165       if (anArgIter + 1 >= theArgNb)
5166       {
5167         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5168         return 1;
5169       }
5170
5171       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
5172       if (!aBreadth.IsIntegerValue())
5173       {
5174         std::cout << "Error: a width should be an integer value!\n";
5175         return 1;
5176       }
5177       aColorScale->SetBreadth (aBreadth.IntegerValue());
5178     }
5179     else if (aFlag == "-height"
5180           || aFlag == "-h")
5181     {
5182       if (anArgIter + 1 >= theArgNb)
5183       {
5184         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5185         return 1;
5186       }
5187
5188       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
5189       if (!aHeight.IsIntegerValue())
5190       {
5191         std::cout << "Error: a width should be an integer value!\n";
5192         return 1;
5193       }
5194       aColorScale->SetHeight (aHeight.IntegerValue());
5195     }
5196     else if (aFlag == "-color")
5197     {
5198       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
5199       {
5200         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
5201         return 1;
5202       }
5203       else if (anArgIter + 2 >= theArgNb)
5204       {
5205         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5206         return 1;
5207       }
5208
5209       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
5210       if (!anInd.IsIntegerValue())
5211       {
5212         std::cout << "Error: Index value should be integer!\n";
5213         return 1;
5214       }
5215       const Standard_Integer anIndex = anInd.IntegerValue();
5216       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
5217       {
5218         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
5219         return 1;
5220       }
5221
5222       Quantity_Color aColor;
5223       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
5224                                                            theArgVec + (anArgIter + 1),
5225                                                            aColor);
5226       if (aNbParsed == 0)
5227       {
5228         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
5229         return 1;
5230       }
5231       aColorScale->SetIntervalColor (aColor, anIndex);
5232       aColorScale->SetColorType (Aspect_TOCSD_USER);
5233       anArgIter += aNbParsed;
5234     }
5235     else if (aFlag == "-label")
5236     {
5237       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
5238       {
5239         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
5240         return 1;
5241       }
5242       else if (anArgIter + 2 >= theArgNb)
5243       {
5244         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5245         return 1;
5246       }
5247
5248       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
5249       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
5250       {
5251         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
5252         return 1;
5253       }
5254
5255       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
5256       aColorScale->SetLabel     (aText, anIndex);
5257       aColorScale->SetLabelType (Aspect_TOCSD_USER);
5258       anArgIter += 2;
5259     }
5260     else if (aFlag == "-labelat"
5261           || aFlag == "-labat"
5262           || aFlag == "-labelatborder"
5263           || aFlag == "-labatborder"
5264           || aFlag == "-labelatcenter"
5265           || aFlag == "-labatcenter")
5266     {
5267       Standard_Boolean toEnable = Standard_True;
5268       if (aFlag == "-labelat"
5269        || aFlag == "-labat")
5270       {
5271         Standard_Integer aLabAtBorder = -1;
5272         if (++anArgIter >= theArgNb)
5273         {
5274           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
5275           anAtBorder.LowerCase();
5276           if (anAtBorder == "border")
5277           {
5278             aLabAtBorder = 1;
5279           }
5280           else if (anAtBorder == "center")
5281           {
5282             aLabAtBorder = 0;
5283           }
5284         }
5285         if (aLabAtBorder == -1)
5286         {
5287           std::cout << "Syntax error at argument '" << anArg << "'!\n";
5288           return 1;
5289         }
5290         toEnable = (aLabAtBorder == 1);
5291       }
5292       else if (anArgIter + 1 < theArgNb
5293             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
5294       {
5295         ++anArgIter;
5296       }
5297       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
5298                                   || aFlag == "-labatcenter"
5299                                    ? !toEnable
5300                                    :  toEnable);
5301     }
5302     else if (aFlag == "-colors")
5303     {
5304       Aspect_SequenceOfColor aSeq;
5305       for (;;)
5306       {
5307         Quantity_Color aColor;
5308         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
5309                                                              theArgVec + (anArgIter + 1),
5310                                                              aColor);
5311         if (aNbParsed == 0)
5312         {
5313           break;
5314         }
5315         anArgIter += aNbParsed;
5316         aSeq.Append (aColor);
5317       }
5318       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
5319       {
5320         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
5321                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
5322         return 1;
5323       }
5324
5325       aColorScale->SetColors    (aSeq);
5326       aColorScale->SetColorType (Aspect_TOCSD_USER);
5327     }
5328     else if (aFlag == "-labels"
5329           || aFlag == "-freelabels")
5330     {
5331       if (anArgIter + 1 >= theArgNb)
5332       {
5333         std::cout << "Syntax error at argument '" << anArg << "'!\n";
5334         return 1;
5335       }
5336
5337       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
5338                                  ? aColorScale->GetNumberOfIntervals() + 1
5339                                  : aColorScale->GetNumberOfIntervals();
5340       if (aFlag == "-freelabels")
5341       {
5342         ++anArgIter;
5343         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
5344       }
5345       if (anArgIter + aNbLabels >= theArgNb)
5346       {
5347         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
5348         return 1;
5349       }
5350
5351       TColStd_SequenceOfExtendedString aSeq;
5352       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
5353       {
5354         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
5355       }
5356       aColorScale->SetLabels (aSeq);
5357       aColorScale->SetLabelType (Aspect_TOCSD_USER);
5358     }
5359     else if (aFlag == "-title")
5360     {
5361       if (anArgIter + 1 >= theArgNb)
5362       {
5363         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5364         return 1;
5365       }
5366
5367       Standard_Boolean isTwoArgs = Standard_False;
5368       if (anArgIter + 2 < theArgNb)
5369       {
5370         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
5371         aSecondArg.LowerCase();
5372       Standard_DISABLE_DEPRECATION_WARNINGS
5373         if (aSecondArg == "none")
5374         {
5375           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
5376           isTwoArgs = Standard_True;
5377         }
5378         else if (aSecondArg == "left")
5379         {
5380           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
5381           isTwoArgs = Standard_True;
5382         }
5383         else if (aSecondArg == "right")
5384         {
5385           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
5386           isTwoArgs = Standard_True;
5387         }
5388         else if (aSecondArg == "center")
5389         {
5390           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
5391           isTwoArgs = Standard_True;
5392         }
5393       Standard_ENABLE_DEPRECATION_WARNINGS
5394       }
5395
5396       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
5397       if (isTwoArgs)
5398       {
5399         anArgIter += 1;
5400       }
5401       anArgIter += 1;
5402     }
5403     else if (aFlag == "-demoversion"
5404           || aFlag == "-demo")
5405     {
5406       aColorScale->SetPosition (0, 0);
5407       aColorScale->SetTextHeight (16);
5408       aColorScale->SetRange (0.0, 100.0);
5409       aColorScale->SetNumberOfIntervals (10);
5410       aColorScale->SetBreadth (0);
5411       aColorScale->SetHeight  (0);
5412       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
5413       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
5414       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
5415     }
5416     else if (aFlag == "-findcolor")
5417     {
5418       if (anArgIter + 1 >= theArgNb)
5419       {
5420         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5421         return 1;
5422       }
5423
5424       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
5425
5426       if (!anArg1.IsRealValue())
5427       {
5428         std::cout << "Error: the value should be real!\n";
5429         return 1;
5430       }
5431
5432       Quantity_Color aColor;
5433       aColorScale->FindColor (anArg1.RealValue(), aColor);
5434       theDI << Quantity_Color::StringName (aColor.Name());
5435       return 0;
5436     }
5437     else
5438     {
5439       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
5440       return 1;
5441     }
5442   }
5443
5444   Standard_Integer aWinWidth = 0, aWinHeight = 0;
5445   aView->Window()->Size (aWinWidth, aWinHeight);
5446   if (aColorScale->GetBreadth() == 0)
5447   {
5448     aColorScale->SetBreadth (aWinWidth);
5449   }
5450   if (aColorScale->GetHeight() == 0)
5451   {
5452     aColorScale->SetHeight (aWinHeight);
5453   }
5454   aColorScale->SetToUpdate();
5455   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
5456   return 0;
5457 }
5458
5459 //==============================================================================
5460 //function : VGraduatedTrihedron
5461 //purpose  : Displays or hides a graduated trihedron
5462 //==============================================================================
5463 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
5464                                   Quantity_Color& theColor)
5465 {
5466   Quantity_NameOfColor aColorName;
5467   TCollection_AsciiString aVal = theValue;
5468   aVal.UpperCase();
5469   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
5470   {
5471     return Standard_False;
5472   }
5473   theColor = Quantity_Color (aColorName);
5474   return Standard_True;
5475 }
5476
5477 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
5478 {
5479   if (theArgNum < 2)
5480   {
5481     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
5482               << theArgs[0] <<"' for more information.\n";
5483     return 1;  //TCL_ERROR
5484   }
5485
5486   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
5487   TCollection_AsciiString aParseKey;
5488   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
5489   {
5490     TCollection_AsciiString anArg (theArgs [anArgIt]);
5491
5492     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
5493     {
5494       aParseKey = anArg;
5495       aParseKey.Remove (1);
5496       aParseKey.LowerCase();
5497       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
5498       continue;
5499     }
5500
5501     if (aParseKey.IsEmpty())
5502     {
5503       continue;
5504     }
5505
5506     aMapOfArgs(aParseKey)->Append (anArg);
5507   }
5508
5509   // Check parameters
5510   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
5511        aMapIt.More(); aMapIt.Next())
5512   {
5513     const TCollection_AsciiString& aKey = aMapIt.Key();
5514     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
5515
5516     // Bool key, without arguments
5517     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
5518         && anArgs->IsEmpty())
5519     {
5520       continue;
5521     }
5522
5523     // One argument
5524     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
5525           && anArgs->Length() == 1)
5526     {
5527       continue;
5528     }
5529
5530     // On/off arguments
5531     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
5532         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
5533         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
5534         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
5535         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
5536     {
5537       continue;
5538     }
5539
5540     // One string argument
5541     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
5542           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
5543           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5544     {
5545       continue;
5546     }
5547
5548     // One integer argument
5549     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
5550           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
5551           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
5552           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
5553          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
5554     {
5555       continue;
5556     }
5557
5558     // One real argument
5559     if ( aKey.IsEqual ("arrowlength")
5560          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
5561     {
5562       continue;
5563     }
5564
5565     // Two string arguments
5566     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
5567          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5568     {
5569       continue;
5570     }
5571
5572     TCollection_AsciiString aLowerKey;
5573     aLowerKey  = "-";
5574     aLowerKey += aKey;
5575     aLowerKey.LowerCase();
5576     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
5577     std::cout << "Type help for more information.\n";
5578     return 1;
5579   }
5580
5581   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
5582   if (anAISContext.IsNull())
5583   {
5584     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
5585     return 1;
5586   }
5587
5588   Standard_Boolean toDisplay = Standard_True;
5589   Quantity_Color aColor;
5590   Graphic3d_GraduatedTrihedron aTrihedronData;
5591   // Process parameters
5592   Handle(TColStd_HSequenceOfAsciiString) aValues;
5593   if (aMapOfArgs.Find ("off", aValues))
5594   {
5595     toDisplay = Standard_False;
5596   }
5597
5598   // AXES NAMES
5599   if (aMapOfArgs.Find ("xname", aValues))
5600   {
5601     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
5602   }
5603   if (aMapOfArgs.Find ("yname", aValues))
5604   {
5605     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
5606   }
5607   if (aMapOfArgs.Find ("zname", aValues))
5608   {
5609     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
5610   }
5611   if (aMapOfArgs.Find ("xdrawname", aValues))
5612   {
5613     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5614   }
5615   if (aMapOfArgs.Find ("ydrawname", aValues))
5616   {
5617     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5618   }
5619   if (aMapOfArgs.Find ("zdrawname", aValues))
5620   {
5621     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5622   }
5623   if (aMapOfArgs.Find ("xnameoffset", aValues))
5624   {
5625     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5626   }
5627   if (aMapOfArgs.Find ("ynameoffset", aValues))
5628   {
5629     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5630   }
5631   if (aMapOfArgs.Find ("znameoffset", aValues))
5632   {
5633     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5634   }
5635
5636   // COLORS
5637   if (aMapOfArgs.Find ("xnamecolor", aValues))
5638   {
5639     if (!GetColor (aValues->Value(1), aColor))
5640     {
5641       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
5642       return 1;
5643     }
5644     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
5645   }
5646   if (aMapOfArgs.Find ("ynamecolor", aValues))
5647   {
5648     if (!GetColor (aValues->Value(1), aColor))
5649     {
5650       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
5651       return 1;
5652     }
5653     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
5654   }
5655   if (aMapOfArgs.Find ("znamecolor", aValues))
5656   {
5657     if (!GetColor (aValues->Value(1), aColor))
5658     {
5659       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
5660       return 1;
5661     }
5662     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
5663   }
5664   if (aMapOfArgs.Find ("xcolor", aValues))
5665   {
5666     if (!GetColor (aValues->Value(1), aColor))
5667     {
5668       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
5669       return 1;
5670     }
5671     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
5672   }
5673   if (aMapOfArgs.Find ("ycolor", aValues))
5674   {
5675     if (!GetColor (aValues->Value(1), aColor))
5676     {
5677       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
5678       return 1;
5679     }
5680     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
5681   }
5682   if (aMapOfArgs.Find ("zcolor", aValues))
5683   {
5684     if (!GetColor (aValues->Value(1), aColor))
5685     {
5686       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
5687       return 1;
5688     }
5689     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
5690   }
5691
5692   // TICKMARKS
5693   if (aMapOfArgs.Find ("xticks", aValues))
5694   {
5695     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5696   }
5697   if (aMapOfArgs.Find ("yticks", aValues))
5698   {
5699     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5700   }
5701   if (aMapOfArgs.Find ("zticks", aValues))
5702   {
5703     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5704   }
5705   if (aMapOfArgs.Find ("xticklength", aValues))
5706   {
5707     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5708   }
5709   if (aMapOfArgs.Find ("yticklength", aValues))
5710   {
5711     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5712   }
5713   if (aMapOfArgs.Find ("zticklength", aValues))
5714   {
5715     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5716   }
5717   if (aMapOfArgs.Find ("xdrawticks", aValues))
5718   {
5719     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5720   }
5721   if (aMapOfArgs.Find ("ydrawticks", aValues))
5722   {
5723     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5724   }
5725   if (aMapOfArgs.Find ("zdrawticks", aValues))
5726   {
5727     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5728   }
5729
5730   // VALUES
5731   if (aMapOfArgs.Find ("xdrawvalues", aValues))
5732   {
5733     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5734   }
5735   if (aMapOfArgs.Find ("ydrawvalues", aValues))
5736   {
5737     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5738   }
5739   if (aMapOfArgs.Find ("zdrawvalues", aValues))
5740   {
5741     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5742   }
5743   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
5744   {
5745     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5746   }
5747   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
5748   {
5749     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5750   }
5751   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
5752   {
5753     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5754   }
5755
5756   // ARROWS
5757   if (aMapOfArgs.Find ("arrowlength", aValues))
5758   {
5759     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
5760   }
5761
5762   // FONTS
5763   if (aMapOfArgs.Find ("namefont", aValues))
5764   {
5765     aTrihedronData.SetNamesFont (aValues->Value(1));
5766   }
5767   if (aMapOfArgs.Find ("valuesfont", aValues))
5768   {
5769     aTrihedronData.SetValuesFont (aValues->Value(1));
5770   }
5771
5772   if (aMapOfArgs.Find ("drawgrid", aValues))
5773   {
5774     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
5775   }
5776   if (aMapOfArgs.Find ("drawaxes", aValues))
5777   {
5778     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
5779   }
5780
5781   // The final step: display of erase trihedron
5782   if (toDisplay)
5783   {
5784     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
5785   }
5786   else
5787   {
5788     ViewerTest::CurrentView()->GraduatedTrihedronErase();
5789   }
5790
5791   ViewerTest::GetAISContext()->UpdateCurrentViewer();
5792   ViewerTest::CurrentView()->Redraw();
5793
5794   return 0;
5795 }
5796
5797 //==============================================================================
5798 //function : VTile
5799 //purpose  :
5800 //==============================================================================
5801 static int VTile (Draw_Interpretor& theDI,
5802                   Standard_Integer  theArgNb,
5803                   const char**      theArgVec)
5804 {
5805   Handle(V3d_View) aView = ViewerTest::CurrentView();
5806   if (aView.IsNull())
5807   {
5808     std::cerr << "Error: no active viewer.\n";
5809     return 1;
5810   }
5811
5812   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
5813   if (theArgNb < 2)
5814   {
5815     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
5816           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
5817           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
5818     return 0;
5819   }
5820
5821   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
5822   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5823   {
5824     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5825     anArg.LowerCase();
5826     if (anArg == "-lowerleft"
5827      || anArg == "-upperleft")
5828     {
5829       if (anArgIter + 3 < theArgNb)
5830       {
5831         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5832         return 1;
5833       }
5834       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
5835       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5836       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5837     }
5838     else if (anArg == "-total"
5839           || anArg == "-totalsize"
5840           || anArg == "-viewsize")
5841     {
5842       if (anArgIter + 3 < theArgNb)
5843       {
5844         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5845         return 1;
5846       }
5847       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5848       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5849       if (aTile.TotalSize.x() < 1
5850        || aTile.TotalSize.y() < 1)
5851       {
5852         std::cerr << "Error: total size is incorrect.\n";
5853         return 1;
5854       }
5855     }
5856     else if (anArg == "-tilesize")
5857     {
5858       if (anArgIter + 3 < theArgNb)
5859       {
5860         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5861         return 1;
5862       }
5863
5864       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5865       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5866       if (aTile.TileSize.x() < 1
5867        || aTile.TileSize.y() < 1)
5868       {
5869         std::cerr << "Error: tile size is incorrect.\n";
5870         return 1;
5871       }
5872     }
5873     else if (anArg == "-unset")
5874     {
5875       aView->Camera()->SetTile (Graphic3d_CameraTile());
5876       aView->Redraw();
5877       return 0;
5878     }
5879   }
5880
5881   if (aTile.TileSize.x() < 1
5882    || aTile.TileSize.y() < 1)
5883   {
5884     std::cerr << "Error: tile size is undefined.\n";
5885     return 1;
5886   }
5887   else if (aTile.TotalSize.x() < 1
5888         || aTile.TotalSize.y() < 1)
5889   {
5890     std::cerr << "Error: total size is undefined.\n";
5891     return 1;
5892   }
5893
5894   aView->Camera()->SetTile (aTile);
5895   aView->Redraw();
5896   return 0;
5897 }
5898
5899 //! Format ZLayer ID.
5900 inline const char* formZLayerId (const Standard_Integer theLayerId)
5901 {
5902   switch (theLayerId)
5903   {
5904     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
5905     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
5906     case Graphic3d_ZLayerId_Top:     return "[TOP]";
5907     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
5908     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
5909     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
5910   }
5911   return "";
5912 }
5913
5914 //! Print the ZLayer information.
5915 inline void printZLayerInfo (Draw_Interpretor& theDI,
5916                              const Graphic3d_ZLayerSettings& theLayer)
5917 {
5918   if (!theLayer.Name().IsEmpty())
5919   {
5920     theDI << "  Name: " << theLayer.Name() << "\n";
5921   }
5922   if (theLayer.IsImmediate())
5923   {
5924     theDI << "  Immediate: TRUE\n";
5925   }
5926   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
5927   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
5928   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
5929   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
5930   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
5931   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
5932   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
5933   {
5934     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
5935   }
5936 }
5937
5938 //==============================================================================
5939 //function : VZLayer
5940 //purpose  : Test z layer operations for v3d viewer
5941 //==============================================================================
5942 static int VZLayer (Draw_Interpretor& theDI,
5943                     Standard_Integer  theArgNb,
5944                     const char**      theArgVec)
5945 {
5946   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5947   if (aContextAIS.IsNull())
5948   {
5949     std::cout << "No active viewer!\n";
5950     return 1;
5951   }
5952
5953   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
5954   if (theArgNb < 2)
5955   {
5956     TColStd_SequenceOfInteger aLayers;
5957     aViewer->GetAllZLayers (aLayers);
5958     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5959     {
5960       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
5961       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
5962       printZLayerInfo (theDI, aSettings);
5963     }
5964     return 1;
5965   }
5966
5967   Standard_Integer anArgIter = 1;
5968   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5969   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
5970   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5971   {
5972     ++anArgIter;
5973   }
5974
5975   {
5976     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
5977     if (aFirstArg.IsIntegerValue())
5978     {
5979       ++anArgIter;
5980       aLayerId = aFirstArg.IntegerValue();
5981     }
5982     else
5983     {
5984       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
5985       {
5986         ++anArgIter;
5987       }
5988     }
5989   }
5990
5991   for (; anArgIter < theArgNb; ++anArgIter)
5992   {
5993     // perform operation
5994     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5995     anArg.LowerCase();
5996     if (anUpdateTool.parseRedrawMode (anArg))
5997     {
5998       //
5999     }
6000     else if (anArg == "-add"
6001           || anArg == "add")
6002     {
6003       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
6004       if (!aViewer->AddZLayer (aLayerId))
6005       {
6006         std::cout << "Error: can not add a new z layer!\n";
6007         return 0;
6008       }
6009
6010       theDI << aLayerId;
6011     }
6012     else if (anArg == "-del"
6013           || anArg == "-delete"
6014           || anArg == "del")
6015     {
6016       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
6017       {
6018         if (++anArgIter >= theArgNb)
6019         {
6020           std::cout << "Syntax error: id of z layer to remove is missing\n";
6021           return 1;
6022         }
6023
6024         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
6025       }
6026
6027       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
6028        || aLayerId == Graphic3d_ZLayerId_Default
6029        || aLayerId == Graphic3d_ZLayerId_Top
6030        || aLayerId == Graphic3d_ZLayerId_Topmost
6031        || aLayerId == Graphic3d_ZLayerId_TopOSD
6032        || aLayerId == Graphic3d_ZLayerId_BotOSD)
6033       {
6034         std::cout << "Syntax error: standard Z layer can not be removed\n";
6035         return 1;
6036       }
6037
6038       // move all object displayed in removing layer to default layer
6039       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
6040            anObjIter.More(); anObjIter.Next())
6041       {
6042         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
6043         if (aPrs.IsNull()
6044          || aPrs->ZLayer() != aLayerId)
6045         {
6046           continue;
6047         }
6048         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
6049       }
6050
6051       if (!aViewer->RemoveZLayer (aLayerId))
6052       {
6053         std::cout << "Z layer can not be removed!\n";
6054       }
6055       else
6056       {
6057         theDI << aLayerId << " ";
6058       }
6059     }
6060     else if (anArg == "-get"
6061           || anArg == "get")
6062     {
6063       TColStd_SequenceOfInteger aLayers;
6064       aViewer->GetAllZLayers (aLayers);
6065       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
6066       {
6067         theDI << aLayeriter.Value() << " ";
6068       }
6069
6070       theDI << "\n";
6071     }
6072     else if (anArg == "-name")
6073     {
6074       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
6075       {
6076         std::cout << "Syntax error: id of Z layer is missing\n";
6077         return 1;
6078       }
6079
6080       if (++anArgIter >= theArgNb)
6081       {
6082         std::cout << "Syntax error: name is missing\n";
6083         return 1;
6084       }
6085
6086       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
6087       aSettings.SetName (theArgVec[anArgIter]);
6088       aViewer->SetZLayerSettings (aLayerId, aSettings);
6089     }
6090     else if (anArg == "-origin")
6091     {
6092       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
6093       {
6094         std::cout << "Syntax error: id of Z layer is missing\n";
6095         return 1;
6096       }
6097
6098       if (anArgIter + 2 >= theArgNb)
6099       {
6100         std::cout << "Syntax error: origin coordinates are missing\n";
6101         return 1;
6102       }
6103
6104       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
6105       gp_XYZ anOrigin;
6106       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
6107       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
6108       anOrigin.SetZ (0.0);
6109       if (anArgIter + 3 < theArgNb)
6110       {
6111         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
6112         anArgIter += 3;
6113       }
6114       else
6115       {
6116         anArgIter += 2;
6117       }
6118       aSettings.SetOrigin (anOrigin);
6119       aViewer->SetZLayerSettings (aLayerId, aSettings);
6120     }
6121     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
6122           && anArgIter + 1 < theArgNb
6123           && (anArg == "-cullingdistance"
6124            || anArg == "-cullingdist"
6125            || anArg == "-culldistance"
6126            || anArg == "-culldist"
6127            || anArg == "-distcull"
6128            || anArg == "-distculling"
6129            || anArg == "-distanceculling"))
6130     {
6131       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
6132       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
6133       aSettings.SetCullingDistance (aDist);
6134       aViewer->SetZLayerSettings (aLayerId, aSettings);
6135     }
6136     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
6137           && anArgIter + 1 < theArgNb
6138           && (anArg == "-cullingsize"
6139            || anArg == "-cullsize"
6140            || anArg == "-sizecull"
6141            || anArg == "-sizeculling"))
6142     {
6143       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
6144       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
6145       aSettings.SetCullingSize (aSize);
6146       aViewer->SetZLayerSettings (aLayerId, aSettings);
6147     }
6148     else if (anArg == "-settings"
6149           || anArg == "settings")
6150     {
6151       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
6152       {
6153         if (++anArgIter >= theArgNb)
6154         {
6155           std::cout << "Syntax error: id of Z layer is missing\n";
6156           return 1;
6157         }
6158
6159         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
6160       }
6161
6162       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
6163       printZLayerInfo (theDI, aSettings);
6164     }
6165     else if (anArg == "-enable"
6166           || anArg == "enable"
6167           || anArg == "-disable"
6168           || anArg == "disable")
6169     {
6170       const Standard_Boolean toEnable = anArg == "-enable"
6171                                      || anArg == "enable";
6172       if (++anArgIter >= theArgNb)
6173       {
6174         std::cout << "Syntax error: option name is missing\n";
6175         return 1;
6176       }
6177
6178       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
6179       aSubOp.LowerCase();
6180       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
6181       {
6182         if (++anArgIter >= theArgNb)
6183         {
6184           std::cout << "Syntax error: id of Z layer is missing\n";
6185           return 1;
6186         }
6187
6188         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
6189       }
6190
6191       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
6192       if (aSubOp == "depthtest"
6193        || aSubOp == "test")
6194       {
6195         aSettings.SetEnableDepthTest (toEnable);
6196       }
6197       else if (aSubOp == "depthwrite"
6198             || aSubOp == "write")
6199       {
6200         aSettings.SetEnableDepthWrite (toEnable);
6201       }
6202       else if (aSubOp == "depthclear"
6203             || aSubOp == "clear")
6204       {
6205         aSettings.SetClearDepth (toEnable);
6206       }
6207       else if (aSubOp == "depthoffset"
6208             || aSubOp == "offset")
6209       {
6210         Graphic3d_PolygonOffset aParams;
6211         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
6212         if (toEnable)
6213         {
6214           if (anArgIter + 2 >= theArgNb)
6215           {
6216             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
6217             return 1;
6218           }
6219
6220           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
6221           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
6222         }
6223         aSettings.SetPolygonOffset (aParams);
6224       }
6225       else if (aSubOp == "positiveoffset"
6226             || aSubOp == "poffset")
6227       {
6228         if (toEnable)
6229         {
6230           aSettings.SetDepthOffsetPositive();
6231         }
6232         else
6233         {
6234           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
6235         }
6236       }
6237       else if (aSubOp == "negativeoffset"
6238             || aSubOp == "noffset")
6239       {
6240         if (toEnable)
6241         {
6242           aSettings.SetDepthOffsetNegative();
6243         }
6244         else
6245         {
6246           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
6247         }
6248       }
6249       else if (aSubOp == "textureenv")
6250       {
6251         aSettings.SetEnvironmentTexture (toEnable);
6252       }
6253
6254       aViewer->SetZLayerSettings (aLayerId, aSettings);
6255     }
6256     else
6257     {
6258       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
6259       return 1;
6260     }
6261   }
6262
6263   return 0;
6264 }
6265
6266 // The interactive presentation of 2d layer item
6267 // for "vlayerline" command it provides a presentation of
6268 // line with user-defined linewidth, linetype and transparency.
6269 class V3d_LineItem : public AIS_InteractiveObject
6270 {
6271 public:
6272   // CASCADE RTTI
6273   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
6274
6275   // constructor
6276   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
6277                                Standard_Real X2, Standard_Real Y2,
6278                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
6279                                Standard_Real theWidth    = 0.5,
6280                                Standard_Real theTransp   = 1.0);
6281
6282   private:
6283
6284   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
6285                 const Handle(Prs3d_Presentation)& thePresentation,
6286                 const Standard_Integer theMode) Standard_OVERRIDE;
6287
6288   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
6289                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
6290   {}
6291
6292 private:
6293
6294   Standard_Real       myX1, myY1, myX2, myY2;
6295   Aspect_TypeOfLine   myType;
6296   Standard_Real       myWidth;
6297 };
6298
6299 // default constructor for line item
6300 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
6301                            Standard_Real X2, Standard_Real Y2,
6302                            Aspect_TypeOfLine theType,
6303                            Standard_Real theWidth,
6304                            Standard_Real theTransp) :
6305   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
6306   myType(theType), myWidth(theWidth)
6307 {
6308   SetTransparency (1-theTransp);
6309 }
6310
6311 // render line
6312 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
6313                             const Handle(Prs3d_Presentation)& thePresentation,
6314                             const Standard_Integer /*theMode*/)
6315 {
6316   thePresentation->Clear();
6317   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
6318   Standard_Integer aWidth, aHeight;
6319   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
6320   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
6321   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
6322   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
6323   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
6324   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
6325   aGroup->SetPrimitivesAspect (anAspect->Aspect());
6326   aGroup->AddPrimitiveArray (aPrim);
6327 }
6328
6329 //=============================================================================
6330 //function : VLayerLine
6331 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
6332 //         : linewidth, transparency coefficient
6333 //============================================================================
6334 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
6335 {
6336   // get the active view
6337   Handle(V3d_View) aView = ViewerTest::CurrentView();
6338   if (aView.IsNull())
6339   {
6340     di << "Call vinit before!\n";
6341     return 1;
6342   }
6343   else if (argc < 5)
6344   {
6345     di << "Use: " << argv[0];
6346     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
6347     di << " linetype : { 0 | 1 | 2 | 3 } \n";
6348     di << "              0 - solid  \n";
6349     di << "              1 - dashed \n";
6350     di << "              2 - dot    \n";
6351     di << "              3 - dashdot\n";
6352     di << " transparency : { 0.0 - 1.0 } \n";
6353     di << "                  0.0 - transparent\n";
6354     di << "                  1.0 - visible    \n";
6355     return 1;
6356   }
6357
6358   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6359   // get the input params
6360   Standard_Real X1 = Draw::Atof(argv[1]);
6361   Standard_Real Y1 = Draw::Atof(argv[2]);
6362   Standard_Real X2 = Draw::Atof(argv[3]);
6363   Standard_Real Y2 = Draw::Atof(argv[4]);
6364
6365   Standard_Real aWidth = 0.5;
6366   Standard_Real aTransparency = 1.0;
6367
6368   // has width
6369   if (argc > 5)
6370     aWidth = Draw::Atof(argv[5]);
6371
6372   // select appropriate line type
6373   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
6374   if (argc > 6
6375   && !ViewerTest::ParseLineType (argv[6], aLineType))
6376   {
6377     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
6378     return 1;
6379   }
6380
6381   // has transparency
6382   if (argc > 7)
6383   {
6384     aTransparency = Draw::Atof(argv[7]);
6385     if (aTransparency < 0 || aTransparency > 1.0)
6386       aTransparency = 1.0;
6387   }
6388
6389   static Handle (V3d_LineItem) aLine;
6390   if (!aLine.IsNull())
6391   {
6392     aContext->Erase (aLine, Standard_False);
6393   }
6394   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
6395                             aLineType, aWidth,
6396                             aTransparency);
6397
6398   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
6399   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
6400   aLine->SetToUpdate();
6401   aContext->Display (aLine, Standard_True);
6402
6403   return 0;
6404 }
6405
6406
6407 //==============================================================================
6408 //function : VGrid
6409 //purpose  :
6410 //==============================================================================
6411
6412 static int VGrid (Draw_Interpretor& /*theDI*/,
6413                   Standard_Integer  theArgNb,
6414                   const char**      theArgVec)
6415 {
6416   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
6417   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6418   if (aView.IsNull() || aViewer.IsNull())
6419   {
6420     std::cerr << "Error: no active view\n";
6421     return 1;
6422   }
6423
6424   Aspect_GridType     aType = aViewer->GridType();
6425   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
6426   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
6427   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
6428   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
6429   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6430   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6431   {
6432     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6433     anArg.LowerCase();
6434     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
6435     {
6436       continue;
6437     }
6438     else if (anArgIter + 1 < theArgNb
6439           && anArg == "-type")
6440     {
6441       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
6442       anArgNext.LowerCase();
6443       if (anArgNext == "r"
6444        || anArgNext == "rect"
6445        || anArgNext == "rectangular")
6446       {
6447         aType = Aspect_GT_Rectangular;
6448       }
6449       else if (anArgNext == "c"
6450             || anArgNext == "circ"
6451             || anArgNext == "circular")
6452       {
6453         aType = Aspect_GT_Circular;
6454       }
6455       else
6456       {
6457         std::cout << "Syntax error at '" << anArgNext << "'\n";
6458         return 1;
6459       }
6460     }
6461     else if (anArgIter + 1 < theArgNb
6462           && anArg == "-mode")
6463     {
6464       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
6465       anArgNext.LowerCase();
6466       if (anArgNext == "l"
6467        || anArgNext == "line"
6468        || anArgNext == "lines")
6469       {
6470         aMode = Aspect_GDM_Lines;
6471       }
6472       else if (anArgNext == "p"
6473             || anArgNext == "point"
6474             || anArgNext == "points")
6475       {
6476         aMode = Aspect_GDM_Points;
6477       }
6478       else
6479       {
6480         std::cout << "Syntax error at '" << anArgNext << "'\n";
6481         return 1;
6482       }
6483     }
6484     else if (anArgIter + 2 < theArgNb
6485           && (anArg == "-origin"
6486            || anArg == "-orig"))
6487     {
6488       hasOrigin = true;
6489       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6490                               Draw::Atof (theArgVec[anArgIter + 2]));
6491       anArgIter += 2;
6492     }
6493     else if (anArgIter + 2 < theArgNb
6494           && anArg == "-step")
6495     {
6496       hasStep = true;
6497       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6498                             Draw::Atof (theArgVec[anArgIter + 2]));
6499       if (aNewStepXY.x() <= 0.0
6500        || aNewStepXY.y() <= 0.0)
6501       {
6502         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6503         return 1;
6504       }
6505       anArgIter += 2;
6506     }
6507     else if (anArgIter + 1 < theArgNb
6508           && (anArg == "-angle"
6509            || anArg == "-rotangle"
6510            || anArg == "-rotationangle"))
6511     {
6512       hasRotAngle = true;
6513       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
6514     }
6515     else if (anArgIter + 1 < theArgNb
6516           && (anArg == "-zoffset"
6517            || anArg == "-dz"))
6518     {
6519       hasZOffset = true;
6520       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
6521     }
6522     else if (anArgIter + 1 < theArgNb
6523           && anArg == "-radius")
6524     {
6525       hasSize = true;
6526       ++anArgIter;
6527       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
6528       if (aNewStepXY.x() <= 0.0)
6529       {
6530         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
6531         return 1;
6532       }
6533     }
6534     else if (anArgIter + 2 < theArgNb
6535           && anArg == "-size")
6536     {
6537       hasSize = true;
6538       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6539                             Draw::Atof (theArgVec[anArgIter + 2]));
6540       if (aNewStepXY.x() <= 0.0
6541        || aNewStepXY.y() <= 0.0)
6542       {
6543         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6544         return 1;
6545       }
6546       anArgIter += 2;
6547     }
6548     else if (anArg == "r"
6549           || anArg == "rect"
6550           || anArg == "rectangular")
6551     {
6552       aType = Aspect_GT_Rectangular;
6553     }
6554     else if (anArg == "c"
6555           || anArg == "circ"
6556           || anArg == "circular")
6557     {
6558       aType = Aspect_GT_Circular;
6559     }
6560     else if (anArg == "l"
6561           || anArg == "line"
6562           || anArg == "lines")
6563     {
6564       aMode = Aspect_GDM_Lines;
6565     }
6566     else if (anArg == "p"
6567           || anArg == "point"
6568           || anArg == "points")
6569     {
6570       aMode = Aspect_GDM_Points;
6571     }
6572     else if (anArgIter + 1 >= theArgNb
6573           && anArg == "off")
6574     {
6575       aViewer->DeactivateGrid();
6576       return 0;
6577     }
6578     else
6579     {
6580       std::cout << "Syntax error at '" << anArg << "'\n";
6581       return 1;
6582     }
6583   }
6584
6585   if (aType == Aspect_GT_Rectangular)
6586   {
6587     Graphic3d_Vec2d anOrigXY, aStepXY;
6588     Standard_Real aRotAngle = 0.0;
6589     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6590     if (hasOrigin)
6591     {
6592       anOrigXY = aNewOriginXY;
6593     }
6594     if (hasStep)
6595     {
6596       aStepXY = aNewStepXY;
6597     }
6598     if (hasRotAngle)
6599     {
6600       aRotAngle = aNewRotAngle;
6601     }
6602     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6603     if (hasSize || hasZOffset)
6604     {
6605       Graphic3d_Vec3d aSize;
6606       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6607       if (hasSize)
6608       {
6609         aSize.x() = aNewSizeXY.x();
6610         aSize.y() = aNewSizeXY.y();
6611       }
6612       if (hasZOffset)
6613       {
6614         aSize.z() = aNewZOffset;
6615       }
6616       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6617     }
6618   }
6619   else if (aType == Aspect_GT_Circular)
6620   {
6621     Graphic3d_Vec2d anOrigXY;
6622     Standard_Real aRadiusStep;
6623     Standard_Integer aDivisionNumber;
6624     Standard_Real aRotAngle = 0.0;
6625     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6626     if (hasOrigin)
6627     {
6628       anOrigXY = aNewOriginXY;
6629     }
6630     if (hasStep)
6631     {
6632       aRadiusStep     = aNewStepXY[0];
6633       aDivisionNumber = (int )aNewStepXY[1];
6634       if (aDivisionNumber < 1)
6635       {
6636         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
6637         return 1;
6638       }
6639     }
6640     if (hasRotAngle)
6641     {
6642       aRotAngle = aNewRotAngle;
6643     }
6644
6645     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6646     if (hasSize || hasZOffset)
6647     {
6648       Standard_Real aRadius = 0.0, aZOffset = 0.0;
6649       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
6650       if (hasSize)
6651       {
6652         aRadius = aNewSizeXY.x();
6653         if (aNewSizeXY.y() != 0.0)
6654         {
6655           std::cout << "Syntax error: circular size should be specified as radius\n";
6656           return 1;
6657         }
6658       }
6659       if (hasZOffset)
6660       {
6661         aZOffset = aNewZOffset;
6662       }
6663       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
6664     }
6665   }
6666   aViewer->ActivateGrid (aType, aMode);
6667   return 0;
6668 }
6669
6670 //==============================================================================
6671 //function : VPriviledgedPlane
6672 //purpose  :
6673 //==============================================================================
6674
6675 static int VPriviledgedPlane (Draw_Interpretor& theDI,
6676                               Standard_Integer  theArgNb,
6677                               const char**      theArgVec)
6678 {
6679   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
6680   {
6681     std::cerr << "Error: wrong number of arguments! See usage:\n";
6682     theDI.PrintHelp (theArgVec[0]);
6683     return 1;
6684   }
6685
6686   // get the active viewer
6687   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6688   if (aViewer.IsNull())
6689   {
6690     std::cerr << "Error: no active viewer. Please call vinit.\n";
6691     return 1;
6692   }
6693
6694   if (theArgNb == 1)
6695   {
6696     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
6697     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
6698     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
6699     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
6700     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
6701           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
6702           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
6703     return 0;
6704   }
6705
6706   Standard_Integer anArgIdx = 1;
6707   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
6708   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
6709   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
6710   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
6711   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
6712   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
6713
6714   gp_Ax3 aPriviledgedPlane;
6715   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
6716   gp_Dir aNorm (aNormX, aNormY, aNormZ);
6717   if (theArgNb > 7)
6718   {
6719     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
6720     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
6721     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
6722     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
6723     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
6724   }
6725   else
6726   {
6727     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
6728   }
6729
6730   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
6731
6732   return 0;
6733 }
6734
6735 //==============================================================================
6736 //function : VConvert
6737 //purpose  :
6738 //==============================================================================
6739
6740 static int VConvert (Draw_Interpretor& theDI,
6741                      Standard_Integer  theArgNb,
6742                      const char**      theArgVec)
6743 {
6744   // get the active view
6745   Handle(V3d_View) aView = ViewerTest::CurrentView();
6746   if (aView.IsNull())
6747   {
6748     std::cerr << "Error: no active view. Please call vinit.\n";
6749     return 1;
6750   }
6751
6752   enum { Model, Ray, View, Window, Grid } aMode = Model;
6753
6754   // access coordinate arguments
6755   TColStd_SequenceOfReal aCoord;
6756   Standard_Integer anArgIdx = 1;
6757   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
6758   {
6759     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6760     if (!anArg.IsRealValue())
6761     {
6762       break;
6763     }
6764     aCoord.Append (anArg.RealValue());
6765   }
6766
6767   // non-numeric argument too early
6768   if (aCoord.IsEmpty())
6769   {
6770     std::cerr << "Error: wrong number of arguments! See usage:\n";
6771     theDI.PrintHelp (theArgVec[0]);
6772     return 1;
6773   }
6774
6775   // collect all other arguments and options
6776   for (; anArgIdx < theArgNb; ++anArgIdx)
6777   {
6778     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6779     anArg.LowerCase();
6780     if      (anArg == "window") aMode = Window;
6781     else if (anArg == "view")   aMode = View;
6782     else if (anArg == "grid")   aMode = Grid;
6783     else if (anArg == "ray")    aMode = Ray;
6784     else
6785     {
6786       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
6787       theDI.PrintHelp (theArgVec[0]);
6788       return 1;
6789     }
6790   }
6791
6792   // complete input checks
6793   if ((aCoord.Length() == 1 && theArgNb > 3) ||
6794       (aCoord.Length() == 2 && theArgNb > 4) ||
6795       (aCoord.Length() == 3 && theArgNb > 5))
6796   {
6797     std::cerr << "Error: wrong number of arguments! See usage:\n";
6798     theDI.PrintHelp (theArgVec[0]);
6799     return 1;
6800   }
6801
6802   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6803   Standard_Integer aXYp[2] = {0, 0};
6804
6805   // convert one-dimensional coordinate
6806   if (aCoord.Length() == 1)
6807   {
6808     switch (aMode)
6809     {
6810       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
6811       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
6812       default:
6813         std::cerr << "Error: wrong arguments! See usage:\n";
6814         theDI.PrintHelp (theArgVec[0]);
6815         return 1;
6816     }
6817   }
6818
6819   // convert 2D coordinates from projection or view reference space
6820   if (aCoord.Length() == 2)
6821   {
6822     switch (aMode)
6823     {
6824       case Model :
6825         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6826         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6827         return 0;
6828
6829       case View :
6830         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
6831         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
6832         return 0;
6833
6834       case Window :
6835         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
6836         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6837         return 0;
6838
6839       case Grid :
6840         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6841         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
6842         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6843         return 0;
6844
6845       case Ray :
6846         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
6847                                 (Standard_Integer) aCoord (2),
6848                                 aXYZ[0], aXYZ[1], aXYZ[2],
6849                                 aXYZ[3], aXYZ[4], aXYZ[5]);
6850         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6851         return 0;
6852
6853       default:
6854         std::cerr << "Error: wrong arguments! See usage:\n";
6855         theDI.PrintHelp (theArgVec[0]);
6856         return 1;
6857     }
6858   }
6859
6860   // convert 3D coordinates from view reference space
6861   else if (aCoord.Length() == 3)
6862   {
6863     switch (aMode)
6864     {
6865       case Window :
6866         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
6867         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6868         return 0;
6869
6870       case Grid :
6871         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
6872         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6873         return 0;
6874
6875       default:
6876         std::cerr << "Error: wrong arguments! See usage:\n";
6877         theDI.PrintHelp (theArgVec[0]);
6878         return 1;
6879     }
6880   }
6881
6882   return 0;
6883 }
6884
6885 //==============================================================================
6886 //function : VFps
6887 //purpose  :
6888 //==============================================================================
6889
6890 static int VFps (Draw_Interpretor& theDI,
6891                  Standard_Integer  theArgNb,
6892                  const char**      theArgVec)
6893 {
6894   // get the active view
6895   Handle(V3d_View) aView = ViewerTest::CurrentView();
6896   if (aView.IsNull())
6897   {
6898     std::cerr << "No active view. Please call vinit.\n";
6899     return 1;
6900   }
6901
6902   Standard_Integer aFramesNb = -1;
6903   Standard_Real aDuration = -1.0;
6904   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6905   {
6906     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6907     anArg.LowerCase();
6908     if (aDuration < 0.0
6909      && anArgIter + 1 < theArgNb
6910      && (anArg == "-duration"
6911       || anArg == "-dur"
6912       || anArg == "-time"))
6913     {
6914       aDuration = Draw::Atof (theArgVec[++anArgIter]);
6915     }
6916     else if (aFramesNb < 0
6917           && anArg.IsIntegerValue())
6918     {
6919       aFramesNb = anArg.IntegerValue();
6920       if (aFramesNb <= 0)
6921       {
6922         std::cerr << "Syntax error at '" << anArg << "'\n";
6923         return 1;
6924       }
6925     }
6926     else
6927     {
6928       std::cerr << "Syntax error at '" << anArg << "'\n";
6929       return 1;
6930     }
6931   }
6932   if (aFramesNb < 0 && aDuration < 0.0)
6933   {
6934     aFramesNb = 100;
6935   }
6936
6937   // the time is meaningless for first call
6938   // due to async OpenGl rendering
6939   aView->Redraw();
6940
6941   // redraw view in loop to estimate average values
6942   OSD_Timer aTimer;
6943   aTimer.Start();
6944   Standard_Integer aFrameIter = 1;
6945   for (;; ++aFrameIter)
6946   {
6947     aView->Redraw();
6948     if ((aFramesNb > 0
6949       && aFrameIter >= aFramesNb)
6950      || (aDuration > 0.0
6951       && aTimer.ElapsedTime() >= aDuration))
6952     {
6953       break;
6954     }
6955   }
6956   aTimer.Stop();
6957   Standard_Real aCpu;
6958   const Standard_Real aTime = aTimer.ElapsedTime();
6959   aTimer.OSD_Chronometer::Show (aCpu);
6960
6961   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
6962   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
6963
6964   // return statistics
6965   theDI << "FPS: " << aFpsAver << "\n"
6966         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
6967
6968   // compute additional statistics in ray-tracing mode
6969   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
6970   if (aParams.Method == Graphic3d_RM_RAYTRACING)
6971   {
6972     Graphic3d_Vec2i aWinSize (0, 0);
6973     aView->Window()->Size (aWinSize.x(), aWinSize.y());
6974
6975     // 1 shadow ray and 1 secondary ray pew each bounce
6976     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
6977     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
6978   }
6979
6980   return 0;
6981 }
6982
6983 //! Auxiliary function for parsing glsl dump level argument.
6984 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
6985                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
6986 {
6987   TCollection_AsciiString aTypeStr (theArg);
6988   aTypeStr.LowerCase();
6989   if (aTypeStr == "off"
6990    || aTypeStr == "0")
6991   {
6992     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6993   }
6994   else if (aTypeStr == "short")
6995   {
6996     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
6997   }
6998   else if (aTypeStr == "full"
6999         || aTypeStr == "1")
7000   {
7001     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
7002   }
7003   else
7004   {
7005     return Standard_False;
7006   }
7007   return Standard_True;
7008 }
7009
7010 //==============================================================================
7011 //function : VGlDebug
7012 //purpose  :
7013 //==============================================================================
7014
7015 static int VGlDebug (Draw_Interpretor& theDI,
7016                      Standard_Integer  theArgNb,
7017                      const char**      theArgVec)
7018 {
7019   Handle(OpenGl_GraphicDriver) aDriver;
7020   Handle(V3d_View) aView = ViewerTest::CurrentView();
7021   if (!aView.IsNull())
7022   {
7023     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
7024   }
7025   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
7026   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
7027
7028   if (theArgNb < 2)
7029   {
7030     TCollection_AsciiString aDebActive, aSyncActive;
7031     if (aCaps == NULL)
7032     {
7033       aCaps = aDefCaps;
7034     }
7035     else
7036     {
7037       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
7038                                                                   "GL_ARB_debug_output");
7039       aDebActive = isActive ? " (active)" : " (inactive)";
7040       if (isActive)
7041       {
7042         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
7043         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
7044       }
7045     }
7046
7047     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
7048       + "glslSourceCode: "
7049       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
7050          ? "Off"
7051          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
7052           ? "Short"
7053           : "Full")
7054       + "\n";
7055     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
7056           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
7057           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
7058           << aGlslCodeDebugStatus
7059           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
7060     return 0;
7061   }
7062
7063   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
7064   {
7065     Standard_CString        anArg     = theArgVec[anArgIter];
7066     TCollection_AsciiString anArgCase (anArg);
7067     anArgCase.LowerCase();
7068     Standard_Boolean toEnableDebug = Standard_True;
7069     if (anArgCase == "-glsl"
7070      || anArgCase == "-glslwarn"
7071      || anArgCase == "-glslwarns"
7072      || anArgCase == "-glslwarnings")
7073     {
7074       Standard_Boolean toShowWarns = Standard_True;
7075       if (++anArgIter < theArgNb
7076       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
7077       {
7078         --anArgIter;
7079       }
7080       aDefCaps->glslWarnings = toShowWarns;
7081       if (aCaps != NULL)
7082       {
7083         aCaps->glslWarnings = toShowWarns;
7084       }
7085     }
7086     else if (anArgCase == "-extra"
7087           || anArgCase == "-extramsg"
7088           || anArgCase == "-extramessages")
7089     {
7090       Standard_Boolean toShow = Standard_True;
7091       if (++anArgIter < theArgNb
7092       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
7093       {
7094         --anArgIter;
7095       }
7096       aDefCaps->suppressExtraMsg = !toShow;
7097       if (aCaps != NULL)
7098       {
7099         aCaps->suppressExtraMsg = !toShow;
7100       }
7101     }
7102     else if (anArgCase == "-noextra"
7103           || anArgCase == "-noextramsg"
7104           || anArgCase == "-noextramessages")
7105     {
7106       Standard_Boolean toSuppress = Standard_True;
7107       if (++anArgIter < theArgNb
7108       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
7109       {
7110         --anArgIter;
7111       }
7112       aDefCaps->suppressExtraMsg = toSuppress;
7113       if (aCaps != NULL)
7114       {
7115         aCaps->suppressExtraMsg = toSuppress;
7116       }
7117     }
7118     else if (anArgCase == "-sync")
7119     {
7120       Standard_Boolean toSync = Standard_True;
7121       if (++anArgIter < theArgNb
7122       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
7123       {
7124         --anArgIter;
7125       }
7126       aDefCaps->contextSyncDebug = toSync;
7127       if (toSync)
7128       {
7129         aDefCaps->contextDebug = Standard_True;
7130       }
7131     }
7132     else if (anArgCase == "-glslsourcecode"
7133           || anArgCase == "-glslcode")
7134     {
7135       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
7136       if (++anArgIter < theArgNb
7137       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
7138       {
7139         --anArgIter;
7140       }
7141       aDefCaps->glslDumpLevel = aGslsDumpLevel;
7142       if (aCaps != NULL)
7143       {
7144         aCaps->glslDumpLevel = aGslsDumpLevel;
7145       }
7146     }
7147     else if (anArgCase == "-debug")
7148     {
7149       if (++anArgIter < theArgNb
7150       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
7151       {
7152         --anArgIter;
7153       }
7154       aDefCaps->contextDebug = toEnableDebug;
7155     }
7156     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
7157           && (anArgIter + 1 == theArgNb))
7158     {
7159       // simple alias to turn on almost everything
7160       aDefCaps->contextDebug     = toEnableDebug;
7161       aDefCaps->contextSyncDebug = toEnableDebug;
7162       aDefCaps->glslWarnings     = toEnableDebug;
7163       if (!toEnableDebug)
7164       {
7165         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
7166       }
7167       aDefCaps->suppressExtraMsg = !toEnableDebug;
7168       if (aCaps != NULL)
7169       {
7170         aCaps->contextDebug     = toEnableDebug;
7171         aCaps->contextSyncDebug = toEnableDebug;
7172         aCaps->glslWarnings     = toEnableDebug;
7173         if (!toEnableDebug)
7174         {
7175           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
7176         }
7177         aCaps->suppressExtraMsg = !toEnableDebug;
7178       }
7179     }
7180     else
7181     {
7182       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
7183       return 1;
7184     }
7185   }
7186
7187   return 0;
7188 }
7189
7190 //==============================================================================
7191 //function : VVbo
7192 //purpose  :
7193 //==============================================================================
7194
7195 static int VVbo (Draw_Interpretor& theDI,
7196                  Standard_Integer  theArgNb,
7197                  const char**      theArgVec)
7198 {
7199   const Standard_Boolean toSet    = (theArgNb > 1);
7200   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
7201   if (toSet)
7202   {
7203     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
7204   }
7205
7206   // get the context
7207   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
7208   if (aContextAIS.IsNull())
7209   {
7210     if (!toSet)
7211     {
7212       std::cerr << "No active view!\n";
7213     }
7214     return 1;
7215   }
7216   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
7217   if (!aDriver.IsNull())
7218   {
7219     if (!toSet)
7220     {
7221       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
7222     }
7223     else
7224     {
7225       aDriver->ChangeOptions().vboDisable = toUseVbo;
7226     }
7227   }
7228
7229   return 0;
7230 }
7231
7232 //==============================================================================
7233 //function : VCaps
7234 //purpose  :
7235 //==============================================================================
7236
7237 static int VCaps (Draw_Interpretor& theDI,
7238                   Standard_Integer  theArgNb,
7239                   const char**      theArgVec)
7240 {
7241   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
7242   Handle(OpenGl_GraphicDriver)   aDriver;
7243   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7244   if (!aContext.IsNull())
7245   {
7246     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
7247     aCaps   = &aDriver->ChangeOptions();
7248   }
7249
7250   if (theArgNb < 2)
7251   {
7252     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
7253     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
7254     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
7255     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
7256     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
7257     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
7258     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
7259     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
7260     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
7261     return 0;
7262   }
7263
7264   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
7265   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
7266   {
7267     Standard_CString        anArg     = theArgVec[anArgIter];
7268     TCollection_AsciiString anArgCase (anArg);
7269     anArgCase.LowerCase();
7270     if (anUpdateTool.parseRedrawMode (anArg))
7271     {
7272       continue;
7273     }
7274     else if (anArgCase == "-vsync"
7275           || anArgCase == "-swapinterval")
7276     {
7277       Standard_Boolean toEnable = Standard_True;
7278       if (++anArgIter < theArgNb
7279       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7280       {
7281         --anArgIter;
7282       }
7283       aCaps->swapInterval = toEnable;
7284     }
7285     else if (anArgCase == "-ffp")
7286     {
7287       Standard_Boolean toEnable = Standard_True;
7288       if (++anArgIter < theArgNb
7289       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7290       {
7291         --anArgIter;
7292       }
7293       aCaps->ffpEnable = toEnable;
7294     }
7295     else if (anArgCase == "-polygonmode")
7296     {
7297       Standard_Boolean toEnable = Standard_True;
7298       if (++anArgIter < theArgNb
7299       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7300       {
7301         --anArgIter;
7302       }
7303       aCaps->usePolygonMode = toEnable;
7304     }
7305     else if (anArgCase == "-vbo")
7306     {
7307       Standard_Boolean toEnable = Standard_True;
7308       if (++anArgIter < theArgNb
7309       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7310       {
7311         --anArgIter;
7312       }
7313       aCaps->vboDisable = !toEnable;
7314     }
7315     else if (anArgCase == "-sprite"
7316           || anArgCase == "-sprites")
7317     {
7318       Standard_Boolean toEnable = Standard_True;
7319       if (++anArgIter < theArgNb
7320       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7321       {
7322         --anArgIter;
7323       }
7324       aCaps->pntSpritesDisable = !toEnable;
7325     }
7326     else if (anArgCase == "-softmode")
7327     {
7328       Standard_Boolean toEnable = Standard_True;
7329       if (++anArgIter < theArgNb
7330       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7331       {
7332         --anArgIter;
7333       }
7334       aCaps->contextNoAccel = toEnable;
7335     }
7336     else if (anArgCase == "-winbuffer"
7337           || anArgCase == "-windowbuffer"
7338           || anArgCase == "-usewinbuffer"
7339           || anArgCase == "-usewindowbuffer"
7340           || anArgCase == "-usesystembuffer")
7341     {
7342       Standard_Boolean toEnable = Standard_True;
7343       if (++anArgIter < theArgNb
7344       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7345       {
7346         --anArgIter;
7347       }
7348       aCaps->useSystemBuffer = toEnable;
7349     }
7350     else if (anArgCase == "-accel"
7351           || anArgCase == "-acceleration")
7352     {
7353       Standard_Boolean toEnable = Standard_True;
7354       if (++anArgIter < theArgNb
7355       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7356       {
7357         --anArgIter;
7358       }
7359       aCaps->contextNoAccel = !toEnable;
7360     }
7361     else if (anArgCase == "-compat"
7362           || anArgCase == "-compatprofile"
7363           || anArgCase == "-compatible"
7364           || anArgCase == "-compatibleprofile")
7365     {
7366       Standard_Boolean toEnable = Standard_True;
7367       if (++anArgIter < theArgNb
7368       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7369       {
7370         --anArgIter;
7371       }
7372       aCaps->contextCompatible = toEnable;
7373       if (!aCaps->contextCompatible)
7374       {
7375         aCaps->ffpEnable = Standard_False;
7376       }
7377     }
7378     else if (anArgCase == "-core"
7379           || anArgCase == "-coreprofile")
7380     {
7381       Standard_Boolean toEnable = Standard_True;
7382       if (++anArgIter < theArgNb
7383       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7384       {
7385         --anArgIter;
7386       }
7387       aCaps->contextCompatible = !toEnable;
7388       if (!aCaps->contextCompatible)
7389       {
7390         aCaps->ffpEnable = Standard_False;
7391       }
7392     }
7393     else if (anArgCase == "-stereo"
7394           || anArgCase == "-quadbuffer")
7395     {
7396       Standard_Boolean toEnable = Standard_True;
7397       if (++anArgIter < theArgNb
7398       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7399       {
7400         --anArgIter;
7401       }
7402       aCaps->contextStereo = toEnable;
7403     }
7404     else
7405     {
7406       std::cout << "Error: unknown argument '" << anArg << "'\n";
7407       return 1;
7408     }
7409   }
7410   if (aCaps != &ViewerTest_myDefaultCaps)
7411   {
7412     ViewerTest_myDefaultCaps = *aCaps;
7413   }
7414   return 0;
7415 }
7416
7417 //==============================================================================
7418 //function : VMemGpu
7419 //purpose  :
7420 //==============================================================================
7421
7422 static int VMemGpu (Draw_Interpretor& theDI,
7423                     Standard_Integer  theArgNb,
7424                     const char**      theArgVec)
7425 {
7426   // get the context
7427   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
7428   if (aContextAIS.IsNull())
7429   {
7430     std::cerr << "No active view. Please call vinit.\n";
7431     return 1;
7432   }
7433
7434   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
7435   if (aDriver.IsNull())
7436   {
7437     std::cerr << "Graphic driver not available.\n";
7438     return 1;
7439   }
7440
7441   Standard_Size aFreeBytes = 0;
7442   TCollection_AsciiString anInfo;
7443   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
7444   {
7445     std::cerr << "Information not available.\n";
7446     return 1;
7447   }
7448
7449   if (theArgNb > 1 && *theArgVec[1] == 'f')
7450   {
7451     theDI << Standard_Real (aFreeBytes);
7452   }
7453   else
7454   {
7455     theDI << anInfo;
7456   }
7457
7458   return 0;
7459 }
7460
7461 // ==============================================================================
7462 // function : VReadPixel
7463 // purpose  :
7464 // ==============================================================================
7465 static int VReadPixel (Draw_Interpretor& theDI,
7466                        Standard_Integer  theArgNb,
7467                        const char**      theArgVec)
7468 {
7469   // get the active view
7470   Handle(V3d_View) aView = ViewerTest::CurrentView();
7471   if (aView.IsNull())
7472   {
7473     std::cerr << "No active view. Please call vinit.\n";
7474     return 1;
7475   }
7476   else if (theArgNb < 3)
7477   {
7478     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
7479     return 1;
7480   }
7481
7482   Image_Format         aFormat     = Image_Format_RGBA;
7483   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
7484
7485   Standard_Integer aWidth, aHeight;
7486   aView->Window()->Size (aWidth, aHeight);
7487   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
7488   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
7489   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
7490   {
7491     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
7492     return 1;
7493   }
7494
7495   Standard_Boolean toShowName = Standard_False;
7496   Standard_Boolean toShowHls  = Standard_False;
7497   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
7498   {
7499     TCollection_AsciiString aParam (theArgVec[anIter]);
7500     aParam.LowerCase();
7501     if (aParam == "-rgb"
7502      || aParam == "rgb")
7503     {
7504       aFormat     = Image_Format_RGB;
7505       aBufferType = Graphic3d_BT_RGB;
7506     }
7507     else if (aParam == "-hls"
7508           || aParam == "hls")
7509     {
7510       aFormat     = Image_Format_RGB;
7511       aBufferType = Graphic3d_BT_RGB;
7512       toShowHls   = Standard_True;
7513     }
7514     else if (aParam == "-rgbf"
7515           || aParam == "rgbf")
7516     {
7517       aFormat     = Image_Format_RGBF;
7518       aBufferType = Graphic3d_BT_RGB;
7519     }
7520     else if (aParam == "-rgba"
7521           || aParam == "rgba")
7522     {
7523       aFormat     = Image_Format_RGBA;
7524       aBufferType = Graphic3d_BT_RGBA;
7525     }
7526     else if (aParam == "-rgbaf"
7527           || aParam == "rgbaf")
7528     {
7529       aFormat     = Image_Format_RGBAF;
7530       aBufferType = Graphic3d_BT_RGBA;
7531     }
7532     else if (aParam == "-depth"
7533           || aParam == "depth")
7534     {
7535       aFormat     = Image_Format_GrayF;
7536       aBufferType = Graphic3d_BT_Depth;
7537     }
7538     else if (aParam == "-name"
7539           || aParam == "name")
7540     {
7541       toShowName = Standard_True;
7542     }
7543     else
7544     {
7545       std::cout << "Syntax error at '" << aParam << "'\n";
7546     }
7547   }
7548
7549   Image_PixMap anImage;
7550   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
7551   {
7552     std::cerr << "Image allocation failed\n";
7553     return 1;
7554   }
7555   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
7556   {
7557     std::cerr << "Image dump failed\n";
7558     return 1;
7559   }
7560
7561   // redirect possible warning messages that could have been added by ToPixMap
7562   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
7563   // contaminate result of the command
7564   Standard_CString aWarnLog = theDI.Result();
7565   if (aWarnLog != NULL && aWarnLog[0] != '\0')
7566   {
7567     std::cout << aWarnLog << std::endl;
7568   }
7569   theDI.Reset();
7570
7571   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
7572   if (toShowName)
7573   {
7574     if (aBufferType == Graphic3d_BT_RGBA)
7575     {
7576       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
7577     }
7578     else
7579     {
7580       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
7581     }
7582   }
7583   else
7584   {
7585     switch (aBufferType)
7586     {
7587       default:
7588       case Graphic3d_BT_RGB:
7589       {
7590         if (toShowHls)
7591         {
7592           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
7593         }
7594         else
7595         {
7596           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
7597         }
7598         break;
7599       }
7600       case Graphic3d_BT_RGBA:
7601       {
7602         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
7603         break;
7604       }
7605       case Graphic3d_BT_Depth:
7606       {
7607         theDI << aColor.GetRGB().Red();
7608         break;
7609       }
7610     }
7611   }
7612
7613   return 0;
7614 }
7615
7616 //! Auxiliary presentation for an image plane.
7617 class ViewerTest_ImagePrs : public AIS_InteractiveObject
7618 {
7619 public:
7620   //! Main constructor.
7621   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
7622                        const Standard_Real theWidth,
7623                        const Standard_Real theHeight,
7624                        const TCollection_AsciiString& theLabel)
7625   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
7626   {
7627     SetDisplayMode (0);
7628     SetHilightMode (1);
7629     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
7630     {
7631       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
7632       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
7633       Graphic3d_MaterialAspect aMat;
7634       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
7635       aMat.SetAmbient  (1.0);
7636       aMat.SetDiffuse  (1.0);
7637       aMat.SetSpecular (1.0);
7638       aMat.SetEmissive (1.0);
7639       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
7640       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
7641       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
7642       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
7643       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7644       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
7645       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7646       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7647       aFillAspect->SetFrontMaterial (aMat);
7648       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
7649       aFillAspect->SetTextureMapOn();
7650     }
7651     {
7652       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
7653       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
7654       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
7655       myDrawer->SetTextAspect (aTextAspect);
7656     }
7657     {
7658       const gp_Dir aNorm (0.0, 0.0, 1.0);
7659       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
7660       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
7661       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
7662       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
7663       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
7664       myTris->AddEdge (1);
7665       myTris->AddEdge (2);
7666       myTris->AddEdge (3);
7667       myTris->AddEdge (3);
7668       myTris->AddEdge (2);
7669       myTris->AddEdge (4);
7670
7671       myRect = new Graphic3d_ArrayOfPolylines (4);
7672       myRect->AddVertex (myTris->Vertice (1));
7673       myRect->AddVertex (myTris->Vertice (3));
7674       myRect->AddVertex (myTris->Vertice (4));
7675       myRect->AddVertex (myTris->Vertice (2));
7676     }
7677   }
7678
7679   //! Returns TRUE for accepted display modes.
7680   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7681
7682   //! Compute presentation.
7683   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7684   {
7685     switch (theMode)
7686     {
7687       case 0:
7688       {
7689         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7690         aGroup->AddPrimitiveArray (myTris);
7691         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7692         aGroup->AddPrimitiveArray (myRect);
7693         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7694         return;
7695       }
7696       case 1:
7697       {
7698         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7699         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7700         aGroup->AddPrimitiveArray (myRect);
7701         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7702         return;
7703       }
7704     }
7705   }
7706
7707   //! Compute selection.
7708   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7709   {
7710     if (theMode == 0)
7711     {
7712       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7713       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7714       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7715       theSel->Add (aSensitive);
7716     }
7717   }
7718
7719 private:
7720   Handle(Graphic3d_ArrayOfTriangles) myTris;
7721   Handle(Graphic3d_ArrayOfPolylines) myRect;
7722   TCollection_AsciiString myLabel;
7723   Standard_Real myWidth;
7724   Standard_Real myHeight;
7725 };
7726
7727 //==============================================================================
7728 //function : VDiffImage
7729 //purpose  : The draw-command compares two images.
7730 //==============================================================================
7731
7732 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7733 {
7734   if (theArgNb < 3)
7735   {
7736     std::cout << "Syntax error: not enough arguments.\n";
7737     return 1;
7738   }
7739
7740   Standard_Integer anArgIter = 1;
7741   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7742   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7743   TCollection_AsciiString aDiffImagePath;
7744   Standard_Real    aTolColor        = -1.0;
7745   Standard_Integer toBlackWhite     = -1;
7746   Standard_Integer isBorderFilterOn = -1;
7747   Standard_Boolean isOldSyntax = Standard_False;
7748   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7749   for (; anArgIter < theArgNb; ++anArgIter)
7750   {
7751     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7752     anArg.LowerCase();
7753     if (anArgIter + 1 < theArgNb
7754      && (anArg == "-toleranceofcolor"
7755       || anArg == "-tolerancecolor"
7756       || anArg == "-tolerance"
7757       || anArg == "-toler"))
7758     {
7759       aTolColor = Atof (theArgVec[++anArgIter]);
7760       if (aTolColor < 0.0 || aTolColor > 1.0)
7761       {
7762         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7763         return 1;
7764       }
7765     }
7766     else if (anArg == "-blackwhite")
7767     {
7768       Standard_Boolean toEnable = Standard_True;
7769       if (anArgIter + 1 < theArgNb
7770        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7771       {
7772         ++anArgIter;
7773       }
7774       toBlackWhite = toEnable ? 1 : 0;
7775     }
7776     else if (anArg == "-borderfilter")
7777     {
7778       Standard_Boolean toEnable = Standard_True;
7779       if (anArgIter + 1 < theArgNb
7780        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7781       {
7782         ++anArgIter;
7783       }
7784       isBorderFilterOn = toEnable ? 1 : 0;
7785     }
7786     else if (anArg == "-exitonclose")
7787     {
7788       Draw_ToExitOnCloseView = true;
7789       if (anArgIter + 1 < theArgNb
7790        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
7791       {
7792         ++anArgIter;
7793       }
7794     }
7795     else if (anArg == "-closeonescape"
7796           || anArg == "-closeonesc")
7797     {
7798       Draw_ToCloseViewOnEsc = true;
7799       if (anArgIter + 1 < theArgNb
7800        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
7801       {
7802         ++anArgIter;
7803       }
7804     }
7805     else if (anArgIter + 3 < theArgNb
7806           && anArg == "-display")
7807     {
7808       aViewName   = theArgVec[++anArgIter];
7809       aPrsNameRef = theArgVec[++anArgIter];
7810       aPrsNameNew = theArgVec[++anArgIter];
7811       if (anArgIter + 1 < theArgNb
7812       && *theArgVec[anArgIter + 1] != '-')
7813       {
7814         aPrsNameDiff = theArgVec[++anArgIter];
7815       }
7816     }
7817     else if (aTolColor < 0.0
7818           && anArg.IsRealValue())
7819     {
7820       isOldSyntax = Standard_True;
7821       aTolColor = anArg.RealValue();
7822       if (aTolColor < 0.0 || aTolColor > 1.0)
7823       {
7824         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7825         return 1;
7826       }
7827     }
7828     else if (isOldSyntax
7829           && toBlackWhite == -1
7830           && (anArg == "0" || anArg == "1"))
7831     {
7832       toBlackWhite = anArg == "1" ? 1 : 0;
7833     }
7834     else if (isOldSyntax
7835           && isBorderFilterOn == -1
7836           && (anArg == "0" || anArg == "1"))
7837     {
7838       isBorderFilterOn = anArg == "1" ? 1 : 0;
7839     }
7840     else if (aDiffImagePath.IsEmpty())
7841     {
7842       aDiffImagePath = theArgVec[anArgIter];
7843     }
7844     else
7845     {
7846       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7847       return 1;
7848     }
7849   }
7850
7851   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7852   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7853   if (!anImgRef->Load (anImgPathRef))
7854   {
7855     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7856     return 1;
7857   }
7858   if (!anImgNew->Load (anImgPathNew))
7859   {
7860     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7861     return 1;
7862   }
7863
7864   // compare the images
7865   Image_Diff aComparer;
7866   Standard_Integer aDiffColorsNb = -1;
7867   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7868   {
7869     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7870     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7871     aDiffColorsNb = aComparer.Compare();
7872     theDI << aDiffColorsNb << "\n";
7873   }
7874
7875   // save image of difference
7876   Handle(Image_AlienPixMap) aDiff;
7877   if (aDiffColorsNb > 0
7878   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7879   {
7880     aDiff = new Image_AlienPixMap();
7881     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7882     {
7883       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7884       return 1;
7885     }
7886     aComparer.SaveDiffImage (*aDiff);
7887     if (!aDiffImagePath.IsEmpty()
7888      && !aDiff->Save (aDiffImagePath))
7889     {
7890       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7891       return 1;
7892     }
7893   }
7894
7895   if (aViewName.IsEmpty())
7896   {
7897     return 0;
7898   }
7899
7900   ViewerTest_Names aViewNames (aViewName);
7901   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7902   {
7903     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7904     theDI.Eval (aCommand.ToCString());
7905   }
7906
7907   Standard_Integer aPxLeft = 0;
7908   Standard_Integer aPxTop  = 0;
7909   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7910   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7911                               ? int(anImgRef->SizeY() * 2)
7912                               : int(anImgRef->SizeY());
7913   TCollection_AsciiString aDisplayName;
7914   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7915                                                             aViewName, aDisplayName);
7916
7917   Standard_Real aRatio = anImgRef->Ratio();
7918   Standard_Real aSizeX = 1.0;
7919   Standard_Real aSizeY = aSizeX / aRatio;
7920   {
7921     OSD_Path aPath (anImgPathRef);
7922     TCollection_AsciiString aLabelRef;
7923     if (!aPath.Name().IsEmpty())
7924     {
7925       aLabelRef = aPath.Name() + aPath.Extension();
7926     }
7927     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7928
7929     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7930     gp_Trsf aTrsfRef;
7931     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7932     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7933     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7934   }
7935   {
7936     OSD_Path aPath (anImgPathNew);
7937     TCollection_AsciiString aLabelNew;
7938     if (!aPath.Name().IsEmpty())
7939     {
7940       aLabelNew = aPath.Name() + aPath.Extension();
7941     }
7942     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7943
7944     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7945     gp_Trsf aTrsfRef;
7946     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7947     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7948     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7949   }
7950   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7951   if (!aDiff.IsNull())
7952   {
7953     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7954     gp_Trsf aTrsfDiff;
7955     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7956     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7957   }
7958   if (!aPrsNameDiff.IsEmpty())
7959   {
7960     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7961   }
7962   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7963   ViewerTest::CurrentView()->FitAll();
7964   return 0;
7965 }
7966
7967 //=======================================================================
7968 //function : VSelect
7969 //purpose  : Emulates different types of selection by mouse:
7970 //           1) single click selection
7971 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7972 //           3) selection with polygon having corners at
7973 //           pixel positions (x1,y1),...,(xn,yn)
7974 //           4) any of these selections with shift button pressed
7975 //=======================================================================
7976 static Standard_Integer VSelect (Draw_Interpretor& di,
7977                                  Standard_Integer argc,
7978                                  const char ** argv)
7979 {
7980   if(argc < 3)
7981   {
7982     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
7983     return 1;
7984   }
7985
7986   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
7987   if(myAIScontext.IsNull())
7988   {
7989     di << "use 'vinit' command before " << argv[0] << "\n";
7990     return 1;
7991   }
7992
7993   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
7994   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
7995   TCollection_AsciiString anArg;
7996   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
7997   anArg.LowerCase();
7998   if (anArg == "-allowoverlap")
7999   {
8000     Standard_Boolean isValidated = isShiftSelection ? argc == 8
8001       : argc == 7;
8002     if (!isValidated)
8003     {
8004       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
8005       return 1;
8006     }
8007
8008     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
8009     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
8010     aCoordsNb -= 2;
8011   }
8012
8013   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
8014   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
8015   if(aCoordsNb == 2)
8016   {
8017     if(isShiftSelection)
8018       aCurrentEventManager->ShiftSelect();
8019     else
8020       aCurrentEventManager->Select();
8021   }
8022   else if(aCoordsNb == 4)
8023   {
8024     if(isShiftSelection)
8025       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
8026     else
8027       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
8028   }
8029   else
8030   {
8031     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
8032
8033     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
8034       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
8035
8036     if(isShiftSelection)
8037       aCurrentEventManager->ShiftSelect(aPolyline);
8038     else
8039       aCurrentEventManager->Select(aPolyline);
8040   }
8041   return 0;
8042 }
8043
8044 //=======================================================================
8045 //function : VMoveTo
8046 //purpose  : Emulates cursor movement to defined pixel position
8047 //=======================================================================
8048 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
8049                                 Standard_Integer theNbArgs,
8050                                 const char**     theArgVec)
8051 {
8052   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
8053   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
8054   if (aContext.IsNull())
8055   {
8056     std::cout << "Error: no active View\n";
8057     return 1;
8058   }
8059
8060   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
8061   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
8062   {
8063     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
8064     anArgStr.LowerCase();
8065     if (anArgStr == "-reset"
8066      || anArgStr == "-clear")
8067     {
8068       if (anArgIter + 1 < theNbArgs)
8069       {
8070         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
8071         return 1;
8072       }
8073
8074       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
8075                                        && aContext->CurrentViewer()->GridEcho();
8076       if (toEchoGrid)
8077       {
8078         aContext->CurrentViewer()->HideGridEcho (aView);
8079       }
8080       if (aContext->ClearDetected() || toEchoGrid)
8081       {
8082         aContext->CurrentViewer()->RedrawImmediate();
8083       }
8084       return 0;
8085     }
8086     else if (aMousePos.x() == IntegerLast()
8087           && anArgStr.IsIntegerValue())
8088     {
8089       aMousePos.x() = anArgStr.IntegerValue();
8090     }
8091     else if (aMousePos.y() == IntegerLast()
8092           && anArgStr.IsIntegerValue())
8093     {
8094       aMousePos.y() = anArgStr.IntegerValue();
8095     }
8096     else
8097     {
8098       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
8099       return 1;
8100     }
8101   }
8102
8103   if (aMousePos.x() == IntegerLast()
8104    || aMousePos.y() == IntegerLast())
8105   {
8106     std::cout << "Syntax error: wrong number of arguments\n";
8107     return 1;
8108   }
8109
8110   ViewerTest::CurrentEventManager()->MoveTo (aMousePos.x(), aMousePos.y());
8111   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
8112   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
8113   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
8114   {
8115     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
8116     {
8117       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
8118       break;
8119     }
8120   }
8121   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
8122   return 0;
8123 }
8124
8125 namespace
8126 {
8127   //! Global map storing all animations registered in ViewerTest.
8128   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
8129
8130   //! The animation calling the Draw Harness command.
8131   class ViewerTest_AnimationProc : public AIS_Animation
8132   {
8133   public:
8134
8135     //! Main constructor.
8136     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
8137                               Draw_Interpretor* theDI,
8138                               const TCollection_AsciiString& theCommand)
8139     : AIS_Animation (theAnimationName),
8140       myDrawInter(theDI),
8141       myCommand  (theCommand)
8142     {
8143       //
8144     }
8145
8146   protected:
8147
8148     //! Evaluate the command.
8149     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
8150     {
8151       TCollection_AsciiString aCmd = myCommand;
8152       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
8153       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
8154       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
8155       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
8156       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
8157       myDrawInter->Eval (aCmd.ToCString());
8158     }
8159
8160     //! Find the keyword in the command and replace it with value.
8161     //! @return the position of the keyword to pass value
8162     void replace (TCollection_AsciiString&       theCmd,
8163                   const TCollection_AsciiString& theKey,
8164                   const TCollection_AsciiString& theVal)
8165     {
8166       TCollection_AsciiString aCmd (theCmd);
8167       aCmd.LowerCase();
8168       const Standard_Integer aPos = aCmd.Search (theKey);
8169       if (aPos == -1)
8170       {
8171         return;
8172       }
8173
8174       TCollection_AsciiString aPart1, aPart2;
8175       Standard_Integer aPart1To = aPos - 1;
8176       if (aPart1To >= 1
8177        && aPart1To <= theCmd.Length())
8178       {
8179         aPart1 = theCmd.SubString (1, aPart1To);
8180       }
8181
8182       Standard_Integer aPart2From = aPos + theKey.Length();
8183       if (aPart2From >= 1
8184        && aPart2From <= theCmd.Length())
8185       {
8186         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
8187       }
8188
8189       theCmd = aPart1 + theVal + aPart2;
8190     }
8191
8192   protected:
8193
8194     Draw_Interpretor*       myDrawInter;
8195     TCollection_AsciiString myCommand;
8196
8197   };
8198
8199   //! Replace the animation with the new one.
8200   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
8201                                 Handle(AIS_Animation)&       theAnimation,
8202                                 const Handle(AIS_Animation)& theAnimationNew)
8203   {
8204     theAnimationNew->CopyFrom (theAnimation);
8205     if (!theParentAnimation.IsNull())
8206     {
8207       theParentAnimation->Replace (theAnimation, theAnimationNew);
8208     }
8209     else
8210     {
8211       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
8212       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
8213     }
8214     theAnimation = theAnimationNew;
8215   }
8216
8217   //! Parse the point.
8218   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
8219   {
8220     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
8221     if (!anXYZ[0].IsRealValue()
8222      || !anXYZ[1].IsRealValue()
8223      || !anXYZ[2].IsRealValue())
8224     {
8225       return Standard_False;
8226     }
8227
8228     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
8229     return Standard_True;
8230   }
8231
8232   //! Parse the quaternion.
8233   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
8234   {
8235     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
8236     if (!anXYZW[0].IsRealValue()
8237      || !anXYZW[1].IsRealValue()
8238      || !anXYZW[2].IsRealValue()
8239      || !anXYZW[3].IsRealValue())
8240     {
8241       return Standard_False;
8242     }
8243
8244     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
8245     return Standard_True;
8246   }
8247
8248   //! Auxiliary class for flipping image upside-down.
8249   class ImageFlipper
8250   {
8251   public:
8252
8253     //! Empty constructor.
8254     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
8255
8256     //! Perform flipping.
8257     Standard_Boolean FlipY (Image_PixMap& theImage)
8258     {
8259       if (theImage.IsEmpty()
8260        || theImage.SizeX() == 0
8261        || theImage.SizeY() == 0)
8262       {
8263         return Standard_False;
8264       }
8265
8266       const Standard_Size aRowSize = theImage.SizeRowBytes();
8267       if (myTmp.Size() < aRowSize
8268       && !myTmp.Allocate (aRowSize))
8269       {
8270         return Standard_False;
8271       }
8272
8273       // for odd height middle row should be left as is
8274       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
8275       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
8276       {
8277         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
8278         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
8279         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
8280         memcpy (aTop,               aBot,         aRowSize);
8281         memcpy (aBot,               myTmp.Data(), aRowSize);
8282       }
8283       return Standard_True;
8284     }
8285
8286   private:
8287     NCollection_Buffer myTmp;
8288   };
8289
8290 }
8291
8292 //=================================================================================================
8293 //function : VViewParams
8294 //purpose  : Gets or sets AIS View characteristics
8295 //=================================================================================================
8296 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8297 {
8298   Handle(V3d_View) aView = ViewerTest::CurrentView();
8299   if (aView.IsNull())
8300   {
8301     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
8302     return 1;
8303   }
8304
8305   Standard_Boolean toSetProj     = Standard_False;
8306   Standard_Boolean toSetUp       = Standard_False;
8307   Standard_Boolean toSetAt       = Standard_False;
8308   Standard_Boolean toSetEye      = Standard_False;
8309   Standard_Boolean toSetScale    = Standard_False;
8310   Standard_Boolean toSetSize     = Standard_False;
8311   Standard_Boolean toSetCenter2d = Standard_False;
8312   Standard_Real    aViewScale = aView->Scale();
8313   Standard_Real    aViewSize  = 1.0;
8314   Graphic3d_Vec2i  aCenter2d;
8315   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
8316   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
8317   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
8318   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
8319   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
8320   if (theArgsNb == 1)
8321   {
8322     // print all of the available view parameters
8323     char aText[4096];
8324     Sprintf (aText,
8325              "Scale: %g\n"
8326              "Proj:  %12g %12g %12g\n"
8327              "Up:    %12g %12g %12g\n"
8328              "At:    %12g %12g %12g\n"
8329              "Eye:   %12g %12g %12g\n",
8330               aViewScale,
8331               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
8332               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
8333               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
8334               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
8335     theDi << aText;
8336     return 0;
8337   }
8338
8339   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8340   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8341   {
8342     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8343     anArg.LowerCase();
8344     if (anUpdateTool.parseRedrawMode (anArg))
8345     {
8346       continue;
8347     }
8348     else if (anArg == "-cmd"
8349           || anArg == "-command"
8350           || anArg == "-args")
8351     {
8352       char aText[4096];
8353       Sprintf (aText,
8354                "-scale %g "
8355                "-proj %g %g %g "
8356                "-up %g %g %g "
8357                "-at %g %g %g\n",
8358                 aViewScale,
8359                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
8360                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
8361                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
8362       theDi << aText;
8363     }
8364     else if (anArg == "-scale"
8365           || anArg == "-size")
8366     {
8367       if (anArgIter + 1 < theArgsNb
8368        && *theArgVec[anArgIter + 1] != '-')
8369       {
8370         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
8371         if (aValueArg.IsRealValue())
8372         {
8373           ++anArgIter;
8374           if (anArg == "-scale")
8375           {
8376             toSetScale = Standard_True;
8377             aViewScale = aValueArg.RealValue();
8378           }
8379           else if (anArg == "-size")
8380           {
8381             toSetSize = Standard_True;
8382             aViewSize = aValueArg.RealValue();
8383           }
8384           continue;
8385         }
8386       }
8387       if (anArg == "-scale")
8388       {
8389         theDi << "Scale: " << aView->Scale() << "\n";
8390       }
8391       else if (anArg == "-size")
8392       {
8393         Graphic3d_Vec2d aSizeXY;
8394         aView->Size (aSizeXY.x(), aSizeXY.y());
8395         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
8396       }
8397     }
8398     else if (anArg == "-eye"
8399           || anArg == "-at"
8400           || anArg == "-up"
8401           || anArg == "-proj")
8402     {
8403       if (anArgIter + 3 < theArgsNb)
8404       {
8405         gp_XYZ anXYZ;
8406         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
8407         {
8408           anArgIter += 3;
8409           if (anArg == "-eye")
8410           {
8411             toSetEye = Standard_True;
8412             aViewEye = anXYZ;
8413           }
8414           else if (anArg == "-at")
8415           {
8416             toSetAt = Standard_True;
8417             aViewAt = anXYZ;
8418           }
8419           else if (anArg == "-up")
8420           {
8421             toSetUp = Standard_True;
8422             aViewUp = anXYZ;
8423           }
8424           else if (anArg == "-proj")
8425           {
8426             toSetProj = Standard_True;
8427             aViewProj = anXYZ;
8428           }
8429           continue;
8430         }
8431       }
8432
8433       if (anArg == "-eye")
8434       {
8435         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
8436       }
8437       else if (anArg == "-at")
8438       {
8439         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
8440       }
8441       else if (anArg == "-up")
8442       {
8443         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
8444       }
8445       else if (anArg == "-proj")
8446       {
8447         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
8448       }
8449     }
8450     else if (anArg == "-center")
8451     {
8452       if (anArgIter + 2 < theArgsNb)
8453       {
8454         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
8455         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
8456         if (anX.IsIntegerValue()
8457          && anY.IsIntegerValue())
8458         {
8459           toSetCenter2d = Standard_True;
8460           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
8461         }
8462       }
8463     }
8464     else
8465     {
8466       std::cout << "Syntax error at '" << anArg << "'\n";
8467       return 1;
8468     }
8469   }
8470
8471   // change view parameters in proper order
8472   if (toSetScale)
8473   {
8474     aView->SetScale (aViewScale);
8475   }
8476   if (toSetSize)
8477   {
8478     aView->SetSize (aViewSize);
8479   }
8480   if (toSetEye)
8481   {
8482     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
8483   }
8484   if (toSetAt)
8485   {
8486     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
8487   }
8488   if (toSetProj)
8489   {
8490     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
8491   }
8492   if (toSetUp)
8493   {
8494     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
8495   }
8496   if (toSetCenter2d)
8497   {
8498     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
8499   }
8500
8501   return 0;
8502 }
8503
8504 //==============================================================================
8505 //function : V2DMode
8506 //purpose  :
8507 //==============================================================================
8508 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
8509 {
8510   bool is2dMode = true;
8511   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
8512   if (aV3dView.IsNull())
8513   {
8514     std::cout << "Error: no active view.\n";
8515     return 1;
8516   }
8517   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8518   {
8519     const TCollection_AsciiString anArg = theArgVec[anArgIt];
8520     TCollection_AsciiString anArgCase = anArg;
8521     anArgCase.LowerCase();
8522     if (anArgIt + 1 < theArgsNb
8523      && anArgCase == "-name")
8524     {
8525       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
8526       TCollection_AsciiString aViewName = aViewNames.GetViewName();
8527       if (!ViewerTest_myViews.IsBound1 (aViewName))
8528       {
8529         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
8530         return 1;
8531       }
8532       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
8533     }
8534     else if (anArgCase == "-mode")
8535     {
8536       if (anArgIt + 1 < theArgsNb
8537        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
8538       {
8539         ++anArgIt;
8540       }
8541     }
8542     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
8543     {
8544       //
8545     }
8546     else
8547     {
8548       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
8549       return 1;
8550     }
8551   }
8552
8553   aV3dView->SetView2DMode (is2dMode);
8554   return 0;
8555 }
8556
8557 //==============================================================================
8558 //function : VAnimation
8559 //purpose  :
8560 //==============================================================================
8561 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
8562                                     Standard_Integer  theArgNb,
8563                                     const char**      theArgVec)
8564 {
8565   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
8566   if (theArgNb < 2)
8567   {
8568     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
8569          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
8570     {
8571       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
8572     }
8573     return 0;
8574   }
8575   if (aCtx.IsNull())
8576   {
8577     std::cout << "Error: no active view\n";
8578     return 1;
8579   }
8580
8581   Standard_Integer anArgIter = 1;
8582   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
8583   if (aNameArg.IsEmpty())
8584   {
8585     std::cout << "Syntax error: animation name is not defined.\n";
8586     return 1;
8587   }
8588
8589   TCollection_AsciiString aNameArgLower = aNameArg;
8590   aNameArgLower.LowerCase();
8591   if (aNameArgLower == "-reset"
8592    || aNameArgLower == "-clear")
8593   {
8594     ViewerTest_AnimationTimelineMap.Clear();
8595     return 0;
8596   }
8597   else if (aNameArg.Value (1) == '-')
8598   {
8599     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
8600     return 1;
8601   }
8602
8603   const char* aNameSplitter = "/";
8604   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
8605   if (aSplitPos == -1)
8606   {
8607     aNameSplitter = ".";
8608     aSplitPos = aNameArg.Search (aNameSplitter);
8609   }
8610
8611   // find existing or create a new animation by specified name within syntax "parent.child".
8612   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
8613   for (; !aNameArg.IsEmpty();)
8614   {
8615     TCollection_AsciiString aNameParent;
8616     if (aSplitPos != -1)
8617     {
8618       if (aSplitPos == aNameArg.Length())
8619       {
8620         std::cout << "Syntax error: animation name is not defined.\n";
8621         return 1;
8622       }
8623
8624       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
8625       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
8626
8627       aSplitPos = aNameArg.Search (aNameSplitter);
8628     }
8629     else
8630     {
8631       aNameParent = aNameArg;
8632       aNameArg.Clear();
8633     }
8634
8635     if (anAnimation.IsNull())
8636     {
8637       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
8638       {
8639         anAnimation = new AIS_Animation (aNameParent);
8640         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8641       }
8642       aRootAnimation = anAnimation;
8643     }
8644     else
8645     {
8646       aParentAnimation = anAnimation;
8647       anAnimation = aParentAnimation->Find (aNameParent);
8648       if (anAnimation.IsNull())
8649       {
8650         anAnimation = new AIS_Animation (aNameParent);
8651         aParentAnimation->Add (anAnimation);
8652       }
8653     }
8654   }
8655
8656   if (anArgIter >= theArgNb)
8657   {
8658     // just print the list of children
8659     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8660     {
8661       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8662     }
8663     return 0;
8664   }
8665
8666   // animation parameters
8667   Standard_Boolean toPlay = Standard_False;
8668   Standard_Real aPlaySpeed     = 1.0;
8669   Standard_Real aPlayStartTime = anAnimation->StartPts();
8670   Standard_Real aPlayDuration  = anAnimation->Duration();
8671   Standard_Boolean isFreeCamera = Standard_False;
8672   Standard_Boolean isLockLoop   = Standard_False;
8673
8674   // video recording parameters
8675   TCollection_AsciiString aRecFile;
8676   Image_VideoParams aRecParams;
8677
8678   Handle(V3d_View) aView = ViewerTest::CurrentView();
8679   for (; anArgIter < theArgNb; ++anArgIter)
8680   {
8681     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8682     anArg.LowerCase();
8683     // general options
8684     if (anArg == "-reset"
8685      || anArg == "-clear")
8686     {
8687       anAnimation->Clear();
8688     }
8689     else if (anArg == "-remove"
8690           || anArg == "-del"
8691           || anArg == "-delete")
8692     {
8693       if (!aParentAnimation.IsNull())
8694       {
8695         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8696       }
8697       else
8698       {
8699         aParentAnimation->Remove (anAnimation);
8700       }
8701     }
8702     // playback options
8703     else if (anArg == "-play")
8704     {
8705       toPlay = Standard_True;
8706       if (++anArgIter < theArgNb)
8707       {
8708         if (*theArgVec[anArgIter] == '-')
8709         {
8710           --anArgIter;
8711           continue;
8712         }
8713         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8714
8715         if (++anArgIter < theArgNb)
8716         {
8717           if (*theArgVec[anArgIter] == '-')
8718           {
8719             --anArgIter;
8720             continue;
8721           }
8722           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8723         }
8724       }
8725     }
8726     else if (anArg == "-resume")
8727     {
8728       toPlay = Standard_True;
8729       aPlayStartTime = anAnimation->ElapsedTime();
8730       if (++anArgIter < theArgNb)
8731       {
8732         if (*theArgVec[anArgIter] == '-')
8733         {
8734           --anArgIter;
8735           continue;
8736         }
8737
8738         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8739       }
8740     }
8741     else if (anArg == "-playspeed"
8742           || anArg == "-speed")
8743     {
8744       if (++anArgIter >= theArgNb)
8745       {
8746         std::cout << "Syntax error at " << anArg << ".\n";
8747         return 1;
8748       }
8749       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8750     }
8751     else if (anArg == "-lock"
8752           || anArg == "-lockloop"
8753           || anArg == "-playlockloop")
8754     {
8755       isLockLoop = Standard_True;
8756     }
8757     else if (anArg == "-freecamera"
8758           || anArg == "-playfreecamera"
8759           || anArg == "-freelook")
8760     {
8761       isFreeCamera = Standard_True;
8762     }
8763     // video recodring options
8764     else if (anArg == "-rec"
8765           || anArg == "-record")
8766     {
8767       if (++anArgIter >= theArgNb)
8768       {
8769         std::cout << "Syntax error at " << anArg << ".\n";
8770         return 1;
8771       }
8772
8773       aRecFile = theArgVec[anArgIter];
8774       if (aRecParams.FpsNum <= 0)
8775       {
8776         aRecParams.FpsNum = 24;
8777       }
8778
8779       if (anArgIter + 2 < theArgNb
8780       && *theArgVec[anArgIter + 1] != '-'
8781       && *theArgVec[anArgIter + 2] != '-')
8782       {
8783         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8784         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8785         if (aWidthArg .IsIntegerValue()
8786          && aHeightArg.IsIntegerValue())
8787         {
8788           aRecParams.Width  = aWidthArg .IntegerValue();
8789           aRecParams.Height = aHeightArg.IntegerValue();
8790           anArgIter += 2;
8791         }
8792       }
8793     }
8794     else if (anArg == "-fps")
8795     {
8796       if (++anArgIter >= theArgNb)
8797       {
8798         std::cout << "Syntax error at " << anArg << ".\n";
8799         return 1;
8800       }
8801
8802       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8803       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8804       if (aSplitIndex == 0)
8805       {
8806         aRecParams.FpsNum = aFpsArg.IntegerValue();
8807       }
8808       else
8809       {
8810         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8811         aFpsArg.Split (aFpsArg.Length() - 1);
8812         const TCollection_AsciiString aNumStr = aFpsArg;
8813         aRecParams.FpsNum = aNumStr.IntegerValue();
8814         aRecParams.FpsDen = aDenStr.IntegerValue();
8815         if (aRecParams.FpsDen < 1)
8816         {
8817           std::cout << "Syntax error at " << anArg << ".\n";
8818           return 1;
8819         }
8820       }
8821     }
8822     else if (anArg == "-format")
8823     {
8824       if (++anArgIter >= theArgNb)
8825       {
8826         std::cout << "Syntax error at " << anArg << ".\n";
8827         return 1;
8828       }
8829       aRecParams.Format = theArgVec[anArgIter];
8830     }
8831     else if (anArg == "-pix_fmt"
8832           || anArg == "-pixfmt"
8833           || anArg == "-pixelformat")
8834     {
8835       if (++anArgIter >= theArgNb)
8836       {
8837         std::cout << "Syntax error at " << anArg << ".\n";
8838         return 1;
8839       }
8840       aRecParams.PixelFormat = theArgVec[anArgIter];
8841     }
8842     else if (anArg == "-codec"
8843           || anArg == "-vcodec"
8844           || anArg == "-videocodec")
8845     {
8846       if (++anArgIter >= theArgNb)
8847       {
8848         std::cout << "Syntax error at " << anArg << ".\n";
8849         return 1;
8850       }
8851       aRecParams.VideoCodec = theArgVec[anArgIter];
8852     }
8853     else if (anArg == "-crf"
8854           || anArg == "-preset"
8855           || anArg == "-qp")
8856     {
8857       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8858       if (++anArgIter >= theArgNb)
8859       {
8860         std::cout << "Syntax error at " << anArg << ".\n";
8861         return 1;
8862       }
8863
8864       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8865     }
8866     // animation definition options
8867     else if (anArg == "-start"
8868           || anArg == "-starttime"
8869           || anArg == "-startpts")
8870     {
8871       if (++anArgIter >= theArgNb)
8872       {
8873         std::cout << "Syntax error at " << anArg << ".\n";
8874         return 1;
8875       }
8876
8877       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8878       aRootAnimation->UpdateTotalDuration();
8879     }
8880     else if (anArg == "-end"
8881           || anArg == "-endtime"
8882           || anArg == "-endpts")
8883     {
8884       if (++anArgIter >= theArgNb)
8885       {
8886         std::cout << "Syntax error at " << anArg << ".\n";
8887         return 1;
8888       }
8889
8890       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8891       aRootAnimation->UpdateTotalDuration();
8892     }
8893     else if (anArg == "-dur"
8894           || anArg == "-duration")
8895     {
8896       if (++anArgIter >= theArgNb)
8897       {
8898         std::cout << "Syntax error at " << anArg << ".\n";
8899         return 1;
8900       }
8901
8902       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8903       aRootAnimation->UpdateTotalDuration();
8904     }
8905     else if (anArg == "-command"
8906           || anArg == "-cmd"
8907           || anArg == "-invoke"
8908           || anArg == "-eval"
8909           || anArg == "-proc")
8910     {
8911       if (++anArgIter >= theArgNb)
8912       {
8913         std::cout << "Syntax error at " << anArg << ".\n";
8914         return 1;
8915       }
8916
8917       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8918       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8919     }
8920     else if (anArg == "-objecttrsf"
8921           || anArg == "-objectransformation"
8922           || anArg == "-objtransformation"
8923           || anArg == "-objtrsf"
8924           || anArg == "-object"
8925           || anArg == "-obj")
8926     {
8927       if (++anArgIter >= theArgNb)
8928       {
8929         std::cout << "Syntax error at " << anArg << ".\n";
8930         return 1;
8931       }
8932
8933       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8934       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8935       Handle(AIS_InteractiveObject) anObject;
8936       if (!aMapOfAIS.Find2 (anObjName, anObject))
8937       {
8938         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8939         return 1;
8940       }
8941
8942       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8943       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8944       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8945       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8946       Standard_Boolean isTrsfSet = Standard_False;
8947       Standard_Integer aTrsfArgIter = anArgIter + 1;
8948       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8949       {
8950         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8951         aTrsfArg.LowerCase();
8952         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8953         if (aTrsfArg.StartsWith ("-rotation")
8954          || aTrsfArg.StartsWith ("-rot"))
8955         {
8956           isTrsfSet = Standard_True;
8957           if (aTrsfArgIter + 4 >= theArgNb
8958           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8959           {
8960             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8961             return 1;
8962           }
8963           aTrsfArgIter += 4;
8964         }
8965         else if (aTrsfArg.StartsWith ("-location")
8966               || aTrsfArg.StartsWith ("-loc"))
8967         {
8968           isTrsfSet = Standard_True;
8969           if (aTrsfArgIter + 3 >= theArgNb
8970           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8971           {
8972             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8973             return 1;
8974           }
8975           aTrsfArgIter += 3;
8976         }
8977         else if (aTrsfArg.StartsWith ("-scale"))
8978         {
8979           isTrsfSet = Standard_True;
8980           if (++aTrsfArgIter >= theArgNb)
8981           {
8982             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8983             return 1;
8984           }
8985
8986           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8987           if (!aScaleStr.IsRealValue())
8988           {
8989             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8990             return 1;
8991           }
8992           aScales[anIndex] = aScaleStr.RealValue();
8993         }
8994         else
8995         {
8996           anArgIter = aTrsfArgIter - 1;
8997           break;
8998         }
8999       }
9000       if (!isTrsfSet)
9001       {
9002         std::cout << "Syntax error at " << anArg << ".\n";
9003         return 1;
9004       }
9005       else if (aTrsfArgIter >= theArgNb)
9006       {
9007         anArgIter = theArgNb;
9008       }
9009
9010       aTrsfs[0].SetRotation        (aRotQuats[0]);
9011       aTrsfs[1].SetRotation        (aRotQuats[1]);
9012       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
9013       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
9014       aTrsfs[0].SetScaleFactor     (aScales[0]);
9015       aTrsfs[1].SetScaleFactor     (aScales[1]);
9016
9017       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
9018       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
9019     }
9020     else if (anArg == "-viewtrsf"
9021           || anArg == "-view")
9022     {
9023       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
9024       if (aCamAnimation.IsNull())
9025       {
9026         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
9027         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
9028       }
9029
9030       Handle(Graphic3d_Camera) aCams[2] =
9031       {
9032         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
9033         new Graphic3d_Camera (aCamAnimation->View()->Camera())
9034       };
9035
9036       Standard_Boolean isTrsfSet = Standard_False;
9037       Standard_Integer aViewArgIter = anArgIter + 1;
9038       for (; aViewArgIter < theArgNb; ++aViewArgIter)
9039       {
9040         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
9041         aViewArg.LowerCase();
9042         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
9043         if (aViewArg.StartsWith ("-scale"))
9044         {
9045           isTrsfSet = Standard_True;
9046           if (++aViewArgIter >= theArgNb)
9047           {
9048             std::cout << "Syntax error at " << anArg << ".\n";
9049             return 1;
9050           }
9051
9052           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
9053           if (!aScaleStr.IsRealValue())
9054           {
9055             std::cout << "Syntax error at " << aViewArg << ".\n";
9056             return 1;
9057           }
9058           Standard_Real aScale = aScaleStr.RealValue();
9059           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
9060           aCams[anIndex]->SetScale (aScale);
9061         }
9062         else if (aViewArg.StartsWith ("-eye")
9063               || aViewArg.StartsWith ("-center")
9064               || aViewArg.StartsWith ("-at")
9065               || aViewArg.StartsWith ("-up"))
9066         {
9067           isTrsfSet = Standard_True;
9068           gp_XYZ anXYZ;
9069           if (aViewArgIter + 3 >= theArgNb
9070           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
9071           {
9072             std::cout << "Syntax error at " << aViewArg << ".\n";
9073             return 1;
9074           }
9075           aViewArgIter += 3;
9076
9077           if (aViewArg.StartsWith ("-eye"))
9078           {
9079             aCams[anIndex]->SetEye (anXYZ);
9080           }
9081           else if (aViewArg.StartsWith ("-center")
9082                 || aViewArg.StartsWith ("-at"))
9083           {
9084             aCams[anIndex]->SetCenter (anXYZ);
9085           }
9086           else if (aViewArg.StartsWith ("-up"))
9087           {
9088             aCams[anIndex]->SetUp (anXYZ);
9089           }
9090         }
9091         else
9092         {
9093           anArgIter = aViewArgIter - 1;
9094           break;
9095         }
9096       }
9097       if (!isTrsfSet)
9098       {
9099         std::cout << "Syntax error at " << anArg << ".\n";
9100         return 1;
9101       }
9102       else if (aViewArgIter >= theArgNb)
9103       {
9104         anArgIter = theArgNb;
9105       }
9106
9107       aCamAnimation->SetCameraStart(aCams[0]);
9108       aCamAnimation->SetCameraEnd  (aCams[1]);
9109     }
9110     else
9111     {
9112       std::cout << "Syntax error at " << anArg << ".\n";
9113       return 1;
9114     }
9115   }
9116
9117   if (!toPlay && aRecFile.IsEmpty())
9118   {
9119     return 0;
9120   }
9121
9122   // Start animation timeline and process frame updating.
9123   TheIsAnimating = Standard_True;
9124   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
9125   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
9126   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
9127   if (isFreeCamera)
9128   {
9129     aView->Camera()->Copy (aCameraBack);
9130   }
9131
9132   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
9133   if (aRecParams.FpsNum <= 0)
9134   {
9135     while (!anAnimation->IsStopped())
9136     {
9137       aCameraBack->Copy (aView->Camera());
9138       const Standard_Real aPts = anAnimation->UpdateTimer();
9139       if (isFreeCamera)
9140       {
9141         aView->Camera()->Copy (aCameraBack);
9142       }
9143
9144       if (aPts >= anUpperPts)
9145       {
9146         anAnimation->Pause();
9147         break;
9148       }
9149
9150       if (aView->IsInvalidated())
9151       {
9152         aView->Redraw();
9153       }
9154       else
9155       {
9156         aView->RedrawImmediate();
9157       }
9158
9159       if (!isLockLoop)
9160       {
9161         // handle user events
9162         theDI.Eval ("after 1 set waiter 1");
9163         theDI.Eval ("vwait waiter");
9164       }
9165       if (!TheIsAnimating)
9166       {
9167         anAnimation->Pause();
9168         theDI << aPts;
9169         break;
9170       }
9171     }
9172
9173     if (aView->IsInvalidated())
9174     {
9175       aView->Redraw();
9176     }
9177     else
9178     {
9179       aView->RedrawImmediate();
9180     }
9181   }
9182   else
9183   {
9184     OSD_Timer aPerfTimer;
9185     aPerfTimer.Start();
9186
9187     Handle(Image_VideoRecorder) aRecorder;
9188     ImageFlipper aFlipper;
9189     Handle(Draw_ProgressIndicator) aProgress;
9190     if (!aRecFile.IsEmpty())
9191     {
9192       if (aRecParams.Width  <= 0
9193        || aRecParams.Height <= 0)
9194       {
9195         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
9196       }
9197
9198       aRecorder = new Image_VideoRecorder();
9199       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
9200       {
9201         std::cout << "Error: failed to open video file for recording\n";
9202         return 0;
9203       }
9204
9205       aProgress = new Draw_ProgressIndicator (theDI, 1);
9206     }
9207
9208     // Manage frame-rated animation here
9209     Standard_Real aPts = aPlayStartTime;
9210     int64_t aNbFrames = 0;
9211     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
9212     Standard_Integer aSecondsProgress = 0;
9213     for (; aPts <= anUpperPts && aPSentry.More();)
9214     {
9215       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
9216       aPts = aPlayStartTime + aRecPts;
9217       ++aNbFrames;
9218       if (!anAnimation->Update (aPts))
9219       {
9220         break;
9221       }
9222
9223       if (!aRecorder.IsNull())
9224       {
9225         V3d_ImageDumpOptions aDumpParams;
9226         aDumpParams.Width          = aRecParams.Width;
9227         aDumpParams.Height         = aRecParams.Height;
9228         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
9229         aDumpParams.StereoOptions  = V3d_SDO_MONO;
9230         aDumpParams.ToAdjustAspect = Standard_True;
9231         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
9232         {
9233           std::cout << "Error: view dump is failed!\n";
9234           return 0;
9235         }
9236         aFlipper.FlipY (aRecorder->ChangeFrame());
9237         if (!aRecorder->PushFrame())
9238         {
9239           return 0;
9240         }
9241       }
9242       else
9243       {
9244         aView->Redraw();
9245       }
9246
9247       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
9248       {
9249         aPSentry.Next();
9250         ++aSecondsProgress;
9251       }
9252     }
9253
9254     aPerfTimer.Stop();
9255     anAnimation->Stop();
9256     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
9257     theDI << "Average FPS: " << aRecFps << "\n"
9258           << "Nb. Frames: "  << Standard_Real(aNbFrames);
9259
9260     aView->Redraw();
9261   }
9262
9263   aView->SetImmediateUpdate (wasImmediateUpdate);
9264   TheIsAnimating = Standard_False;
9265   return 0;
9266 }
9267
9268
9269 //=======================================================================
9270 //function : VChangeSelected
9271 //purpose  : Adds the shape to selection or remove one from it
9272 //=======================================================================
9273 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
9274                                 Standard_Integer argc,
9275                                 const char ** argv)
9276 {
9277   if(argc != 2)
9278   {
9279     di<<"Usage : " << argv[0] << " shape \n";
9280     return 1;
9281   }
9282   //get AIS_Shape:
9283   TCollection_AsciiString aName(argv[1]);
9284   Handle(AIS_InteractiveObject) anAISObject;
9285   if (!GetMapOfAIS().Find2 (aName, anAISObject)
9286     || anAISObject.IsNull())
9287   {
9288     di<<"Use 'vdisplay' before";
9289     return 1;
9290   }
9291
9292   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
9293   return 0;
9294 }
9295
9296 //=======================================================================
9297 //function : VNbSelected
9298 //purpose  : Returns number of selected objects
9299 //=======================================================================
9300 static Standard_Integer VNbSelected (Draw_Interpretor& di,
9301                                 Standard_Integer argc,
9302                                 const char ** argv)
9303 {
9304   if(argc != 1)
9305   {
9306     di << "Usage : " << argv[0] << "\n";
9307     return 1;
9308   }
9309   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9310   if(aContext.IsNull())
9311   {
9312     di << "use 'vinit' command before " << argv[0] << "\n";
9313     return 1;
9314   }
9315   di << aContext->NbSelected() << "\n";
9316   return 0;
9317 }
9318
9319 //=======================================================================
9320 //function : VPurgeDisplay
9321 //purpose  : Switches altialiasing on or off
9322 //=======================================================================
9323 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
9324                                 Standard_Integer argc,
9325                                 const char ** argv)
9326 {
9327   if (argc > 1)
9328   {
9329     di << "Usage : " << argv[0] << "\n";
9330     return 1;
9331   }
9332   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9333   if (aContext.IsNull())
9334   {
9335     di << "use 'vinit' command before " << argv[0] << "\n";
9336     return 1;
9337   }
9338
9339   di << aContext->PurgeDisplay() << "\n";
9340   return 0;
9341 }
9342
9343 //=======================================================================
9344 //function : VSetViewSize
9345 //purpose  :
9346 //=======================================================================
9347 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
9348                                 Standard_Integer argc,
9349                                 const char ** argv)
9350 {
9351   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9352   if(aContext.IsNull())
9353   {
9354     di << "use 'vinit' command before " << argv[0] << "\n";
9355     return 1;
9356   }
9357   if(argc != 2)
9358   {
9359     di<<"Usage : " << argv[0] << " Size\n";
9360     return 1;
9361   }
9362   Standard_Real aSize = Draw::Atof (argv[1]);
9363   if (aSize <= 0.)
9364   {
9365     di<<"Bad Size value  : " << aSize << "\n";
9366     return 1;
9367   }
9368
9369   Handle(V3d_View) aView = ViewerTest::CurrentView();
9370   aView->SetSize(aSize);
9371   return 0;
9372 }
9373
9374 //=======================================================================
9375 //function : VMoveView
9376 //purpose  :
9377 //=======================================================================
9378 static Standard_Integer VMoveView (Draw_Interpretor& di,
9379                                 Standard_Integer argc,
9380                                 const char ** argv)
9381 {
9382   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9383   if(aContext.IsNull())
9384   {
9385     di << "use 'vinit' command before " << argv[0] << "\n";
9386     return 1;
9387   }
9388   if(argc < 4 || argc > 5)
9389   {
9390     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9391     return 1;
9392   }
9393   Standard_Real Dx = Draw::Atof (argv[1]);
9394   Standard_Real Dy = Draw::Atof (argv[2]);
9395   Standard_Real Dz = Draw::Atof (argv[3]);
9396   Standard_Boolean aStart = Standard_True;
9397   if (argc == 5)
9398   {
9399       aStart = (Draw::Atoi (argv[4]) > 0);
9400   }
9401
9402   Handle(V3d_View) aView = ViewerTest::CurrentView();
9403   aView->Move(Dx,Dy,Dz,aStart);
9404   return 0;
9405 }
9406
9407 //=======================================================================
9408 //function : VTranslateView
9409 //purpose  :
9410 //=======================================================================
9411 static Standard_Integer VTranslateView (Draw_Interpretor& di,
9412                                 Standard_Integer argc,
9413                                 const char ** argv)
9414 {
9415   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9416   if(aContext.IsNull())
9417   {
9418     di << "use 'vinit' command before " << argv[0] << "\n";
9419     return 1;
9420   }
9421   if(argc < 4 || argc > 5)
9422   {
9423     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9424     return 1;
9425   }
9426   Standard_Real Dx = Draw::Atof (argv[1]);
9427   Standard_Real Dy = Draw::Atof (argv[2]);
9428   Standard_Real Dz = Draw::Atof (argv[3]);
9429   Standard_Boolean aStart = Standard_True;
9430   if (argc == 5)
9431   {
9432       aStart = (Draw::Atoi (argv[4]) > 0);
9433   }
9434
9435   Handle(V3d_View) aView = ViewerTest::CurrentView();
9436   aView->Translate(Dx,Dy,Dz,aStart);
9437   return 0;
9438 }
9439
9440 //=======================================================================
9441 //function : VTurnView
9442 //purpose  :
9443 //=======================================================================
9444 static Standard_Integer VTurnView (Draw_Interpretor& di,
9445                                 Standard_Integer argc,
9446                                 const char ** argv)
9447 {
9448   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9449   if(aContext.IsNull()) {
9450     di << "use 'vinit' command before " << argv[0] << "\n";
9451     return 1;
9452   }
9453   if(argc < 4 || argc > 5){
9454     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
9455     return 1;
9456   }
9457   Standard_Real Ax = Draw::Atof (argv[1]);
9458   Standard_Real Ay = Draw::Atof (argv[2]);
9459   Standard_Real Az = Draw::Atof (argv[3]);
9460   Standard_Boolean aStart = Standard_True;
9461   if (argc == 5)
9462   {
9463       aStart = (Draw::Atoi (argv[4]) > 0);
9464   }
9465
9466   Handle(V3d_View) aView = ViewerTest::CurrentView();
9467   aView->Turn(Ax,Ay,Az,aStart);
9468   return 0;
9469 }
9470
9471 //==============================================================================
9472 //function : VTextureEnv
9473 //purpose  : ENables or disables environment mapping
9474 //==============================================================================
9475 class OCC_TextureEnv : public Graphic3d_TextureEnv
9476 {
9477 public:
9478   OCC_TextureEnv(const Standard_CString FileName);
9479   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
9480   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
9481                             const Standard_Boolean theModulateFlag,
9482                             const Graphic3d_TypeOfTextureFilter theFilter,
9483                             const Standard_ShortReal theXScale,
9484                             const Standard_ShortReal theYScale,
9485                             const Standard_ShortReal theXShift,
9486                             const Standard_ShortReal theYShift,
9487                             const Standard_ShortReal theAngle);
9488   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
9489 };
9490 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
9491
9492 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
9493   : Graphic3d_TextureEnv(theFileName)
9494 {
9495 }
9496
9497 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
9498   : Graphic3d_TextureEnv(theTexId)
9499 {
9500 }
9501
9502 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
9503                                           const Standard_Boolean theModulateFlag,
9504                                           const Graphic3d_TypeOfTextureFilter theFilter,
9505                                           const Standard_ShortReal theXScale,
9506                                           const Standard_ShortReal theYScale,
9507                                           const Standard_ShortReal theXShift,
9508                                           const Standard_ShortReal theYShift,
9509                                           const Standard_ShortReal theAngle)
9510 {
9511   myParams->SetRepeat     (theRepeatFlag);
9512   myParams->SetModulate   (theModulateFlag);
9513   myParams->SetFilter     (theFilter);
9514   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
9515   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
9516   myParams->SetRotation   (theAngle);
9517 }
9518
9519 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
9520 {
9521   // get the active view
9522   Handle(V3d_View) aView = ViewerTest::CurrentView();
9523   if (aView.IsNull())
9524   {
9525     std::cerr << "No active view. Please call vinit.\n";
9526     return 1;
9527   }
9528
9529   // Checking the input arguments
9530   Standard_Boolean anEnableFlag = Standard_False;
9531   Standard_Boolean isOk         = theArgNb >= 2;
9532   if (isOk)
9533   {
9534     TCollection_AsciiString anEnableOpt(theArgVec[1]);
9535     anEnableFlag = anEnableOpt.IsEqual("on");
9536     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
9537   }
9538   if (anEnableFlag)
9539   {
9540     isOk = (theArgNb == 3 || theArgNb == 11);
9541     if (isOk)
9542     {
9543       TCollection_AsciiString aTextureOpt(theArgVec[2]);
9544       isOk = (!aTextureOpt.IsIntegerValue() ||
9545              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
9546
9547       if (isOk && theArgNb == 11)
9548       {
9549         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
9550                                 aModulateOpt(theArgVec[4]),
9551                                 aFilterOpt  (theArgVec[5]),
9552                                 aSScaleOpt  (theArgVec[6]),
9553                                 aTScaleOpt  (theArgVec[7]),
9554                                 aSTransOpt  (theArgVec[8]),
9555                                 aTTransOpt  (theArgVec[9]),
9556                                 anAngleOpt  (theArgVec[10]);
9557         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
9558                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
9559                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
9560                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
9561                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
9562                 anAngleOpt.IsRealValue());
9563       }
9564     }
9565   }
9566
9567   if (!isOk)
9568   {
9569     std::cerr << "Usage :" << std::endl;
9570     std::cerr << theArgVec[0] << " off" << std::endl;
9571     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;
9572     return 1;
9573   }
9574
9575   if (anEnableFlag)
9576   {
9577     TCollection_AsciiString aTextureOpt(theArgVec[2]);
9578     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
9579                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
9580                                      new OCC_TextureEnv(theArgVec[2]);
9581
9582     if (theArgNb == 11)
9583     {
9584       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
9585       aTexEnv->SetTextureParameters(
9586         aRepeatOpt.  IsEqual("repeat"),
9587         aModulateOpt.IsEqual("modulate"),
9588         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
9589                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
9590                                                                            Graphic3d_TOTF_TRILINEAR,
9591         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
9592         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
9593         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
9594         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
9595         (Standard_ShortReal)Draw::Atof(theArgVec[10])
9596         );
9597     }
9598     aView->SetTextureEnv(aTexEnv);
9599   }
9600   else // Disabling environment mapping
9601   {
9602     Handle(Graphic3d_TextureEnv) aTexture;
9603     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
9604   }
9605
9606   aView->Redraw();
9607   return 0;
9608 }
9609
9610 namespace
9611 {
9612   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
9613
9614   //! Remove registered clipping plane from all views and objects.
9615   static void removePlane (MapOfPlanes& theRegPlanes,
9616                            const TCollection_AsciiString& theName)
9617   {
9618     Handle(Graphic3d_ClipPlane) aClipPlane;
9619     if (!theRegPlanes.Find (theName, aClipPlane))
9620     {
9621       std::cout << "Warning: no such plane.\n";
9622       return;
9623     }
9624
9625     theRegPlanes.UnBind (theName);
9626     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
9627          anIObjIt.More(); anIObjIt.Next())
9628     {
9629       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
9630       aPrs->RemoveClipPlane (aClipPlane);
9631     }
9632
9633     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
9634          aViewIt.More(); aViewIt.Next())
9635     {
9636       const Handle(V3d_View)& aView = aViewIt.Key2();
9637       aView->RemoveClipPlane(aClipPlane);
9638     }
9639
9640     ViewerTest::RedrawAllViews();
9641   }
9642 }
9643
9644 //===============================================================================================
9645 //function : VClipPlane
9646 //purpose  :
9647 //===============================================================================================
9648 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9649 {
9650   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9651   static MapOfPlanes aRegPlanes;
9652
9653   if (theArgsNb < 2)
9654   {
9655     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9656     {
9657       theDi << aPlaneIter.Key() << " ";
9658     }
9659     return 0;
9660   }
9661
9662   TCollection_AsciiString aCommand (theArgVec[1]);
9663   aCommand.LowerCase();
9664   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9665   if (anActiveView.IsNull())
9666   {
9667     std::cout << "Error: no active view.\n";
9668     return 1;
9669   }
9670
9671   // print maximum number of planes for current viewer
9672   if (aCommand == "-maxplanes"
9673    || aCommand == "maxplanes")
9674   {
9675     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9676           << " plane slots provided by driver.\n";
9677     return 0;
9678   }
9679
9680   // create / delete plane instance
9681   if (aCommand == "-create"
9682    || aCommand == "create"
9683    || aCommand == "-delete"
9684    || aCommand == "delete"
9685    || aCommand == "-clone"
9686    || aCommand == "clone")
9687   {
9688     if (theArgsNb < 3)
9689     {
9690       std::cout << "Syntax error: plane name is required.\n";
9691       return 1;
9692     }
9693
9694     Standard_Boolean toCreate = aCommand == "-create"
9695                              || aCommand == "create";
9696     Standard_Boolean toClone  = aCommand == "-clone"
9697                              || aCommand == "clone";
9698     Standard_Boolean toDelete = aCommand == "-delete"
9699                              || aCommand == "delete";
9700     TCollection_AsciiString aPlane (theArgVec[2]);
9701
9702     if (toCreate)
9703     {
9704       if (aRegPlanes.IsBound (aPlane))
9705       {
9706         std::cout << "Warning: existing plane has been overridden.\n";
9707         toDelete = true;
9708       }
9709       else
9710       {
9711         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9712         return 0;
9713       }
9714     }
9715     else if (toClone) // toClone
9716     {
9717       if (!aRegPlanes.IsBound (aPlane))
9718       {
9719         std::cout << "Error: no such plane.\n";
9720         return 1;
9721       }
9722       else if (theArgsNb < 4)
9723       {
9724         std::cout << "Syntax error: enter name for new plane.\n";
9725         return 1;
9726       }
9727
9728       TCollection_AsciiString aClone (theArgVec[3]);
9729       if (aRegPlanes.IsBound (aClone))
9730       {
9731         std::cout << "Error: plane name is in use.\n";
9732         return 1;
9733       }
9734
9735       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9736
9737       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9738       return 0;
9739     }
9740
9741     if (toDelete)
9742     {
9743       if (aPlane == "ALL"
9744        || aPlane == "all"
9745        || aPlane == "*")
9746       {
9747         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9748         {
9749           aPlane = aPlaneIter.Key();
9750           removePlane (aRegPlanes, aPlane);
9751           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9752         }
9753       }
9754       else
9755       {
9756         removePlane (aRegPlanes, aPlane);
9757       }
9758     }
9759
9760     if (toCreate)
9761     {
9762       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9763     }
9764     return 0;
9765   }
9766
9767   // set / unset plane command
9768   if (aCommand == "set"
9769    || aCommand == "unset")
9770   {
9771     if (theArgsNb < 5)
9772     {
9773       std::cout << "Syntax error: need more arguments.\n";
9774       return 1;
9775     }
9776
9777     // redirect to new syntax
9778     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9779     anArgVec.SetValue (1, theArgVec[0]);
9780     anArgVec.SetValue (2, theArgVec[2]);
9781     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9782     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9783     {
9784       anArgVec.SetValue (anIt, theArgVec[anIt]);
9785     }
9786
9787     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9788   }
9789
9790   // change plane command
9791   TCollection_AsciiString aPlaneName;
9792   Handle(Graphic3d_ClipPlane) aClipPlane;
9793   Standard_Integer anArgIter = 0;
9794   if (aCommand == "-change"
9795    || aCommand == "change")
9796   {
9797     // old syntax support
9798     if (theArgsNb < 3)
9799     {
9800       std::cout << "Syntax error: need more arguments.\n";
9801       return 1;
9802     }
9803
9804     anArgIter  = 3;
9805     aPlaneName = theArgVec[2];
9806     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9807     {
9808       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9809       return 1;
9810     }
9811   }
9812   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9813   {
9814     anArgIter  = 2;
9815     aPlaneName = theArgVec[1];
9816   }
9817   else
9818   {
9819     anArgIter  = 2;
9820     aPlaneName = theArgVec[1];
9821     aClipPlane = new Graphic3d_ClipPlane();
9822     aRegPlanes.Bind (aPlaneName, aClipPlane);
9823     theDi << "Created new plane " << aPlaneName << ".\n";
9824   }
9825
9826   if (theArgsNb - anArgIter < 1)
9827   {
9828     std::cout << "Syntax error: need more arguments.\n";
9829     return 1;
9830   }
9831
9832   for (; anArgIter < theArgsNb; ++anArgIter)
9833   {
9834     const char**     aChangeArgs   = theArgVec + anArgIter;
9835     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9836     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9837     aChangeArg.LowerCase();
9838
9839     Standard_Boolean toEnable = Standard_True;
9840     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9841     {
9842       aClipPlane->SetOn (toEnable);
9843     }
9844     else if (aChangeArg.StartsWith ("-equation")
9845           || aChangeArg.StartsWith ("equation"))
9846     {
9847       if (aNbChangeArgs < 5)
9848       {
9849         std::cout << "Syntax error: need more arguments.\n";
9850         return 1;
9851       }
9852
9853       Standard_Integer aSubIndex = 1;
9854       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9855       if (aPrefixLen < aChangeArg.Length())
9856       {
9857         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9858         if (!aSubStr.IsIntegerValue()
9859           || aSubStr.IntegerValue() <= 0)
9860         {
9861           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9862           return 1;
9863         }
9864         aSubIndex = aSubStr.IntegerValue();
9865       }
9866
9867       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9868       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9869       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9870       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9871       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9872       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9873       {
9874         if (aSubPln->ChainNextPlane().IsNull())
9875         {
9876           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9877         }
9878         aSubPln = aSubPln->ChainNextPlane();
9879       }
9880       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9881       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9882       anArgIter += 4;
9883     }
9884     else if ((aChangeArg == "-boxinterior"
9885            || aChangeArg == "-boxint"
9886            || aChangeArg == "-box")
9887             && aNbChangeArgs >= 7)
9888     {
9889       Graphic3d_BndBox3d aBndBox;
9890       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9891       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9892       anArgIter += 6;
9893
9894       Standard_Integer aNbSubPlanes = 6;
9895       const Graphic3d_Vec3d aDirArray[6] =
9896       {
9897         Graphic3d_Vec3d (-1, 0, 0),
9898         Graphic3d_Vec3d ( 1, 0, 0),
9899         Graphic3d_Vec3d ( 0,-1, 0),
9900         Graphic3d_Vec3d ( 0, 1, 0),
9901         Graphic3d_Vec3d ( 0, 0,-1),
9902         Graphic3d_Vec3d ( 0, 0, 1),
9903       };
9904       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9905       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9906       {
9907         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9908         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9909         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9910         if (aSubPlaneIter + 1 == aNbSubPlanes)
9911         {
9912           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9913         }
9914         else
9915         {
9916           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9917         }
9918         aSubPln = aSubPln->ChainNextPlane();
9919       }
9920     }
9921     else if (aChangeArg == "-capping"
9922           || aChangeArg == "capping")
9923     {
9924       if (aNbChangeArgs < 2)
9925       {
9926         std::cout << "Syntax error: need more arguments.\n";
9927         return 1;
9928       }
9929
9930       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9931       {
9932         aClipPlane->SetCapping (toEnable);
9933         anArgIter += 1;
9934       }
9935       else
9936       {
9937         // just skip otherwise (old syntax)
9938       }
9939     }
9940     else if (aChangeArg == "-useobjectmaterial"
9941           || aChangeArg == "-useobjectmat"
9942           || aChangeArg == "-useobjmat"
9943           || aChangeArg == "-useobjmaterial")
9944     {
9945       if (aNbChangeArgs < 2)
9946       {
9947         std::cout << "Syntax error: need more arguments.\n";
9948         return 1;
9949       }
9950
9951       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9952       {
9953         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9954         anArgIter += 1;
9955       }
9956     }
9957     else if (aChangeArg == "-useobjecttexture"
9958           || aChangeArg == "-useobjecttex"
9959           || aChangeArg == "-useobjtexture"
9960           || aChangeArg == "-useobjtex")
9961     {
9962       if (aNbChangeArgs < 2)
9963       {
9964         std::cout << "Syntax error: need more arguments.\n";
9965         return 1;
9966       }
9967
9968       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9969       {
9970         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9971         anArgIter += 1;
9972       }
9973     }
9974     else if (aChangeArg == "-useobjectshader"
9975           || aChangeArg == "-useobjshader")
9976     {
9977       if (aNbChangeArgs < 2)
9978       {
9979         std::cout << "Syntax error: need more arguments.\n";
9980         return 1;
9981       }
9982
9983       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9984       {
9985         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9986         anArgIter += 1;
9987       }
9988     }
9989     else if (aChangeArg == "-color"
9990           || aChangeArg == "color")
9991     {
9992       Quantity_Color aColor;
9993       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9994                                                            aChangeArgs + 1,
9995                                                            aColor);
9996       if (aNbParsed == 0)
9997       {
9998         std::cout << "Syntax error: need more arguments.\n";
9999         return 1;
10000       }
10001
10002       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
10003       aMat.SetAmbientColor (aColor);
10004       aMat.SetDiffuseColor (aColor);
10005       aClipPlane->SetCappingMaterial (aMat);
10006       anArgIter += aNbParsed;
10007     }
10008     else if ((aChangeArg == "-transparency"
10009            || aChangeArg == "-transp")
10010           && aNbChangeArgs >= 2)
10011     {
10012       TCollection_AsciiString aValStr (aChangeArgs[1]);
10013       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
10014       if (aValStr.IsRealValue())
10015       {
10016         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
10017         aMat.SetTransparency ((float )aValStr.RealValue());
10018         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
10019         aClipPlane->SetCappingMaterial (aMat);
10020       }
10021       else
10022       {
10023         aValStr.LowerCase();
10024         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
10025         if (aValStr == "opaque")
10026         {
10027           aMode = Graphic3d_AlphaMode_Opaque;
10028         }
10029         else if (aValStr == "mask")
10030         {
10031           aMode = Graphic3d_AlphaMode_Mask;
10032         }
10033         else if (aValStr == "blend")
10034         {
10035           aMode = Graphic3d_AlphaMode_Blend;
10036         }
10037         else if (aValStr == "blendauto")
10038         {
10039           aMode = Graphic3d_AlphaMode_BlendAuto;
10040         }
10041         else
10042         {
10043           std::cout << "Syntax error at '" << aValStr << "'\n";
10044           return 1;
10045         }
10046         anAspect->SetAlphaMode (aMode);
10047         aClipPlane->SetCappingAspect (anAspect);
10048       }
10049       anArgIter += 1;
10050     }
10051     else if (aChangeArg == "-texname"
10052           || aChangeArg == "texname")
10053     {
10054       if (aNbChangeArgs < 2)
10055       {
10056         std::cout << "Syntax error: need more arguments.\n";
10057         return 1;
10058       }
10059
10060       TCollection_AsciiString aTextureName (aChangeArgs[1]);
10061       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
10062       if (!aTexture->IsDone())
10063       {
10064         aClipPlane->SetCappingTexture (NULL);
10065       }
10066       else
10067       {
10068         aTexture->EnableModulate();
10069         aTexture->EnableRepeat();
10070         aClipPlane->SetCappingTexture (aTexture);
10071       }
10072       anArgIter += 1;
10073     }
10074     else if (aChangeArg == "-texscale"
10075           || aChangeArg == "texscale")
10076     {
10077       if (aClipPlane->CappingTexture().IsNull())
10078       {
10079         std::cout << "Error: no texture is set.\n";
10080         return 1;
10081       }
10082
10083       if (aNbChangeArgs < 3)
10084       {
10085         std::cout << "Syntax error: need more arguments.\n";
10086         return 1;
10087       }
10088
10089       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
10090       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
10091       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
10092       anArgIter += 2;
10093     }
10094     else if (aChangeArg == "-texorigin"
10095           || aChangeArg == "texorigin") // texture origin
10096     {
10097       if (aClipPlane->CappingTexture().IsNull())
10098       {
10099         std::cout << "Error: no texture is set.\n";
10100         return 1;
10101       }
10102
10103       if (aNbChangeArgs < 3)
10104       {
10105         std::cout << "Syntax error: need more arguments.\n";
10106         return 1;
10107       }
10108
10109       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
10110       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
10111
10112       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
10113       anArgIter += 2;
10114     }
10115     else if (aChangeArg == "-texrotate"
10116           || aChangeArg == "texrotate") // texture rotation
10117     {
10118       if (aClipPlane->CappingTexture().IsNull())
10119       {
10120         std::cout << "Error: no texture is set.\n";
10121         return 1;
10122       }
10123
10124       if (aNbChangeArgs < 2)
10125       {
10126         std::cout << "Syntax error: need more arguments.\n";
10127         return 1;
10128       }
10129
10130       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
10131       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
10132       anArgIter += 1;
10133     }
10134     else if (aChangeArg == "-hatch"
10135           || aChangeArg == "hatch")
10136     {
10137       if (aNbChangeArgs < 2)
10138       {
10139         std::cout << "Syntax error: need more arguments.\n";
10140         return 1;
10141       }
10142
10143       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
10144       aHatchStr.LowerCase();
10145       if (aHatchStr == "on")
10146       {
10147         aClipPlane->SetCappingHatchOn();
10148       }
10149       else if (aHatchStr == "off")
10150       {
10151         aClipPlane->SetCappingHatchOff();
10152       }
10153       else
10154       {
10155         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
10156       }
10157       anArgIter += 1;
10158     }
10159     else if (aChangeArg == "-delete"
10160           || aChangeArg == "delete")
10161     {
10162       removePlane (aRegPlanes, aPlaneName);
10163       return 0;
10164     }
10165     else if (aChangeArg == "-set"
10166           || aChangeArg == "-unset"
10167           || aChangeArg == "-setoverrideglobal")
10168     {
10169       // set / unset plane command
10170       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
10171       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
10172       Standard_Integer anIt = 1;
10173       for (; anIt < aNbChangeArgs; ++anIt)
10174       {
10175         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
10176         if (anEntityName.IsEmpty()
10177          || anEntityName.Value (1) == '-')
10178         {
10179           break;
10180         }
10181         else if (!toOverrideGlobal
10182                && ViewerTest_myViews.IsBound1 (anEntityName))
10183         {
10184           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
10185           if (toSet)
10186           {
10187             aView->AddClipPlane (aClipPlane);
10188           }
10189           else
10190           {
10191             aView->RemoveClipPlane (aClipPlane);
10192           }
10193           continue;
10194         }
10195         else if (GetMapOfAIS().IsBound2 (anEntityName))
10196         {
10197           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
10198           if (toSet)
10199           {
10200             aIObj->AddClipPlane (aClipPlane);
10201           }
10202           else
10203           {
10204             aIObj->RemoveClipPlane (aClipPlane);
10205           }
10206           if (!aIObj->ClipPlanes().IsNull())
10207           {
10208             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
10209           }
10210         }
10211         else
10212         {
10213           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
10214           return 1;
10215         }
10216       }
10217
10218       if (anIt == 1)
10219       {
10220         // apply to active view
10221         if (toSet)
10222         {
10223           anActiveView->AddClipPlane (aClipPlane);
10224         }
10225         else
10226         {
10227           anActiveView->RemoveClipPlane (aClipPlane);
10228         }
10229       }
10230       else
10231       {
10232         anArgIter = anArgIter + anIt - 1;
10233       }
10234     }
10235     else
10236     {
10237       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
10238       return 1;
10239     }
10240   }
10241
10242   ViewerTest::RedrawAllViews();
10243   return 0;
10244 }
10245
10246 //===============================================================================================
10247 //function : VZRange
10248 //purpose  :
10249 //===============================================================================================
10250 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
10251 {
10252   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
10253
10254   if (aCurrentView.IsNull())
10255   {
10256     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
10257     return 1;
10258   }
10259
10260   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
10261
10262   if (theArgsNb < 2)
10263   {
10264     theDi << "ZNear: " << aCamera->ZNear() << "\n";
10265     theDi << "ZFar: " << aCamera->ZFar() << "\n";
10266     return 0;
10267   }
10268
10269   if (theArgsNb == 3)
10270   {
10271     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
10272     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
10273
10274     if (aNewZNear >= aNewZFar)
10275     {
10276       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
10277       return 1;
10278     }
10279
10280     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
10281     {
10282       std::cout << theArgVec[0] << ": invalid arguments: ";
10283       std::cout << "znear, zfar should be positive for perspective camera.\n";
10284       return 1;
10285     }
10286
10287     aCamera->SetZRange (aNewZNear, aNewZFar);
10288   }
10289   else
10290   {
10291     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
10292     return 1;
10293   }
10294
10295   aCurrentView->Redraw();
10296
10297   return 0;
10298 }
10299
10300 //===============================================================================================
10301 //function : VAutoZFit
10302 //purpose  :
10303 //===============================================================================================
10304 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
10305 {
10306   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
10307
10308   if (aCurrentView.IsNull())
10309   {
10310     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
10311     return 1;
10312   }
10313
10314   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
10315
10316   if (theArgsNb > 3)
10317   {
10318     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
10319     return 1;
10320   }
10321
10322   if (theArgsNb < 2)
10323   {
10324     theDi << "Auto z-fit mode: \n"
10325           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
10326           << "Scale: " << aScale << "\n";
10327     return 0;
10328   }
10329
10330   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
10331
10332   if (theArgsNb >= 3)
10333   {
10334     aScale = Draw::Atoi (theArgVec[2]);
10335   }
10336
10337   aCurrentView->SetAutoZFitMode (isOn, aScale);
10338   aCurrentView->AutoZFit();
10339   aCurrentView->Redraw();
10340
10341   return 0;
10342 }
10343
10344 //! Auxiliary function to print projection type
10345 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
10346 {
10347   switch (theProjType)
10348   {
10349     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
10350     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
10351     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
10352     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
10353     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
10354   }
10355   return "UNKNOWN";
10356 }
10357
10358 //===============================================================================================
10359 //function : VCamera
10360 //purpose  :
10361 //===============================================================================================
10362 static int VCamera (Draw_Interpretor& theDI,
10363                     Standard_Integer  theArgsNb,
10364                     const char**      theArgVec)
10365 {
10366   Handle(V3d_View) aView = ViewerTest::CurrentView();
10367   if (aView.IsNull())
10368   {
10369     std::cout << "Error: no active view.\n";
10370     return 1;
10371   }
10372
10373   Handle(Graphic3d_Camera) aCamera = aView->Camera();
10374   if (theArgsNb < 2)
10375   {
10376     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
10377     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
10378     theDI << "Distance:   " << aCamera->Distance() << "\n";
10379     theDI << "IOD:        " << aCamera->IOD() << "\n";
10380     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
10381     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
10382     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
10383     return 0;
10384   }
10385
10386   TCollection_AsciiString aPrsName;
10387   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10388   {
10389     Standard_CString        anArg = theArgVec[anArgIter];
10390     TCollection_AsciiString anArgCase (anArg);
10391     anArgCase.LowerCase();
10392     if (anArgCase == "-proj"
10393      || anArgCase == "-projection"
10394      || anArgCase == "-projtype"
10395      || anArgCase == "-projectiontype")
10396     {
10397       theDI << projTypeName (aCamera->ProjectionType()) << " ";
10398     }
10399     else if (anArgCase == "-ortho"
10400           || anArgCase == "-orthographic")
10401     {
10402       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
10403     }
10404     else if (anArgCase == "-persp"
10405           || anArgCase == "-perspective"
10406           || anArgCase == "-perspmono"
10407           || anArgCase == "-perspectivemono"
10408           || anArgCase == "-mono")
10409     {
10410       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10411     }
10412     else if (anArgCase == "-stereo"
10413           || anArgCase == "-stereoscopic"
10414           || anArgCase == "-perspstereo"
10415           || anArgCase == "-perspectivestereo")
10416     {
10417       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10418     }
10419     else if (anArgCase == "-left"
10420           || anArgCase == "-lefteye"
10421           || anArgCase == "-monoleft"
10422           || anArgCase == "-monolefteye"
10423           || anArgCase == "-perpsleft"
10424           || anArgCase == "-perpslefteye")
10425     {
10426       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
10427     }
10428     else if (anArgCase == "-right"
10429           || anArgCase == "-righteye"
10430           || anArgCase == "-monoright"
10431           || anArgCase == "-monorighteye"
10432           || anArgCase == "-perpsright")
10433     {
10434       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
10435     }
10436     else if (anArgCase == "-dist"
10437           || anArgCase == "-distance")
10438     {
10439       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10440       if (anArgValue != NULL
10441       && *anArgValue != '-')
10442       {
10443         ++anArgIter;
10444         aCamera->SetDistance (Draw::Atof (anArgValue));
10445         continue;
10446       }
10447       theDI << aCamera->Distance() << " ";
10448     }
10449     else if (anArgCase == "-iod")
10450     {
10451       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10452       if (anArgValue != NULL
10453       && *anArgValue != '-')
10454       {
10455         ++anArgIter;
10456         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
10457         continue;
10458       }
10459       theDI << aCamera->IOD() << " ";
10460     }
10461     else if (anArgCase == "-iodtype")
10462     {
10463       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10464       TCollection_AsciiString anValueCase (anArgValue);
10465       anValueCase.LowerCase();
10466       if (anValueCase == "abs"
10467        || anValueCase == "absolute")
10468       {
10469         ++anArgIter;
10470         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
10471         continue;
10472       }
10473       else if (anValueCase == "rel"
10474             || anValueCase == "relative")
10475       {
10476         ++anArgIter;
10477         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
10478         continue;
10479       }
10480       else if (*anArgValue != '-')
10481       {
10482         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
10483         return 1;
10484       }
10485       switch (aCamera->GetIODType())
10486       {
10487         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
10488         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
10489       }
10490     }
10491     else if (anArgCase == "-zfocus")
10492     {
10493       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10494       if (anArgValue != NULL
10495       && *anArgValue != '-')
10496       {
10497         ++anArgIter;
10498         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
10499         continue;
10500       }
10501       theDI << aCamera->ZFocus() << " ";
10502     }
10503     else if (anArgCase == "-zfocustype")
10504     {
10505       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10506       TCollection_AsciiString anValueCase (anArgValue);
10507       anValueCase.LowerCase();
10508       if (anValueCase == "abs"
10509        || anValueCase == "absolute")
10510       {
10511         ++anArgIter;
10512         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
10513         continue;
10514       }
10515       else if (anValueCase == "rel"
10516             || anValueCase == "relative")
10517       {
10518         ++anArgIter;
10519         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
10520         continue;
10521       }
10522       else if (*anArgValue != '-')
10523       {
10524         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
10525         return 1;
10526       }
10527       switch (aCamera->ZFocusType())
10528       {
10529         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
10530         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
10531       }
10532     }
10533     else if (anArgCase == "-fov"
10534           || anArgCase == "-fovy")
10535     {
10536       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10537       if (anArgValue != NULL
10538       && *anArgValue != '-')
10539       {
10540         ++anArgIter;
10541         aCamera->SetFOVy (Draw::Atof (anArgValue));
10542         continue;
10543       }
10544       theDI << aCamera->FOVy() << " ";
10545     }
10546     else if (aPrsName.IsEmpty()
10547          && !anArgCase.StartsWith ("-"))
10548     {
10549       aPrsName = anArg;
10550     }
10551     else
10552     {
10553       std::cout << "Error: unknown argument '" << anArg << "'\n";
10554       return 1;
10555     }
10556   }
10557
10558   if (aPrsName.IsEmpty()
10559    || theArgsNb > 2)
10560   {
10561     aView->AutoZFit();
10562     aView->Redraw();
10563   }
10564
10565   if (!aPrsName.IsEmpty())
10566   {
10567     Handle(AIS_CameraFrustum) aCameraFrustum;
10568     if (GetMapOfAIS().IsBound2 (aPrsName))
10569     {
10570       // find existing object
10571       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
10572       if (aCameraFrustum.IsNull())
10573       {
10574         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
10575         return 1;
10576       }
10577     }
10578
10579     if (aCameraFrustum.IsNull())
10580     {
10581       aCameraFrustum = new AIS_CameraFrustum();
10582     }
10583     else
10584     {
10585       // not include displayed object of old camera frustum in the new one.
10586       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
10587       aView->ZFitAll();
10588     }
10589     aCameraFrustum->SetCameraFrustum (aView->Camera());
10590
10591     ViewerTest::Display (aPrsName, aCameraFrustum);
10592   }
10593
10594   return 0;
10595 }
10596
10597 //! Parse stereo output mode
10598 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
10599                                          Graphic3d_StereoMode& theMode)
10600 {
10601   TCollection_AsciiString aFlag (theArg);
10602   aFlag.LowerCase();
10603   if (aFlag == "quadbuffer")
10604   {
10605     theMode = Graphic3d_StereoMode_QuadBuffer;
10606   }
10607   else if (aFlag == "anaglyph")
10608   {
10609     theMode = Graphic3d_StereoMode_Anaglyph;
10610   }
10611   else if (aFlag == "row"
10612         || aFlag == "rowinterlaced")
10613   {
10614     theMode = Graphic3d_StereoMode_RowInterlaced;
10615   }
10616   else if (aFlag == "col"
10617         || aFlag == "colinterlaced"
10618         || aFlag == "columninterlaced")
10619   {
10620     theMode = Graphic3d_StereoMode_ColumnInterlaced;
10621   }
10622   else if (aFlag == "chess"
10623         || aFlag == "chessboard")
10624   {
10625     theMode = Graphic3d_StereoMode_ChessBoard;
10626   }
10627   else if (aFlag == "sbs"
10628         || aFlag == "sidebyside")
10629   {
10630     theMode = Graphic3d_StereoMode_SideBySide;
10631   }
10632   else if (aFlag == "ou"
10633         || aFlag == "overunder")
10634   {
10635     theMode = Graphic3d_StereoMode_OverUnder;
10636   }
10637   else if (aFlag == "pageflip"
10638         || aFlag == "softpageflip")
10639   {
10640     theMode = Graphic3d_StereoMode_SoftPageFlip;
10641   }
10642   else
10643   {
10644     return Standard_False;
10645   }
10646   return Standard_True;
10647 }
10648
10649 //! Parse anaglyph filter
10650 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10651                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10652 {
10653   TCollection_AsciiString aFlag (theArg);
10654   aFlag.LowerCase();
10655   if (aFlag == "redcyansimple")
10656   {
10657     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10658   }
10659   else if (aFlag == "redcyan"
10660         || aFlag == "redcyanoptimized")
10661   {
10662     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10663   }
10664   else if (aFlag == "yellowbluesimple")
10665   {
10666     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10667   }
10668   else if (aFlag == "yellowblue"
10669         || aFlag == "yellowblueoptimized")
10670   {
10671     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10672   }
10673   else if (aFlag == "greenmagenta"
10674         || aFlag == "greenmagentasimple")
10675   {
10676     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10677   }
10678   else
10679   {
10680     return Standard_False;
10681   }
10682   return Standard_True;
10683 }
10684
10685 //==============================================================================
10686 //function : VStereo
10687 //purpose  :
10688 //==============================================================================
10689
10690 static int VStereo (Draw_Interpretor& theDI,
10691                     Standard_Integer  theArgNb,
10692                     const char**      theArgVec)
10693 {
10694   Handle(V3d_View) aView = ViewerTest::CurrentView();
10695   if (theArgNb < 2)
10696   {
10697     if (aView.IsNull())
10698     {
10699       std::cout << "Error: no active viewer!\n";
10700       return 0;
10701     }
10702
10703     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10704     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10705     if (isActive)
10706     {
10707       TCollection_AsciiString aMode;
10708       switch (aView->RenderingParams().StereoMode)
10709       {
10710         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10711         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10712         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10713         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10714         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10715         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10716         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10717         case Graphic3d_StereoMode_Anaglyph  :
10718           aMode = "anaglyph";
10719           switch (aView->RenderingParams().AnaglyphFilter)
10720           {
10721             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10722             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10723             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10724             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10725             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10726             default: break;
10727           }
10728         default: break;
10729       }
10730       theDI << "Mode " << aMode << "\n";
10731     }
10732     return 0;
10733   }
10734
10735   Handle(Graphic3d_Camera) aCamera;
10736   Graphic3d_RenderingParams*   aParams   = NULL;
10737   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10738   if (!aView.IsNull())
10739   {
10740     aParams   = &aView->ChangeRenderingParams();
10741     aMode     = aParams->StereoMode;
10742     aCamera   = aView->Camera();
10743   }
10744
10745   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10746   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10747   {
10748     Standard_CString        anArg = theArgVec[anArgIter];
10749     TCollection_AsciiString aFlag (anArg);
10750     aFlag.LowerCase();
10751     if (anUpdateTool.parseRedrawMode (aFlag))
10752     {
10753       continue;
10754     }
10755     else if (aFlag == "0"
10756           || aFlag == "off")
10757     {
10758       if (++anArgIter < theArgNb)
10759       {
10760         std::cout << "Error: wrong number of arguments!\n";
10761         return 1;
10762       }
10763
10764       if (!aCamera.IsNull()
10765        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10766       {
10767         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10768       }
10769       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10770       return 0;
10771     }
10772     else if (aFlag == "1"
10773           || aFlag == "on")
10774     {
10775       if (++anArgIter < theArgNb)
10776       {
10777         std::cout << "Error: wrong number of arguments!\n";
10778         return 1;
10779       }
10780
10781       if (!aCamera.IsNull())
10782       {
10783         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10784       }
10785       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10786       return 0;
10787     }
10788     else if (aFlag == "-reverse"
10789           || aFlag == "-reversed"
10790           || aFlag == "-swap")
10791     {
10792       Standard_Boolean toEnable = Standard_True;
10793       if (++anArgIter < theArgNb
10794       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10795       {
10796         --anArgIter;
10797       }
10798       aParams->ToReverseStereo = toEnable;
10799     }
10800     else if (aFlag == "-noreverse"
10801           || aFlag == "-noswap")
10802     {
10803       Standard_Boolean toDisable = Standard_True;
10804       if (++anArgIter < theArgNb
10805       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10806       {
10807         --anArgIter;
10808       }
10809       aParams->ToReverseStereo = !toDisable;
10810     }
10811     else if (aFlag == "-mode"
10812           || aFlag == "-stereomode")
10813     {
10814       if (++anArgIter >= theArgNb
10815       || !parseStereoMode (theArgVec[anArgIter], aMode))
10816       {
10817         std::cout << "Error: syntax error at '" << anArg << "'\n";
10818         return 1;
10819       }
10820
10821       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10822       {
10823         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10824       }
10825     }
10826     else if (aFlag == "-anaglyph"
10827           || aFlag == "-anaglyphfilter")
10828     {
10829       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10830       if (++anArgIter >= theArgNb
10831       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10832       {
10833         std::cout << "Error: syntax error at '" << anArg << "'\n";
10834         return 1;
10835       }
10836
10837       aMode = Graphic3d_StereoMode_Anaglyph;
10838       aParams->AnaglyphFilter = aFilter;
10839     }
10840     else if (parseStereoMode (anArg, aMode)) // short syntax
10841     {
10842       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10843       {
10844         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10845       }
10846     }
10847     else
10848     {
10849       std::cout << "Error: syntax error at '" << anArg << "'\n";
10850       return 1;
10851     }
10852   }
10853
10854   if (!aView.IsNull())
10855   {
10856     aParams->StereoMode = aMode;
10857     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10858   }
10859   return 0;
10860 }
10861
10862 //===============================================================================================
10863 //function : VDefaults
10864 //purpose  :
10865 //===============================================================================================
10866 static int VDefaults (Draw_Interpretor& theDi,
10867                       Standard_Integer  theArgsNb,
10868                       const char**      theArgVec)
10869 {
10870   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10871   if (aCtx.IsNull())
10872   {
10873     std::cerr << "No active viewer!\n";
10874     return 1;
10875   }
10876
10877   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10878   if (theArgsNb < 2)
10879   {
10880     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10881     {
10882       theDi << "DeflType:           relative\n"
10883             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10884     }
10885     else
10886     {
10887       theDi << "DeflType:           absolute\n"
10888             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10889     }
10890     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10891     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10892     return 0;
10893   }
10894
10895   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10896   {
10897     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10898     anArg.UpperCase();
10899     if (anArg == "-ABSDEFL"
10900      || anArg == "-ABSOLUTEDEFLECTION"
10901      || anArg == "-DEFL"
10902      || anArg == "-DEFLECTION")
10903     {
10904       if (++anArgIter >= theArgsNb)
10905       {
10906         std::cout << "Error: wrong syntax at " << anArg << "\n";
10907         return 1;
10908       }
10909       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10910       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10911     }
10912     else if (anArg == "-RELDEFL"
10913           || anArg == "-RELATIVEDEFLECTION"
10914           || anArg == "-DEVCOEFF"
10915           || anArg == "-DEVIATIONCOEFF"
10916           || anArg == "-DEVIATIONCOEFFICIENT")
10917     {
10918       if (++anArgIter >= theArgsNb)
10919       {
10920         std::cout << "Error: wrong syntax at " << anArg << "\n";
10921         return 1;
10922       }
10923       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10924       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10925     }
10926     else if (anArg == "-ANGDEFL"
10927           || anArg == "-ANGULARDEFL"
10928           || anArg == "-ANGULARDEFLECTION")
10929     {
10930       if (++anArgIter >= theArgsNb)
10931       {
10932         std::cout << "Error: wrong syntax at " << anArg << "\n";
10933         return 1;
10934       }
10935       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10936       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10937     }
10938     else if (anArg == "-AUTOTR"
10939           || anArg == "-AUTOTRIANG"
10940           || anArg == "-AUTOTRIANGULATION")
10941     {
10942       if (++anArgIter >= theArgsNb)
10943       {
10944         std::cout << "Error: wrong syntax at " << anArg << "\n";
10945         return 1;
10946       }
10947       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10948       aValue.LowerCase();
10949       if (aValue == "on"
10950        || aValue == "1")
10951       {
10952         aDefParams->SetAutoTriangulation (Standard_True);
10953       }
10954       else if (aValue == "off"
10955             || aValue == "0")
10956       {
10957         aDefParams->SetAutoTriangulation (Standard_False);
10958       }
10959     }
10960     else
10961     {
10962       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
10963     }
10964   }
10965
10966   return 0;
10967 }
10968
10969 //! Auxiliary method
10970 inline void addLight (const Handle(V3d_Light)& theLightNew,
10971                       const Graphic3d_ZLayerId theLayer,
10972                       const Standard_Boolean   theIsGlobal)
10973 {
10974   if (theLightNew.IsNull())
10975   {
10976     return;
10977   }
10978
10979   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10980   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10981   {
10982     aViewer->AddLight (theLightNew);
10983     if (theIsGlobal)
10984     {
10985       aViewer->SetLightOn (theLightNew);
10986     }
10987     else
10988     {
10989       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10990     }
10991   }
10992   else
10993   {
10994     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10995     if (aSettings.Lights().IsNull())
10996     {
10997       aSettings.SetLights (new Graphic3d_LightSet());
10998     }
10999     aSettings.Lights()->Add (theLightNew);
11000     aViewer->SetZLayerSettings (theLayer, aSettings);
11001   }
11002 }
11003
11004 //! Auxiliary method
11005 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
11006 {
11007   TCollection_AsciiString anArgNextCase (theArgNext);
11008   anArgNextCase.UpperCase();
11009   if (anArgNextCase.Length() > 5
11010    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
11011   {
11012     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
11013   }
11014   else
11015   {
11016     return theArgNext.IntegerValue();
11017   }
11018 }
11019
11020 //===============================================================================================
11021 //function : VLight
11022 //purpose  :
11023 //===============================================================================================
11024 static int VLight (Draw_Interpretor& theDi,
11025                    Standard_Integer  theArgsNb,
11026                    const char**      theArgVec)
11027 {
11028   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
11029   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
11030   if (aView.IsNull()
11031    || aViewer.IsNull())
11032   {
11033     std::cerr << "No active viewer!\n";
11034     return 1;
11035   }
11036
11037   Standard_Real anXYZ[3]   = {};
11038   Standard_Real anAtten[2] = {};
11039   if (theArgsNb < 2)
11040   {
11041     // print lights info
11042     Standard_Integer aLightId = 0;
11043     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
11044     {
11045       Handle(V3d_Light) aLight = aLightIter.Value();
11046       const Quantity_Color aColor = aLight->Color();
11047       theDi << "Light #" << aLightId
11048             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
11049             << " [" << aLight->GetId() << "]" << "\n";
11050       switch (aLight->Type())
11051       {
11052         case V3d_AMBIENT:
11053         {
11054           theDi << "  Type:       Ambient\n";
11055           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
11056           break;
11057         }
11058         case V3d_DIRECTIONAL:
11059         {
11060           theDi << "  Type:       Directional\n";
11061           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
11062           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
11063           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
11064           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
11065           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
11066           break;
11067         }
11068         case V3d_POSITIONAL:
11069         {
11070           theDi << "  Type:       Positional\n";
11071           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
11072           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
11073           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
11074           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
11075           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
11076           aLight->Attenuation (anAtten[0], anAtten[1]);
11077           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
11078           break;
11079         }
11080         case V3d_SPOT:
11081         {
11082           theDi << "  Type:       Spot\n";
11083           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
11084           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
11085           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
11086           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
11087           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
11088           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
11089           aLight->Attenuation (anAtten[0], anAtten[1]);
11090           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
11091           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
11092           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
11093           break;
11094         }
11095         default:
11096         {
11097           theDi << "  Type:       UNKNOWN\n";
11098           break;
11099         }
11100       }
11101       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
11102     }
11103   }
11104
11105   Handle(V3d_Light) aLightNew;
11106   Handle(V3d_Light) aLightOld;
11107   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
11108   Standard_Boolean  isGlobal = Standard_True;
11109   Standard_Boolean  toCreate = Standard_False;
11110   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11111   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
11112   {
11113     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
11114
11115     TCollection_AsciiString aName, aValue;
11116     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
11117     TCollection_AsciiString anArgCase (anArg);
11118     anArgCase.UpperCase();
11119     if (anUpdateTool.parseRedrawMode (anArg))
11120     {
11121       continue;
11122     }
11123
11124     if (anArgCase.IsEqual ("NEW")
11125      || anArgCase.IsEqual ("ADD")
11126      || anArgCase.IsEqual ("CREATE")
11127      || anArgCase.IsEqual ("-NEW")
11128      || anArgCase.IsEqual ("-ADD")
11129      || anArgCase.IsEqual ("-CREATE"))
11130     {
11131       toCreate = Standard_True;
11132     }
11133     else if (anArgCase.IsEqual ("-LAYER")
11134           || anArgCase.IsEqual ("-ZLAYER"))
11135     {
11136       if (++anArgIt >= theArgsNb)
11137       {
11138         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11139         return 1;
11140       }
11141
11142       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
11143       aValStr.LowerCase();
11144       if (aValStr == "default"
11145        || aValStr == "def")
11146       {
11147         aLayer = Graphic3d_ZLayerId_Default;
11148       }
11149       else if (aValStr == "top")
11150       {
11151         aLayer = Graphic3d_ZLayerId_Top;
11152       }
11153       else if (aValStr == "topmost")
11154       {
11155         aLayer = Graphic3d_ZLayerId_Topmost;
11156       }
11157       else if (aValStr == "toposd"
11158             || aValStr == "osd")
11159       {
11160         aLayer = Graphic3d_ZLayerId_TopOSD;
11161       }
11162       else if (aValStr == "botosd"
11163             || aValStr == "bottom")
11164       {
11165         aLayer = Graphic3d_ZLayerId_BotOSD;
11166       }
11167       else if (aValStr.IsIntegerValue())
11168       {
11169         aLayer = Draw::Atoi (theArgVec[anArgIt]);
11170       }
11171       else
11172       {
11173         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
11174         return 1;
11175       }
11176     }
11177     else if (anArgCase.IsEqual ("GLOB")
11178           || anArgCase.IsEqual ("GLOBAL")
11179           || anArgCase.IsEqual ("-GLOB")
11180           || anArgCase.IsEqual ("-GLOBAL"))
11181     {
11182       isGlobal = Standard_True;
11183     }
11184     else if (anArgCase.IsEqual ("LOC")
11185           || anArgCase.IsEqual ("LOCAL")
11186           || anArgCase.IsEqual ("-LOC")
11187           || anArgCase.IsEqual ("-LOCAL"))
11188     {
11189       isGlobal = Standard_False;
11190     }
11191     else if (anArgCase.IsEqual ("DEF")
11192           || anArgCase.IsEqual ("DEFAULTS")
11193           || anArgCase.IsEqual ("-DEF")
11194           || anArgCase.IsEqual ("-DEFAULTS"))
11195     {
11196       toCreate = Standard_False;
11197       aViewer->SetDefaultLights();
11198     }
11199     else if (anArgCase.IsEqual ("CLR")
11200           || anArgCase.IsEqual ("CLEAR")
11201           || anArgCase.IsEqual ("-CLR")
11202           || anArgCase.IsEqual ("-CLEAR"))
11203     {
11204       toCreate = Standard_False;
11205
11206       TColStd_SequenceOfInteger aLayers;
11207       aViewer->GetAllZLayers (aLayers);
11208       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
11209       {
11210         if (aLayeriter.Value() == aLayer
11211          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
11212         {
11213           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
11214           aSettings.SetLights (Handle(Graphic3d_LightSet)());
11215           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
11216           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
11217           {
11218             break;
11219           }
11220         }
11221       }
11222
11223       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
11224       {
11225         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
11226         {
11227           Handle(V3d_Light) aLight = aLightIter.Value();
11228           aViewer->DelLight (aLight);
11229           aLightIter = aView->ActiveLightIterator();
11230         }
11231       }
11232     }
11233     else if (anArgCase.IsEqual ("AMB")
11234           || anArgCase.IsEqual ("AMBIENT")
11235           || anArgCase.IsEqual ("AMBLIGHT"))
11236     {
11237       if (!toCreate)
11238       {
11239         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11240         return 1;
11241       }
11242
11243       addLight (aLightNew, aLayer, isGlobal);
11244       toCreate  = Standard_False;
11245       aLightNew = new V3d_AmbientLight();
11246     }
11247     else if (anArgCase.IsEqual ("DIRECTIONAL")
11248           || anArgCase.IsEqual ("DIRLIGHT"))
11249     {
11250       if (!toCreate)
11251       {
11252         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11253         return 1;
11254       }
11255
11256       addLight (aLightNew, aLayer, isGlobal);
11257       toCreate  = Standard_False;
11258       aLightNew = new V3d_DirectionalLight();
11259     }
11260     else if (anArgCase.IsEqual ("SPOT")
11261           || anArgCase.IsEqual ("SPOTLIGHT"))
11262     {
11263       if (!toCreate)
11264       {
11265         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11266         return 1;
11267       }
11268
11269       addLight (aLightNew, aLayer, isGlobal);
11270       toCreate  = Standard_False;
11271       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
11272     }
11273     else if (anArgCase.IsEqual ("POSLIGHT")
11274           || anArgCase.IsEqual ("POSITIONAL"))
11275     {
11276       if (!toCreate)
11277       {
11278         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11279         return 1;
11280       }
11281
11282       addLight (aLightNew, aLayer, isGlobal);
11283       toCreate  = Standard_False;
11284       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
11285     }
11286     else if (anArgCase.IsEqual ("CHANGE")
11287           || anArgCase.IsEqual ("-CHANGE"))
11288     {
11289       if (++anArgIt >= theArgsNb)
11290       {
11291         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11292         return 1;
11293       }
11294
11295       addLight (aLightNew, aLayer, isGlobal);
11296       aLightNew.Nullify();
11297       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
11298       Standard_Integer aLightIt = 0;
11299       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
11300       {
11301         if (aLightIt == aLightId)
11302         {
11303           aLightOld = aLightIter.Value();
11304           break;
11305         }
11306       }
11307
11308       if (aLightOld.IsNull())
11309       {
11310         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
11311         return 1;
11312       }
11313     }
11314     else if (anArgCase.IsEqual ("DEL")
11315           || anArgCase.IsEqual ("DELETE")
11316           || anArgCase.IsEqual ("-DEL")
11317           || anArgCase.IsEqual ("-DELETE"))
11318     {
11319       Handle(V3d_Light) aLightDel;
11320       if (++anArgIt >= theArgsNb)
11321       {
11322         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11323         return 1;
11324       }
11325
11326       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
11327       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
11328       Standard_Integer aLightIt = 0;
11329       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
11330       {
11331         aLightDel = aLightIter.Value();
11332         if (aLightIt == aLightDelId)
11333         {
11334           break;
11335         }
11336       }
11337       if (aLightDel.IsNull())
11338       {
11339         continue;
11340       }
11341
11342       TColStd_SequenceOfInteger aLayers;
11343       aViewer->GetAllZLayers (aLayers);
11344       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
11345       {
11346         if (aLayeriter.Value() == aLayer
11347          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
11348         {
11349           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
11350           if (!aSettings.Lights().IsNull())
11351           {
11352             aSettings.Lights()->Remove (aLightDel);
11353             if (aSettings.Lights()->IsEmpty())
11354             {
11355               aSettings.SetLights (Handle(Graphic3d_LightSet)());
11356             }
11357           }
11358           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
11359           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
11360           {
11361             break;
11362           }
11363         }
11364       }
11365
11366       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
11367       {
11368         aViewer->DelLight (aLightDel);
11369       }
11370     }
11371     else if (anArgCase.IsEqual ("COLOR")
11372           || anArgCase.IsEqual ("COLOUR")
11373           || anArgCase.IsEqual ("-COLOR")
11374           || anArgCase.IsEqual ("-COLOUR"))
11375     {
11376       if (++anArgIt >= theArgsNb
11377        || aLightCurr.IsNull())
11378       {
11379         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11380         return 1;
11381       }
11382
11383       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
11384       anArgNext.UpperCase();
11385       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
11386       aLightCurr->SetColor (aColor);
11387     }
11388     else if (anArgCase.IsEqual ("POS")
11389           || anArgCase.IsEqual ("POSITION")
11390           || anArgCase.IsEqual ("-POS")
11391           || anArgCase.IsEqual ("-POSITION"))
11392     {
11393       if ((anArgIt + 3) >= theArgsNb
11394        || aLightCurr.IsNull()
11395        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11396         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11397       {
11398         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11399         return 1;
11400       }
11401
11402       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11403       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11404       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11405       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
11406     }
11407     else if (anArgCase.IsEqual ("DIR")
11408           || anArgCase.IsEqual ("DIRECTION")
11409           || anArgCase.IsEqual ("-DIR")
11410           || anArgCase.IsEqual ("-DIRECTION"))
11411     {
11412       if ((anArgIt + 3) >= theArgsNb
11413        || aLightCurr.IsNull()
11414        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
11415         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11416       {
11417         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11418         return 1;
11419       }
11420
11421       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11422       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11423       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11424       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
11425     }
11426     else if (anArgCase.IsEqual ("SM")
11427           || anArgCase.IsEqual ("SMOOTHNESS")
11428           || anArgCase.IsEqual ("-SM")
11429           || anArgCase.IsEqual ("-SMOOTHNESS"))
11430     {
11431       if (++anArgIt >= theArgsNb
11432        || aLightCurr.IsNull())
11433       {
11434         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11435         return 1;
11436       }
11437
11438       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11439       if (Abs (aSmoothness) <= ShortRealEpsilon())
11440       {
11441         aLightCurr->SetIntensity (1.f);
11442       }
11443       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
11444       {
11445         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
11446       }
11447       else
11448       {
11449         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
11450         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
11451       }
11452
11453       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
11454       {
11455         aLightCurr->SetSmoothRadius (aSmoothness);
11456       }
11457       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
11458       {
11459         aLightCurr->SetSmoothAngle (aSmoothness);
11460       }
11461     }
11462     else if (anArgCase.IsEqual ("INT")
11463           || anArgCase.IsEqual ("INTENSITY")
11464           || anArgCase.IsEqual ("-INT")
11465           || anArgCase.IsEqual ("-INTENSITY"))
11466     {
11467       if (++anArgIt >= theArgsNb
11468        || aLightCurr.IsNull())
11469       {
11470         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11471         return 1;
11472       }
11473
11474       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11475       aLightCurr->SetIntensity (aIntensity);
11476     }
11477     else if (anArgCase.IsEqual ("ANG")
11478           || anArgCase.IsEqual ("ANGLE")
11479           || anArgCase.IsEqual ("-ANG")
11480           || anArgCase.IsEqual ("-ANGLE"))
11481     {
11482       if (++anArgIt >= theArgsNb
11483        || aLightCurr.IsNull()
11484        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11485       {
11486         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11487         return 1;
11488       }
11489
11490       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11491       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
11492     }
11493     else if (anArgCase.IsEqual ("CONSTATTEN")
11494           || anArgCase.IsEqual ("CONSTATTENUATION")
11495           || anArgCase.IsEqual ("-CONSTATTEN")
11496           || anArgCase.IsEqual ("-CONSTATTENUATION"))
11497     {
11498       if (++anArgIt >= theArgsNb
11499        || aLightCurr.IsNull()
11500        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11501         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11502       {
11503         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11504         return 1;
11505       }
11506
11507       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11508       anAtten[0] = Atof (theArgVec[anArgIt]);
11509       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11510     }
11511     else if (anArgCase.IsEqual ("LINATTEN")
11512           || anArgCase.IsEqual ("LINEARATTEN")
11513           || anArgCase.IsEqual ("LINEARATTENUATION")
11514           || anArgCase.IsEqual ("-LINATTEN")
11515           || anArgCase.IsEqual ("-LINEARATTEN")
11516           || anArgCase.IsEqual ("-LINEARATTENUATION"))
11517     {
11518       if (++anArgIt >= theArgsNb
11519        || aLightCurr.IsNull()
11520        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11521         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11522       {
11523         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11524         return 1;
11525       }
11526
11527       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11528       anAtten[1] = Atof (theArgVec[anArgIt]);
11529       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11530     }
11531     else if (anArgCase.IsEqual ("EXP")
11532           || anArgCase.IsEqual ("EXPONENT")
11533           || anArgCase.IsEqual ("SPOTEXP")
11534           || anArgCase.IsEqual ("SPOTEXPONENT")
11535           || anArgCase.IsEqual ("-EXP")
11536           || anArgCase.IsEqual ("-EXPONENT")
11537           || anArgCase.IsEqual ("-SPOTEXP")
11538           || anArgCase.IsEqual ("-SPOTEXPONENT"))
11539     {
11540       if (++anArgIt >= theArgsNb
11541        || aLightCurr.IsNull()
11542        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11543       {
11544         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11545         return 1;
11546       }
11547
11548       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
11549     }
11550     else if (anArgCase.IsEqual ("HEAD")
11551           || anArgCase.IsEqual ("HEADLIGHT")
11552           || anArgCase.IsEqual ("-HEAD")
11553           || anArgCase.IsEqual ("-HEADLIGHT"))
11554     {
11555       if (aLightCurr.IsNull()
11556        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
11557       {
11558         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11559         return 1;
11560       }
11561
11562       Standard_Boolean isHeadLight = Standard_True;
11563       if (anArgIt + 1 < theArgsNb
11564        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
11565       {
11566         ++anArgIt;
11567       }
11568       aLightCurr->SetHeadlight (isHeadLight);
11569     }
11570     else
11571     {
11572       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
11573     }
11574   }
11575
11576   addLight (aLightNew, aLayer, isGlobal);
11577   return 0;
11578 }
11579
11580 //! Read Graphic3d_RenderingParams::PerfCounters flag.
11581 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
11582                                             Standard_Boolean& theToReset,
11583                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
11584                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
11585 {
11586   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
11587   TCollection_AsciiString aVal = theValue;
11588   Standard_Boolean toReverse = Standard_False;
11589   if (aVal == "none")
11590   {
11591     theToReset = Standard_True;
11592     return Standard_True;
11593   }
11594   else if (aVal.StartsWith ("-"))
11595   {
11596     toReverse = Standard_True;
11597     aVal = aVal.SubString (2, aVal.Length());
11598   }
11599   else if (aVal.StartsWith ("no"))
11600   {
11601     toReverse = Standard_True;
11602     aVal = aVal.SubString (3, aVal.Length());
11603   }
11604   else if (aVal.StartsWith ("+"))
11605   {
11606     aVal = aVal.SubString (2, aVal.Length());
11607   }
11608   else
11609   {
11610     theToReset = Standard_True;
11611   }
11612
11613   if (     aVal == "fps"
11614         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11615   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
11616   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
11617   else if (aVal == "structs"
11618         || aVal == "structures"
11619         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
11620   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
11621   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11622   else if (aVal == "tris"
11623         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
11624   else if (aVal == "pnts"
11625         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
11626   else if (aVal == "mem"
11627         || aVal == "gpumem"
11628         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11629   else if (aVal == "skipimmediate"
11630         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
11631   else if (aVal == "frametime"
11632         || aVal == "frametimers"
11633         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11634   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
11635   else if (aVal == "extended"
11636         || aVal == "verbose"
11637         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
11638   else if (aVal == "full"
11639         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
11640   else
11641   {
11642     return Standard_False;
11643   }
11644
11645   if (toReverse)
11646   {
11647     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11648   }
11649   else
11650   {
11651     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11652   }
11653   return Standard_True;
11654 }
11655
11656 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11657 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11658                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11659 {
11660   TCollection_AsciiString aValue = theValue;
11661   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11662   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11663   Standard_Boolean toReset = Standard_False;
11664   for (;;)
11665   {
11666     Standard_Integer aSplitPos = aValue.Search ("|");
11667     if (aSplitPos <= 0)
11668     {
11669       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11670       {
11671         return Standard_False;
11672       }
11673       if (toReset)
11674       {
11675         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11676       }
11677       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11678       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11679       return Standard_True;
11680     }
11681
11682     if (aSplitPos > 1)
11683     {
11684       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11685       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11686       {
11687         return Standard_False;
11688       }
11689     }
11690     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11691   }
11692 }
11693
11694 //=======================================================================
11695 //function : VRenderParams
11696 //purpose  : Enables/disables rendering features
11697 //=======================================================================
11698
11699 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11700                                        Standard_Integer  theArgNb,
11701                                        const char**      theArgVec)
11702 {
11703   Handle(V3d_View) aView = ViewerTest::CurrentView();
11704   if (aView.IsNull())
11705   {
11706     std::cerr << "Error: no active viewer!\n";
11707     return 1;
11708   }
11709
11710   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11711   TCollection_AsciiString aCmdName (theArgVec[0]);
11712   aCmdName.LowerCase();
11713   if (aCmdName == "vraytrace")
11714   {
11715     if (theArgNb == 1)
11716     {
11717       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11718       return 0;
11719     }
11720     else if (theArgNb == 2)
11721     {
11722       TCollection_AsciiString aValue (theArgVec[1]);
11723       aValue.LowerCase();
11724       if (aValue == "on"
11725        || aValue == "1")
11726       {
11727         aParams.Method = Graphic3d_RM_RAYTRACING;
11728         aView->Redraw();
11729         return 0;
11730       }
11731       else if (aValue == "off"
11732             || aValue == "0")
11733       {
11734         aParams.Method = Graphic3d_RM_RASTERIZATION;
11735         aView->Redraw();
11736         return 0;
11737       }
11738       else
11739       {
11740         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11741         return 1;
11742       }
11743     }
11744     else
11745     {
11746       std::cout << "Error: wrong number of arguments\n";
11747       return 1;
11748     }
11749   }
11750
11751   if (theArgNb < 2)
11752   {
11753     theDI << "renderMode:  ";
11754     switch (aParams.Method)
11755     {
11756       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11757       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11758     }
11759     theDI << "\n";
11760     theDI << "transparency:  ";
11761     switch (aParams.TransparencyMethod)
11762     {
11763       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11764       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11765                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11766     }
11767     theDI << "\n";
11768     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11769     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11770     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11771     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11772     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11773     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11774     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11775     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11776     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11777     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11778     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11779     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11780     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11781     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11782     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11783     theDI << "shadingModel: ";
11784     switch (aView->ShadingModel())
11785     {
11786       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
11787       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
11788       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
11789       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
11790       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
11791     }
11792     {
11793       theDI << "perfCounters:";
11794       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11795       {
11796         theDI << " fps";
11797       }
11798       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11799       {
11800         theDI << " cpu";
11801       }
11802       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11803       {
11804         theDI << " structs";
11805       }
11806       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11807       {
11808         theDI << " groups";
11809       }
11810       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11811       {
11812         theDI << " arrays";
11813       }
11814       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11815       {
11816         theDI << " tris";
11817       }
11818       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11819       {
11820         theDI << " pnts";
11821       }
11822       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11823       {
11824         theDI << " gpumem";
11825       }
11826       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11827       {
11828         theDI << " frameTime";
11829       }
11830       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11831       {
11832         theDI << " skipimmediate";
11833       }
11834       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11835       {
11836         theDI << " none";
11837       }
11838       theDI << "\n";
11839     }
11840     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11841     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11842     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11843                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11844                                                                                                                     "noUpdate") << "\n";
11845     theDI << "\n";
11846     return 0;
11847   }
11848
11849   Standard_Boolean toPrint = Standard_False;
11850   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11851   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11852   {
11853     Standard_CString        anArg (theArgVec[anArgIter]);
11854     TCollection_AsciiString aFlag (anArg);
11855     aFlag.LowerCase();
11856     if (anUpdateTool.parseRedrawMode (aFlag))
11857     {
11858       continue;
11859     }
11860     else if (aFlag == "-echo"
11861           || aFlag == "-print")
11862     {
11863       toPrint = Standard_True;
11864       anUpdateTool.Invalidate();
11865     }
11866     else if (aFlag == "-mode"
11867           || aFlag == "-rendermode"
11868           || aFlag == "-render_mode")
11869     {
11870       if (toPrint)
11871       {
11872         switch (aParams.Method)
11873         {
11874           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11875           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11876         }
11877         continue;
11878       }
11879       else
11880       {
11881         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11882         return 1;
11883       }
11884     }
11885     else if (aFlag == "-ray"
11886           || aFlag == "-raytrace")
11887     {
11888       if (toPrint)
11889       {
11890         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11891         continue;
11892       }
11893
11894       aParams.Method = Graphic3d_RM_RAYTRACING;
11895     }
11896     else if (aFlag == "-rast"
11897           || aFlag == "-raster"
11898           || aFlag == "-rasterization")
11899     {
11900       if (toPrint)
11901       {
11902         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11903         continue;
11904       }
11905
11906       aParams.Method = Graphic3d_RM_RASTERIZATION;
11907     }
11908     else if (aFlag == "-msaa")
11909     {
11910       if (toPrint)
11911       {
11912         theDI << aParams.NbMsaaSamples << " ";
11913         continue;
11914       }
11915       else if (++anArgIter >= theArgNb)
11916       {
11917         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11918         return 1;
11919       }
11920
11921       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11922       if (aNbSamples < 0)
11923       {
11924         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11925         return 1;
11926       }
11927       else
11928       {
11929         aParams.NbMsaaSamples = aNbSamples;
11930       }
11931     }
11932     else if (aFlag == "-linefeather"
11933           || aFlag == "-edgefeather"
11934           || aFlag == "-feather")
11935     {
11936       if (toPrint)
11937       {
11938         theDI << " " << aParams.LineFeather << " ";
11939         continue;
11940       }
11941       else if (++anArgIter >= theArgNb)
11942       {
11943         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11944         return 1;
11945       }
11946
11947       TCollection_AsciiString aParam = theArgVec[anArgIter];
11948       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11949       if (aFeather <= 0.0f)
11950       {
11951         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11952         return 1;
11953       }
11954       aParams.LineFeather = aFeather;
11955     }
11956     else if (aFlag == "-oit")
11957     {
11958       if (toPrint)
11959       {
11960         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11961         {
11962           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11963         }
11964         else
11965         {
11966           theDI << "off" << " ";
11967         }
11968         continue;
11969       }
11970       else if (++anArgIter >= theArgNb)
11971       {
11972         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11973         return 1;
11974       }
11975
11976       TCollection_AsciiString aParam = theArgVec[anArgIter];
11977       aParam.LowerCase();
11978       if (aParam.IsRealValue())
11979       {
11980         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11981         if (aWeight < 0.f || aWeight > 1.f)
11982         {
11983           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11984           return 1;
11985         }
11986
11987         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11988         aParams.OitDepthFactor     = aWeight;
11989       }
11990       else if (aParam == "off")
11991       {
11992         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11993       }
11994       else
11995       {
11996         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11997         return 1;
11998       }
11999     }
12000     else if (aFlag == "-depthprepass")
12001     {
12002       if (toPrint)
12003       {
12004         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
12005         continue;
12006       }
12007       aParams.ToEnableDepthPrepass = Standard_True;
12008       if (anArgIter + 1 < theArgNb
12009        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
12010       {
12011         ++anArgIter;
12012       }
12013     }
12014     else if (aFlag == "-samplealphatocoverage"
12015           || aFlag == "-alphatocoverage")
12016     {
12017       if (toPrint)
12018       {
12019         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
12020         continue;
12021       }
12022       aParams.ToEnableAlphaToCoverage = Standard_True;
12023       if (anArgIter + 1 < theArgNb
12024        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
12025       {
12026         ++anArgIter;
12027       }
12028     }
12029     else if (aFlag == "-rendscale"
12030           || aFlag == "-renderscale"
12031           || aFlag == "-renderresolutionscale")
12032     {
12033       if (toPrint)
12034       {
12035         theDI << aParams.RenderResolutionScale << " ";
12036         continue;
12037       }
12038       else if (++anArgIter >= theArgNb)
12039       {
12040         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12041         return 1;
12042       }
12043
12044       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
12045       if (aScale < 0.01)
12046       {
12047         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
12048         return 1;
12049       }
12050       else
12051       {
12052         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
12053       }
12054     }
12055     else if (aFlag == "-raydepth"
12056           || aFlag == "-ray_depth")
12057     {
12058       if (toPrint)
12059       {
12060         theDI << aParams.RaytracingDepth << " ";
12061         continue;
12062       }
12063       else if (++anArgIter >= theArgNb)
12064       {
12065         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12066         return 1;
12067       }
12068
12069       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
12070
12071       // We allow RaytracingDepth be more than 10 in case of GI enabled
12072       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
12073       {
12074         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
12075         return 1;
12076       }
12077       else
12078       {
12079         aParams.RaytracingDepth = aDepth;
12080       }
12081     }
12082     else if (aFlag == "-shad"
12083           || aFlag == "-shadows")
12084     {
12085       if (toPrint)
12086       {
12087         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
12088         continue;
12089       }
12090
12091       Standard_Boolean toEnable = Standard_True;
12092       if (++anArgIter < theArgNb
12093       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12094       {
12095         --anArgIter;
12096       }
12097       aParams.IsShadowEnabled = toEnable;
12098     }
12099     else if (aFlag == "-refl"
12100           || aFlag == "-reflections")
12101     {
12102       if (toPrint)
12103       {
12104         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
12105         continue;
12106       }
12107
12108       Standard_Boolean toEnable = Standard_True;
12109       if (++anArgIter < theArgNb
12110       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12111       {
12112         --anArgIter;
12113       }
12114       aParams.IsReflectionEnabled = toEnable;
12115     }
12116     else if (aFlag == "-fsaa")
12117     {
12118       if (toPrint)
12119       {
12120         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
12121         continue;
12122       }
12123
12124       Standard_Boolean toEnable = Standard_True;
12125       if (++anArgIter < theArgNb
12126       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12127       {
12128         --anArgIter;
12129       }
12130       aParams.IsAntialiasingEnabled = toEnable;
12131     }
12132     else if (aFlag == "-gleam")
12133     {
12134       if (toPrint)
12135       {
12136         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
12137         continue;
12138       }
12139
12140       Standard_Boolean toEnable = Standard_True;
12141       if (++anArgIter < theArgNb
12142       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12143       {
12144         --anArgIter;
12145       }
12146       aParams.IsTransparentShadowEnabled = toEnable;
12147     }
12148     else if (aFlag == "-gi")
12149     {
12150       if (toPrint)
12151       {
12152         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
12153         continue;
12154       }
12155
12156       Standard_Boolean toEnable = Standard_True;
12157       if (++anArgIter < theArgNb
12158       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12159       {
12160         --anArgIter;
12161       }
12162       aParams.IsGlobalIlluminationEnabled = toEnable;
12163       if (!toEnable)
12164       {
12165         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
12166       }
12167     }
12168     else if (aFlag == "-blockedrng"
12169           || aFlag == "-brng")
12170     {
12171       if (toPrint)
12172       {
12173         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
12174         continue;
12175       }
12176
12177       Standard_Boolean toEnable = Standard_True;
12178       if (++anArgIter < theArgNb
12179         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12180       {
12181         --anArgIter;
12182       }
12183       aParams.CoherentPathTracingMode = toEnable;
12184     }
12185     else if (aFlag == "-maxrad")
12186     {
12187       if (toPrint)
12188       {
12189         theDI << aParams.RadianceClampingValue << " ";
12190         continue;
12191       }
12192       else if (++anArgIter >= theArgNb)
12193       {
12194         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12195         return 1;
12196       }
12197
12198       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
12199       if (!aMaxRadStr.IsRealValue())
12200       {
12201         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12202         return 1;
12203       }
12204
12205       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
12206       if (aMaxRadiance <= 0.0)
12207       {
12208         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
12209         return 1;
12210       }
12211       else
12212       {
12213         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
12214       }
12215     }
12216     else if (aFlag == "-iss")
12217     {
12218       if (toPrint)
12219       {
12220         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
12221         continue;
12222       }
12223
12224       Standard_Boolean toEnable = Standard_True;
12225       if (++anArgIter < theArgNb
12226         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12227       {
12228         --anArgIter;
12229       }
12230       aParams.AdaptiveScreenSampling = toEnable;
12231     }
12232     else if (aFlag == "-issatomic")
12233     {
12234       if (toPrint)
12235       {
12236         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
12237         continue;
12238       }
12239
12240       Standard_Boolean toEnable = Standard_True;
12241       if (++anArgIter < theArgNb
12242       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12243       {
12244         --anArgIter;
12245       }
12246       aParams.AdaptiveScreenSamplingAtomic = toEnable;
12247     }
12248     else if (aFlag == "-issd")
12249     {
12250       if (toPrint)
12251       {
12252         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
12253         continue;
12254       }
12255
12256       Standard_Boolean toEnable = Standard_True;
12257       if (++anArgIter < theArgNb
12258         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12259       {
12260         --anArgIter;
12261       }
12262       aParams.ShowSamplingTiles = toEnable;
12263     }
12264     else if (aFlag == "-tilesize")
12265     {
12266       if (toPrint)
12267       {
12268         theDI << aParams.RayTracingTileSize << " ";
12269         continue;
12270       }
12271       else if (++anArgIter >= theArgNb)
12272       {
12273         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12274         return 1;
12275       }
12276
12277       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
12278       if (aTileSize < 1)
12279       {
12280         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
12281         return 1;
12282       }
12283       aParams.RayTracingTileSize = aTileSize;
12284     }
12285     else if (aFlag == "-nbtiles")
12286     {
12287       if (toPrint)
12288       {
12289         theDI << aParams.NbRayTracingTiles << " ";
12290         continue;
12291       }
12292       else if (++anArgIter >= theArgNb)
12293       {
12294         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12295         return 1;
12296       }
12297
12298       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
12299       if (aNbTiles < -1)
12300       {
12301         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
12302         return 1;
12303       }
12304       else if (aNbTiles > 0
12305             && (aNbTiles < 64
12306              || aNbTiles > 1024))
12307       {
12308         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
12309       }
12310       aParams.NbRayTracingTiles = aNbTiles;
12311     }
12312     else if (aFlag == "-env")
12313     {
12314       if (toPrint)
12315       {
12316         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
12317         continue;
12318       }
12319
12320       Standard_Boolean toEnable = Standard_True;
12321       if (++anArgIter < theArgNb
12322         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12323       {
12324         --anArgIter;
12325       }
12326       aParams.UseEnvironmentMapBackground = toEnable;
12327     }
12328     else if (aFlag == "-twoside")
12329     {
12330       if (toPrint)
12331       {
12332         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
12333         continue;
12334       }
12335
12336       Standard_Boolean toEnable = Standard_True;
12337       if (++anArgIter < theArgNb
12338         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12339       {
12340         --anArgIter;
12341       }
12342       aParams.TwoSidedBsdfModels = toEnable;
12343     }
12344     else if (aFlag == "-shademodel"
12345           || aFlag == "-shadingmodel"
12346           || aFlag == "-shading")
12347     {
12348       if (toPrint)
12349       {
12350         switch (aView->ShadingModel())
12351         {
12352           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
12353           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
12354           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
12355           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
12356           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
12357         }
12358         continue;
12359       }
12360
12361       if (++anArgIter >= theArgNb)
12362       {
12363         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12364       }
12365
12366       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
12367       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
12368        && aModel != Graphic3d_TOSM_DEFAULT)
12369       {
12370         aView->SetShadingModel (aModel);
12371       }
12372       else
12373       {
12374         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
12375         return 1;
12376       }
12377     }
12378     else if (aFlag == "-resolution")
12379     {
12380       if (++anArgIter >= theArgNb)
12381       {
12382         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12383         return 1;
12384       }
12385
12386       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
12387       if (aResolution.IsIntegerValue())
12388       {
12389         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
12390       }
12391       else
12392       {
12393         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12394         return 1;
12395       }
12396     }
12397     else if (aFlag == "-rebuildglsl"
12398           || aFlag == "-rebuild")
12399     {
12400       if (toPrint)
12401       {
12402         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
12403         continue;
12404       }
12405
12406       Standard_Boolean toEnable = Standard_True;
12407       if (++anArgIter < theArgNb
12408           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12409       {
12410         --anArgIter;
12411       }
12412       aParams.RebuildRayTracingShaders = toEnable;
12413     }
12414     else if (aFlag == "-focal")
12415     {
12416       if (++anArgIter >= theArgNb)
12417       {
12418         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12419         return 1;
12420       }
12421
12422       TCollection_AsciiString aParam (theArgVec[anArgIter]);
12423       if (aParam.IsRealValue())
12424       {
12425         float aFocalDist = static_cast<float> (aParam.RealValue());
12426         if (aFocalDist < 0)
12427         {
12428           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12429           return 1;
12430         }
12431         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
12432       }
12433       else
12434       {
12435         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12436         return 1;
12437       }
12438     }
12439     else if (aFlag == "-aperture")
12440     {
12441       if (++anArgIter >= theArgNb)
12442       {
12443         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12444         return 1;
12445       }
12446
12447       TCollection_AsciiString aParam(theArgVec[anArgIter]);
12448       if (aParam.IsRealValue())
12449       {
12450         float aApertureSize = static_cast<float> (aParam.RealValue());
12451         if (aApertureSize < 0)
12452         {
12453           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12454           return 1;
12455         }
12456         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
12457       }
12458       else
12459       {
12460         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12461         return 1;
12462       }
12463     }
12464     else if (aFlag == "-exposure")
12465     {
12466       if (++anArgIter >= theArgNb)
12467       {
12468         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12469         return 1;
12470       }
12471
12472       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
12473       if (anExposure.IsRealValue())
12474       {
12475         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
12476       }
12477       else
12478       {
12479         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12480         return 1;
12481       }
12482     }
12483     else if (aFlag == "-whitepoint")
12484     {
12485       if (++anArgIter >= theArgNb)
12486       {
12487         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12488         return 1;
12489       }
12490
12491       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
12492       if (aWhitePoint.IsRealValue())
12493       {
12494         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
12495       }
12496       else
12497       {
12498         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12499         return 1;
12500       }
12501     }
12502     else if (aFlag == "-tonemapping")
12503     {
12504       if (++anArgIter >= theArgNb)
12505       {
12506         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12507         return 1;
12508       }
12509
12510       TCollection_AsciiString aMode (theArgVec[anArgIter]);
12511       aMode.LowerCase();
12512
12513       if (aMode == "disabled")
12514       {
12515         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
12516       }
12517       else if (aMode == "filmic")
12518       {
12519         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
12520       }
12521       else
12522       {
12523         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12524         return 1;
12525       }
12526     }
12527     else if (aFlag == "-performancestats"
12528           || aFlag == "-performancecounters"
12529           || aFlag == "-perfstats"
12530           || aFlag == "-perfcounters"
12531           || aFlag == "-stats")
12532     {
12533       if (++anArgIter >= theArgNb)
12534       {
12535         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12536         return 1;
12537       }
12538
12539       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
12540       aFlagsStr.LowerCase();
12541       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
12542       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
12543       {
12544         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12545         return 1;
12546       }
12547       aView->ChangeRenderingParams().CollectedStats = aFlags;
12548       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
12549     }
12550     else if (aFlag == "-perfupdateinterval"
12551           || aFlag == "-statsupdateinterval")
12552     {
12553       if (++anArgIter >= theArgNb)
12554       {
12555         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12556         return 1;
12557       }
12558       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12559     }
12560     else if (aFlag == "-perfchart"
12561           || aFlag == "-statschart")
12562     {
12563       if (++anArgIter >= theArgNb)
12564       {
12565         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12566         return 1;
12567       }
12568       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
12569     }
12570     else if (aFlag == "-perfchartmax"
12571           || aFlag == "-statschartmax")
12572     {
12573       if (++anArgIter >= theArgNb)
12574       {
12575         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12576         return 1;
12577       }
12578       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12579     }
12580     else if (aFlag == "-frustumculling"
12581           || aFlag == "-culling")
12582     {
12583       if (toPrint)
12584       {
12585         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
12586                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
12587                                                                                                    "noUpdate") << " ";
12588         continue;
12589       }
12590
12591       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
12592       if (++anArgIter < theArgNb)
12593       {
12594         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
12595         aStateStr.LowerCase();
12596         bool toEnable = true;
12597         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
12598         {
12599           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
12600         }
12601         else if (aStateStr == "noupdate"
12602               || aStateStr == "freeze")
12603         {
12604           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
12605         }
12606         else
12607         {
12608           --anArgIter;
12609         }
12610       }
12611       aParams.FrustumCullingState = aState;
12612     }
12613     else
12614     {
12615       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
12616       return 1;
12617     }
12618   }
12619
12620   return 0;
12621 }
12622
12623 //=======================================================================
12624 //function : searchInfo
12625 //purpose  :
12626 //=======================================================================
12627 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12628                                            const TCollection_AsciiString&              theKey)
12629 {
12630   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12631   {
12632     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12633     {
12634       return anIter.Value();
12635     }
12636   }
12637   return TCollection_AsciiString();
12638 }
12639
12640 //=======================================================================
12641 //function : VStatProfiler
12642 //purpose  :
12643 //=======================================================================
12644 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12645                                        Standard_Integer  theArgNb,
12646                                        const char**      theArgVec)
12647 {
12648   Handle(V3d_View) aView = ViewerTest::CurrentView();
12649   if (aView.IsNull())
12650   {
12651     std::cerr << "Error: no active viewer!\n";
12652     return 1;
12653   }
12654
12655   Standard_Boolean toRedraw = Standard_True;
12656   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12657   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12658   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12659   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12660   {
12661     Standard_CString        anArg (theArgVec[anArgIter]);
12662     TCollection_AsciiString aFlag (anArg);
12663     aFlag.LowerCase();
12664     if (aFlag == "-noredraw")
12665     {
12666       toRedraw = Standard_False;
12667     }
12668     else
12669     {
12670       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12671       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12672       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12673       else if (aFlag == "alllayers"
12674             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12675       else if (aFlag == "allstructs"
12676             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12677       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12678       else if (aFlag == "allarrays"
12679             || aFlag == "fillarrays"
12680             || aFlag == "linearrays"
12681             || aFlag == "pointarrays"
12682             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12683       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12684       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12685       else if (aFlag == "geommem"
12686             || aFlag == "texturemem"
12687             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12688       else if (aFlag == "elapsedframe"
12689             || aFlag == "cpuframeaverage"
12690             || aFlag == "cpupickingaverage"
12691             || aFlag == "cpucullingaverage"
12692             || aFlag == "cpudynaverage"
12693             || aFlag == "cpuframemax"
12694             || aFlag == "cpupickingmax"
12695             || aFlag == "cpucullingmax"
12696             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12697       else
12698       {
12699         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12700         continue;
12701       }
12702
12703       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12704     }
12705   }
12706
12707   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12708   {
12709     aView->ChangeRenderingParams().CollectedStats =
12710       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12711
12712     if (toRedraw)
12713     {
12714       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12715       aView->Redraw();
12716       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12717     }
12718
12719     TColStd_IndexedDataMapOfStringString aDict;
12720     aView->StatisticInformation (aDict);
12721
12722     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12723
12724     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12725     {
12726       Standard_CString        anArg(theArgVec[anArgIter]);
12727       TCollection_AsciiString aFlag(anArg);
12728       aFlag.LowerCase();
12729       if (aFlag == "fps")
12730       {
12731         theDI << searchInfo (aDict, "FPS") << " ";
12732       }
12733       else if (aFlag == "cpu")
12734       {
12735         theDI << searchInfo (aDict, "CPU FPS") << " ";
12736       }
12737       else if (aFlag == "alllayers")
12738       {
12739         theDI << searchInfo (aDict, "Layers") << " ";
12740       }
12741       else if (aFlag == "layers")
12742       {
12743         theDI << searchInfo (aDict, "Rendered layers") << " ";
12744       }
12745       else if (aFlag == "allstructs")
12746       {
12747         theDI << searchInfo (aDict, "Structs") << " ";
12748       }
12749       else if (aFlag == "structs")
12750       {
12751         theDI << searchInfo (aDict, "Rendered structs") << " ";
12752       }
12753       else if (aFlag == "groups")
12754       {
12755         theDI << searchInfo (aDict, "Rendered groups") << " ";
12756       }
12757       else if (aFlag == "allarrays")
12758       {
12759         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12760       }
12761       else if (aFlag == "fillarrays")
12762       {
12763         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12764       }
12765       else if (aFlag == "linearrays")
12766       {
12767         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12768       }
12769       else if (aFlag == "pointarrays")
12770       {
12771         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12772       }
12773       else if (aFlag == "textarrays")
12774       {
12775         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12776       }
12777       else if (aFlag == "triangles")
12778       {
12779         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12780       }
12781       else if (aFlag == "points")
12782       {
12783         theDI << searchInfo (aDict, "Rendered points") << " ";
12784       }
12785       else if (aFlag == "geommem")
12786       {
12787         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12788       }
12789       else if (aFlag == "texturemem")
12790       {
12791         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12792       }
12793       else if (aFlag == "framemem")
12794       {
12795         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12796       }
12797       else if (aFlag == "elapsedframe")
12798       {
12799         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12800       }
12801       else if (aFlag == "cpuframe_average")
12802       {
12803         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12804       }
12805       else if (aFlag == "cpupicking_average")
12806       {
12807         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12808       }
12809       else if (aFlag == "cpuculling_average")
12810       {
12811         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12812       }
12813       else if (aFlag == "cpudyn_average")
12814       {
12815         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12816       }
12817       else if (aFlag == "cpuframe_max")
12818       {
12819         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12820       }
12821       else if (aFlag == "cpupicking_max")
12822       {
12823         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12824       }
12825       else if (aFlag == "cpuculling_max")
12826       {
12827         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12828       }
12829       else if (aFlag == "cpudyn_max")
12830       {
12831         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12832       }
12833     }
12834   }
12835   else
12836   {
12837     if (toRedraw)
12838     {
12839       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12840       aView->Redraw();
12841       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12842     }
12843     theDI << "Statistic info:\n" << aView->StatisticInformation();
12844   }
12845   return 0;
12846 }
12847
12848 //=======================================================================
12849 //function : VProgressiveMode
12850 //purpose  :
12851 //=======================================================================
12852 #if defined(_WIN32)
12853 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
12854                                           Standard_Integer  /*theNbArgs*/,
12855                                           const char**      /*theArgs*/)
12856 {
12857   Handle(V3d_View) aView = ViewerTest::CurrentView();
12858   if (aView.IsNull())
12859   {
12860     std::cerr << "Error: no active viewer!\n";
12861     return 1;
12862   }
12863
12864   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
12865
12866   for (;;)
12867   {
12868     aView->Redraw();
12869
12870     Standard_Boolean toExit = Standard_False;
12871
12872     MSG aMsg;
12873     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
12874     {
12875       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
12876       {
12877         toExit = Standard_True;
12878       }
12879
12880       TranslateMessage (&aMsg);
12881       DispatchMessageW (&aMsg);
12882     }
12883
12884     if (toExit)
12885     {
12886       break;
12887     }
12888   }
12889
12890   return 0;
12891 }
12892 #endif
12893
12894 //=======================================================================
12895 //function : VXRotate
12896 //purpose  :
12897 //=======================================================================
12898 static Standard_Integer VXRotate (Draw_Interpretor& di,
12899                                    Standard_Integer argc,
12900                                    const char ** argv)
12901 {
12902   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12903   if (aContext.IsNull())
12904   {
12905     di << argv[0] << "ERROR : use 'vinit' command before \n";
12906     return 1;
12907   }
12908
12909   if (argc != 3)
12910   {
12911     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12912     return 1;
12913   }
12914
12915   TCollection_AsciiString aName (argv[1]);
12916   Standard_Real anAngle = Draw::Atof (argv[2]);
12917
12918   // find object
12919   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12920   Handle(AIS_InteractiveObject) anIObj;
12921   if (!aMap.Find2 (aName, anIObj))
12922   {
12923     di << "Use 'vdisplay' before\n";
12924     return 1;
12925   }
12926
12927   gp_Trsf aTransform;
12928   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12929   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12930
12931   aContext->SetLocation (anIObj, aTransform);
12932   aContext->UpdateCurrentViewer();
12933   return 0;
12934 }
12935
12936 //===============================================================================================
12937 //class   : ViewerTest_AISManipulator
12938 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
12939 //===============================================================================================
12940 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12941
12942 class ViewerTest_AISManipulator : public AIS_Manipulator
12943 {
12944 public:
12945
12946   ViewerTest_AISManipulator() : AIS_Manipulator()
12947   {
12948     GetMapOfAISManipulators().Add (this);
12949   }
12950
12951   virtual ~ViewerTest_AISManipulator()
12952   {
12953     GetMapOfAISManipulators().Remove (this);
12954   }
12955
12956   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12957 };
12958
12959 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12960 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12961
12962 //===============================================================================================
12963 //function : VManipulator
12964 //purpose  :
12965 //===============================================================================================
12966 static int VManipulator (Draw_Interpretor& theDi,
12967                          Standard_Integer  theArgsNb,
12968                          const char**      theArgVec)
12969 {
12970   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
12971   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12972   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12973   if (aView.IsNull()
12974    || aViewer.IsNull())
12975   {
12976     std::cerr << "No active viewer!\n";
12977     return 1;
12978   }
12979
12980   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12981   Standard_Integer anArgIter = 1;
12982   for (; anArgIter < theArgsNb; ++anArgIter)
12983   {
12984     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12985   }
12986
12987   ViewerTest_CmdParser aCmd;
12988   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12989   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12990   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12991   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12992   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12993   aCmd.AddOption ("detach",         "...       - detach manipulator");
12994
12995   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12996   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12997   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12998
12999   aCmd.AddOption ("move",   "... x y z - move object");
13000   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
13001   aCmd.AddOption ("scale",  "... factor - scale object");
13002
13003   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
13004   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
13005   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
13006   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
13007   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
13008   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
13009   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
13010   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
13011   aCmd.AddOption ("size",              "... size - set size of manipulator");
13012   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
13013
13014   aCmd.Parse (theArgsNb, theArgVec);
13015
13016   if (aCmd.HasOption ("help"))
13017   {
13018     theDi.PrintHelp (theArgVec[0]);
13019     return 0;
13020   }
13021
13022   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
13023
13024   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
13025
13026   if (aName.IsEmpty())
13027   {
13028     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
13029     return 1;
13030   }
13031
13032   // ----------------------------------
13033   // detach existing manipulator object
13034   // ----------------------------------
13035
13036   if (aCmd.HasOption ("detach"))
13037   {
13038     if (!aMapAIS.IsBound2 (aName))
13039     {
13040       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
13041       return 1;
13042     }
13043
13044     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
13045     if (aManipulator.IsNull())
13046     {
13047       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
13048       return 1;
13049     }
13050
13051     aManipulator->Detach();
13052     aMapAIS.UnBind2 (aName);
13053     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
13054
13055     return 0;
13056   }
13057
13058   // -----------------------------------------------
13059   // find or create manipulator if it does not exist
13060   // -----------------------------------------------
13061
13062   Handle(AIS_Manipulator) aManipulator;
13063   if (!aMapAIS.IsBound2 (aName))
13064   {
13065     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
13066
13067     aManipulator = new ViewerTest_AISManipulator();
13068     aMapAIS.Bind (aManipulator, aName);
13069   }
13070   else
13071   {
13072     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
13073     if (aManipulator.IsNull())
13074     {
13075       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
13076       return 1;
13077     }
13078   }
13079
13080   // -----------------------------------------
13081   // change properties of manipulator instance
13082   // -----------------------------------------
13083
13084   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
13085   {
13086     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
13087   }
13088   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
13089   {
13090     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
13091   }
13092   if (aCmd.HasOption ("followRotation", 1, Standard_True))
13093   {
13094     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
13095   }
13096   if (aCmd.HasOption("followDragging", 1, Standard_True))
13097   {
13098     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
13099   }
13100   if (aCmd.HasOption ("gap", 1, Standard_True))
13101   {
13102     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
13103   }
13104   if (aCmd.HasOption ("part", 3, Standard_True))
13105   {
13106     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
13107     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
13108     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
13109     if (aMode < 1 || aMode > 4)
13110     {
13111       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
13112       return 1;
13113     }
13114
13115     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
13116   }
13117   if (aCmd.HasOption("parts", 2, Standard_True))
13118   {
13119     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
13120     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
13121     if (aMode < 1 || aMode > 4)
13122     {
13123       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
13124       return 1;
13125     }
13126
13127     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
13128   }
13129   if (aCmd.HasOption ("pos", 3, Standard_True))
13130   {
13131     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
13132     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
13133     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
13134
13135     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
13136   }
13137   if (aCmd.HasOption ("size", 1, Standard_True))
13138   {
13139     aManipulator->SetSize (aCmd.ArgFloat ("size"));
13140   }
13141   if (aCmd.HasOption ("zoomable", 1, Standard_True))
13142   {
13143     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
13144
13145     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
13146     {
13147       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
13148       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
13149     }
13150   }
13151
13152   // ---------------------------------------------------
13153   // attach, detach or access manipulator from an object
13154   // ---------------------------------------------------
13155
13156   if (aCmd.HasOption ("attach"))
13157   {
13158     // Find an object and attach manipulator to it
13159     if (!aCmd.HasOption ("attach", 1, Standard_True))
13160     {
13161       return 1;
13162     }
13163
13164     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
13165     Handle(AIS_InteractiveObject) anObject;
13166     if (!aMapAIS.Find2 (anObjName, anObject))
13167     {
13168       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
13169       return 1;
13170     }
13171
13172     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
13173     {
13174       if (anIt.Value()->IsAttached()
13175        && anIt.Value()->Object() == anObject)
13176       {
13177         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
13178         return 1;
13179       }
13180     }
13181
13182     AIS_Manipulator::OptionsForAttach anOptions;
13183     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
13184     {
13185       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
13186     }
13187     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
13188     {
13189       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
13190     }
13191     if (aCmd.HasOption ("enableModes", 1, Standard_True))
13192     {
13193       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
13194     }
13195
13196     aManipulator->Attach (anObject, anOptions);
13197   }
13198
13199   // --------------------------------------
13200   // apply transformation using manipulator
13201   // --------------------------------------
13202
13203   if (aCmd.HasOption ("startTransform", 2, Standard_True))
13204   {
13205     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
13206   }
13207   if (aCmd.HasOption ("transform", 2, Standard_True))
13208   {
13209     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
13210   }
13211   if (aCmd.HasOption ("stopTransform"))
13212   {
13213     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
13214
13215     aManipulator->StopTransform (toApply);
13216   }
13217
13218   gp_Trsf aT;
13219   if (aCmd.HasOption ("move", 3, Standard_True))
13220   {
13221     aT.SetTranslationPart (aCmd.ArgVec ("move"));
13222   }
13223   if (aCmd.HasOption ("rotate", 7, Standard_True))
13224   {
13225     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
13226   }
13227   if (aCmd.HasOption ("scale", 1))
13228   {
13229     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
13230   }
13231
13232   if (aT.Form() != gp_Identity)
13233   {
13234     aManipulator->Transform (aT);
13235   }
13236
13237   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
13238
13239   return 0;
13240 }
13241
13242 //===============================================================================================
13243 //function : VSelectionProperties
13244 //purpose  :
13245 //===============================================================================================
13246 static int VSelectionProperties (Draw_Interpretor& theDi,
13247                                  Standard_Integer  theArgsNb,
13248                                  const char**      theArgVec)
13249 {
13250   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
13251   if (aCtx.IsNull())
13252   {
13253     std::cerr << "No active viewer!\n";
13254     return 1;
13255   }
13256
13257   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
13258   {
13259     // handle obsolete alias
13260     bool toEnable = true;
13261     if (theArgsNb < 2)
13262     {
13263       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
13264       return 0;
13265     }
13266     else if (theArgsNb != 2
13267          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
13268     {
13269       std::cout << "Syntax error: wrong number of parameters.";
13270       return 1;
13271     }
13272     if (toEnable != aCtx->ToHilightSelected())
13273     {
13274       aCtx->ClearDetected();
13275       aCtx->SetToHilightSelected (toEnable);
13276     }
13277     return 0;
13278   }
13279
13280   Standard_Boolean toPrint  = theArgsNb == 1;
13281   Standard_Boolean toRedraw = Standard_False;
13282   Standard_Integer anArgIter = 1;
13283   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
13284   if (anArgIter < theArgsNb)
13285   {
13286     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
13287     anArgFirst.LowerCase();
13288     ++anArgIter;
13289     if (anArgFirst == "dynhighlight"
13290      || anArgFirst == "dynhilight"
13291      || anArgFirst == "dynamichighlight"
13292      || anArgFirst == "dynamichilight")
13293     {
13294       aType = Prs3d_TypeOfHighlight_Dynamic;
13295     }
13296     else if (anArgFirst == "localdynhighlight"
13297           || anArgFirst == "localdynhilight"
13298           || anArgFirst == "localdynamichighlight"
13299           || anArgFirst == "localdynamichilight")
13300     {
13301       aType = Prs3d_TypeOfHighlight_LocalDynamic;
13302     }
13303     else if (anArgFirst == "selhighlight"
13304           || anArgFirst == "selhilight"
13305           || anArgFirst == "selectedhighlight"
13306           || anArgFirst == "selectedhilight")
13307     {
13308       aType = Prs3d_TypeOfHighlight_Selected;
13309     }
13310     else if (anArgFirst == "localselhighlight"
13311           || anArgFirst == "localselhilight"
13312           || anArgFirst == "localselectedhighlight"
13313           || anArgFirst == "localselectedhilight")
13314     {
13315       aType = Prs3d_TypeOfHighlight_LocalSelected;
13316     }
13317     else
13318     {
13319       --anArgIter;
13320     }
13321   }
13322   for (; anArgIter < theArgsNb; ++anArgIter)
13323   {
13324     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13325     anArg.LowerCase();
13326     if (anArg == "-help")
13327     {
13328       theDi.PrintHelp (theArgVec[0]);
13329       return 0;
13330     }
13331     else if (anArg == "-print")
13332     {
13333       toPrint = Standard_True;
13334     }
13335     else if (anArg == "-autoactivate")
13336     {
13337       Standard_Boolean toEnable = Standard_True;
13338       if (anArgIter + 1 < theArgsNb
13339        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13340       {
13341         ++anArgIter;
13342       }
13343       aCtx->SetAutoActivateSelection (toEnable);
13344     }
13345     else if (anArg == "-automatichighlight"
13346           || anArg == "-automatichilight"
13347           || anArg == "-autohighlight"
13348           || anArg == "-autohilight")
13349     {
13350       Standard_Boolean toEnable = Standard_True;
13351       if (anArgIter + 1 < theArgsNb
13352        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13353       {
13354         ++anArgIter;
13355       }
13356       aCtx->ClearSelected (false);
13357       aCtx->ClearDetected();
13358       aCtx->SetAutomaticHilight (toEnable);
13359       toRedraw = true;
13360     }
13361     else if (anArg == "-highlightselected"
13362           || anArg == "-hilightselected")
13363     {
13364       Standard_Boolean toEnable = Standard_True;
13365       if (anArgIter + 1 < theArgsNb
13366        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13367       {
13368         ++anArgIter;
13369       }
13370       aCtx->ClearDetected();
13371       aCtx->SetToHilightSelected (toEnable);
13372       toRedraw = true;
13373     }
13374     else if (anArg == "-pickstrategy"
13375           || anArg == "-pickingstrategy")
13376     {
13377       if (++anArgIter >= theArgsNb)
13378       {
13379         std::cout << "Syntax error: type of highlighting is undefined\n";
13380         return 1;
13381       }
13382
13383       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13384       TCollection_AsciiString aVal (theArgVec[anArgIter]);
13385       aVal.LowerCase();
13386       if (aVal == "first"
13387        || aVal == "firstaccepted"
13388        || aVal == "firstacceptable")
13389       {
13390         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13391       }
13392       else if (aVal == "topmost"
13393             || aVal == "onlyTopmost")
13394       {
13395         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
13396       }
13397       else
13398       {
13399         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
13400         return 1;
13401       }
13402
13403       aCtx->SetPickingStrategy (aStrategy);
13404     }
13405     else if (anArg == "-pixtol"
13406           && anArgIter + 1 < theArgsNb)
13407     {
13408       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
13409     }
13410     else if ((anArg == "-mode"
13411            || anArg == "-dispmode")
13412           && anArgIter + 1 < theArgsNb)
13413     {
13414       if (aType == Prs3d_TypeOfHighlight_None)
13415       {
13416         std::cout << "Syntax error: type of highlighting is undefined\n";
13417         return 1;
13418       }
13419
13420       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
13421       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13422       aStyle->SetDisplayMode (aDispMode);
13423       toRedraw = Standard_True;
13424     }
13425     else if (anArg == "-layer"
13426           && anArgIter + 1 < theArgsNb)
13427     {
13428       if (aType == Prs3d_TypeOfHighlight_None)
13429       {
13430         std::cout << "Syntax error: type of highlighting is undefined\n";
13431         return 1;
13432       }
13433
13434       ++anArgIter;
13435       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
13436       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
13437       {
13438         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
13439         return 1;
13440       }
13441
13442       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13443       aStyle->SetZLayer (aNewLayer);
13444       toRedraw = Standard_True;
13445     }
13446     else if (anArg == "-hicolor"
13447           || anArg == "-selcolor"
13448           || anArg == "-color")
13449     {
13450       if (anArg.StartsWith ("-hi"))
13451       {
13452         aType = Prs3d_TypeOfHighlight_Dynamic;
13453       }
13454       else if (anArg.StartsWith ("-sel"))
13455       {
13456         aType = Prs3d_TypeOfHighlight_Selected;
13457       }
13458       else if (aType == Prs3d_TypeOfHighlight_None)
13459       {
13460         std::cout << "Syntax error: type of highlighting is undefined\n";
13461         return 1;
13462       }
13463
13464       Quantity_Color aColor;
13465       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
13466                                                            theArgVec + anArgIter + 1,
13467                                                            aColor);
13468       if (aNbParsed == 0)
13469       {
13470         std::cout << "Syntax error: need more arguments.\n";
13471         return 1;
13472       }
13473       anArgIter += aNbParsed;
13474
13475       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13476       aStyle->SetColor (aColor);
13477       toRedraw = Standard_True;
13478     }
13479     else if ((anArg == "-transp"
13480            || anArg == "-transparency"
13481            || anArg == "-hitransp"
13482            || anArg == "-seltransp"
13483            || anArg == "-hitransplocal"
13484            || anArg == "-seltransplocal")
13485           && anArgIter + 1 < theArgsNb)
13486     {
13487       if (anArg.StartsWith ("-hi"))
13488       {
13489         aType = Prs3d_TypeOfHighlight_Dynamic;
13490       }
13491       else if (anArg.StartsWith ("-sel"))
13492       {
13493         aType = Prs3d_TypeOfHighlight_Selected;
13494       }
13495       else if (aType == Prs3d_TypeOfHighlight_None)
13496       {
13497         std::cout << "Syntax error: type of highlighting is undefined\n";
13498         return 1;
13499       }
13500
13501       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
13502       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13503       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
13504       toRedraw = Standard_True;
13505     }
13506     else if ((anArg == "-mat"
13507            || anArg == "-material")
13508           && anArgIter + 1 < theArgsNb)
13509     {
13510       if (aType == Prs3d_TypeOfHighlight_None)
13511       {
13512         std::cout << "Syntax error: type of highlighting is undefined\n";
13513         return 1;
13514       }
13515
13516       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13517       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
13518       if (aMatName != Graphic3d_NOM_DEFAULT)
13519       {
13520         ++anArgIter;
13521         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
13522         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
13523         Graphic3d_MaterialAspect aMat (aMatName);
13524         aMat.SetColor (aStyle->Color());
13525         aMat.SetTransparency (aStyle->Transparency());
13526         anAspect->SetFrontMaterial (aMat);
13527         anAspect->SetInteriorColor (aStyle->Color());
13528         aStyle->SetBasicFillAreaAspect (anAspect);
13529       }
13530       else
13531       {
13532         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
13533       }
13534       toRedraw = Standard_True;
13535     }
13536     else
13537     {
13538       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
13539     }
13540   }
13541
13542   if (toPrint)
13543   {
13544     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
13545     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
13546     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
13547     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
13548     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
13549     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
13550     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
13551     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
13552     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
13553     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
13554     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
13555     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
13556     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
13557     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
13558   }
13559
13560   if (aCtx->NbSelected() != 0 && toRedraw)
13561   {
13562     aCtx->HilightSelected (Standard_True);
13563   }
13564
13565   return 0;
13566 }
13567
13568 //===============================================================================================
13569 //function : VDumpSelectionImage
13570 //purpose  :
13571 //===============================================================================================
13572 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
13573                                 Standard_Integer  theArgsNb,
13574                                 const char**      theArgVec)
13575 {
13576   if (theArgsNb < 2)
13577   {
13578     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
13579     return 1;
13580   }
13581
13582   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13583   if (aContext.IsNull())
13584   {
13585     std::cout << "Error: no active view.\n";
13586     return 1;
13587   }
13588
13589   TCollection_AsciiString aFile;
13590   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13591   Image_Format anImgFormat = Image_Format_BGR;
13592   Standard_Integer aPickedIndex = 1;
13593   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13594   {
13595     TCollection_AsciiString aParam (theArgVec[anArgIter]);
13596     aParam.LowerCase();
13597     if (aParam == "-type")
13598     {
13599       if (++anArgIter >= theArgsNb)
13600       {
13601         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
13602         return 1;
13603       }
13604
13605       TCollection_AsciiString aValue (theArgVec[anArgIter]);
13606       aValue.LowerCase();
13607       if (aValue == "depth"
13608        || aValue == "normdepth"
13609        || aValue == "normalizeddepth")
13610       {
13611         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13612         anImgFormat = Image_Format_GrayF;
13613       }
13614       if (aValue == "depthinverted"
13615        || aValue == "normdepthinverted"
13616        || aValue == "normalizeddepthinverted"
13617        || aValue == "inverted")
13618       {
13619         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
13620         anImgFormat = Image_Format_GrayF;
13621       }
13622       else if (aValue == "unnormdepth"
13623             || aValue == "unnormalizeddepth")
13624       {
13625         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
13626         anImgFormat = Image_Format_GrayF;
13627       }
13628       else if (aValue == "objectcolor"
13629             || aValue == "object"
13630             || aValue == "color")
13631       {
13632         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13633       }
13634       else if (aValue == "entitycolor"
13635             || aValue == "entity")
13636       {
13637         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13638       }
13639       else if (aValue == "ownercolor"
13640             || aValue == "owner")
13641       {
13642         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13643       }
13644       else if (aValue == "selectionmodecolor"
13645             || aValue == "selectionmode"
13646             || aValue == "selmodecolor"
13647             || aValue == "selmode")
13648       {
13649         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13650       }
13651     }
13652     else if (aParam == "-picked"
13653           || aParam == "-pickeddepth"
13654           || aParam == "-pickedindex")
13655     {
13656       if (++anArgIter >= theArgsNb)
13657       {
13658         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13659         return 1;
13660       }
13661
13662       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13663     }
13664     else if (aFile.IsEmpty())
13665     {
13666       aFile = theArgVec[anArgIter];
13667     }
13668     else
13669     {
13670       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13671       return 1;
13672     }
13673   }
13674   if (aFile.IsEmpty())
13675   {
13676     std::cout << "Syntax error: image file name is missing.\n";
13677     return 1;
13678   }
13679
13680   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13681   Standard_Integer aWidth = 0, aHeight = 0;
13682   aView->Window()->Size (aWidth, aHeight);
13683
13684   Image_AlienPixMap aPixMap;
13685   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13686   {
13687     std::cout << "Error: can't allocate image.\n";
13688     return 1;
13689   }
13690   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13691   {
13692     std::cout << "Error: can't generate selection image.\n";
13693     return 1;
13694   }
13695   if (!aPixMap.Save (aFile))
13696   {
13697     std::cout << "Error: can't save selection image.\n";
13698     return 0;
13699   }
13700   return 0;
13701 }
13702
13703 //=======================================================================
13704 //function : ViewerCommands
13705 //purpose  :
13706 //=======================================================================
13707
13708 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13709 {
13710
13711   const char *group = "ZeViewer";
13712   theCommands.Add("vinit",
13713           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13714     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13715   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13716     "\n\t\t:     [-display displayName]"
13717   #endif
13718     "\n\t\t: Creates new View window with specified name viewName."
13719     "\n\t\t: By default the new view is created in the viewer and in"
13720     "\n\t\t: graphic driver shared with active view."
13721     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13722     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13723     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13724 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13725     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13726     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13727 #endif
13728     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13729     "\n\t\t:  -width, -height width and heigth of window respectively."
13730     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13731     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13732     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13733     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13734     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13735     __FILE__,VInit,group);
13736   theCommands.Add("vclose" ,
13737     "[view_id [keep_context=0|1]]\n"
13738     "or vclose ALL - to remove all created views\n"
13739     " - removes view(viewer window) defined by its view_id.\n"
13740     " - keep_context: by default 0; if 1 and the last view is deleted"
13741     " the current context is not removed.",
13742     __FILE__,VClose,group);
13743   theCommands.Add("vactivate" ,
13744     "vactivate view_id [-noUpdate]"
13745     " - activates view(viewer window) defined by its view_id",
13746     __FILE__,VActivate,group);
13747   theCommands.Add("vviewlist",
13748     "vviewlist [format={tree, long}]"
13749     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13750     " - format: format of result output, if tree the output is a tree view;"
13751     "otherwise it's a list of full view names. By default format = tree",
13752     __FILE__,VViewList,group);
13753   theCommands.Add("vhelp" ,
13754     "vhelp            : display help on the viewer commands",
13755     __FILE__,VHelp,group);
13756   theCommands.Add("vviewproj",
13757           "vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]"
13758     "\n\t\t:         [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]"
13759     "\n\t\t: Setup view direction"
13760     "\n\t\t:   -Yup      use Y-up convention instead of Zup (which is default)."
13761     "\n\t\t:   +-X+-Y+-Z define direction as combination of DX, DY and DZ;"
13762     "\n\t\t:             for example '+Z' will show front of the model,"
13763     "\n\t\t:             '-X-Y+Z' will define left axonometrical view."
13764     "\n\t\t:   -frame    define camera Up and Right directions (regardless Up convention);"
13765     "\n\t\t:             for example '+X+Z' will show front of the model with Z-up."
13766     __FILE__,VViewProj,group);
13767   theCommands.Add("vtop" ,
13768     "vtop or <T>      : Top view. Orientation +X+Y" ,
13769     __FILE__,VViewProj,group);
13770   theCommands.Add("vbottom" ,
13771     "vbottom          : Bottom view. Orientation +X-Y" ,
13772     __FILE__,VViewProj,group);
13773   theCommands.Add("vleft" ,
13774     "vleft            : Left view. Orientation -Y+Z" ,
13775     __FILE__,VViewProj,group);
13776   theCommands.Add("vright" ,
13777     "vright           : Right view. Orientation +Y+Z" ,
13778     __FILE__,VViewProj,group);
13779   theCommands.Add("vaxo" ,
13780     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13781     __FILE__,VViewProj,group);
13782   theCommands.Add("vfront" ,
13783     "vfront           : Front view. Orientation +X+Z" ,
13784     __FILE__,VViewProj,group);
13785   theCommands.Add("vback" ,
13786     "vback            : Back view. Orientation -X+Z" ,
13787     __FILE__,VViewProj,group);
13788   theCommands.Add("vpick" ,
13789     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13790     VPick,group);
13791   theCommands.Add("vfit",
13792     "vfit or <F> [-selected] [-noupdate]"
13793     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13794     __FILE__,VFit,group);
13795   theCommands.Add ("vfitarea",
13796     "vfitarea x1 y1 x2 y2"
13797     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13798     "\n\t\t: Fit view to show area located between two points"
13799     "\n\t\t: given in world 2D or 3D corrdinates.",
13800     __FILE__, VFitArea, group);
13801   theCommands.Add ("vzfit", "vzfit [scale]\n"
13802     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13803     "   \"scale\" - specifies factor to scale computed z range.\n",
13804     __FILE__, VZFit, group);
13805   theCommands.Add("vrepaint",
13806             "vrepaint [-immediate] [-continuous FPS]"
13807     "\n\t\t: force redraw of active View"
13808     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13809     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13810     "\n\t\t:                0 means no continuous rendering,"
13811     "\n\t\t:               -1 means non-stop redraws,"
13812     "\n\t\t:               >0 specifies target framerate,",
13813     __FILE__,VRepaint,group);
13814   theCommands.Add("vclear",
13815     "vclear          : vclear"
13816     "\n\t\t: remove all the object from the viewer",
13817     __FILE__,VClear,group);
13818   theCommands.Add (
13819     "vbackground",
13820     "Changes background or some background settings.\n"
13821     "\n"
13822     "Usage:\n"
13823     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13824     "  vbackground -imageMode FillType\n"
13825     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13826     "  vbackground -gradientMode FillMethod\n"
13827     "  vbackground -color Color\n"
13828     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13829     "  vbackground -default -color Color\n"
13830     "  vbackground -help\n"
13831     "\n"
13832     "Options:\n"
13833     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13834     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13835     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13836     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13837     "  -color        (-col):                               sets background color\n"
13838     "  -default      (-def):                               sets background default gradient or color\n"
13839     "  -help         (-h):                                 outputs short help message\n"
13840     "\n"
13841     "Arguments:\n"
13842     "  Color:      Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13843     "                                  or reals within the range [0.0, 1.0]\n"
13844     "              ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13845     "              #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13846     "  FillMethod: one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13847     "CORNER4\n"
13848     "  FillType:   one of CENTERED, TILED, STRETCH, NONE\n"
13849     "  ImageFile:  a name of the file with the image used as a background\n",
13850     __FILE__,
13851     vbackground,
13852     group);
13853   theCommands.Add ("vsetbg",
13854                    "Loads image as background."
13855                    "\n\t\t: vsetbg ImageFile [FillType]"
13856                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13857                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13858                    __FILE__,
13859                    vbackground,
13860                    group);
13861   theCommands.Add ("vsetbgmode",
13862                    "Changes background image fill type."
13863                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13864                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13865                    __FILE__,
13866                    vbackground,
13867                    group);
13868   theCommands.Add ("vsetgradientbg",
13869                    "Mounts gradient background."
13870                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13871                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13872                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13873                    __FILE__,
13874                    vbackground,
13875                    group);
13876   theCommands.Add ("vsetgrbgmode",
13877                    "Changes gradient background fill method."
13878                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13879                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13880                    __FILE__,
13881                    vbackground,
13882                    group);
13883   theCommands.Add ("vsetcolorbg",
13884                    "Sets background color."
13885                    "\n\t\t: vsetcolorbg [-color] Color."
13886                    "\n\t\t: Alias for 'vbackground -color Color'.",
13887                    __FILE__,
13888                    vbackground,
13889                    group);
13890   theCommands.Add ("vsetdefaultbg",
13891                    "Sets default viewer background fill color (flat/gradient)."
13892                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13893                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13894                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13895                    "\n\t\t: vsetdefaultbg [-color] Color"
13896                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13897                    __FILE__,
13898                    vbackground,
13899                    group);
13900   theCommands.Add("vscale",
13901     "vscale          : vscale X Y Z",
13902     __FILE__,VScale,group);
13903   theCommands.Add("vzbufftrihedron",
13904             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13905     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13906     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13907     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13908     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13909     "\n\t\t: Displays a trihedron",
13910     __FILE__,VZBuffTrihedron,group);
13911   theCommands.Add("vrotate",
13912     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13913     "\n                : Option -mouseStart starts rotation according to the mouse position"
13914     "\n                : Option -mouseMove continues rotation with angle computed"
13915     "\n                : from last and new mouse position."
13916     "\n                : vrotate AX AY AZ [X Y Z]",
13917     __FILE__,VRotate,group);
13918   theCommands.Add("vzoom",
13919     "vzoom           : vzoom coef",
13920     __FILE__,VZoom,group);
13921   theCommands.Add("vpan",
13922     "vpan            : vpan dx dy",
13923     __FILE__,VPan,group);
13924   theCommands.Add("vcolorscale",
13925     "vcolorscale name [-noupdate|-update] [-demo]"
13926     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13927     "\n\t\t:       [-font HeightFont=20]"
13928     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13929     "\n\t\t:       [-smoothTransition {on|off}=off]"
13930     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13931     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13932     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13933     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13934     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13935     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13936     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13937     "\n\t\t:       [-xy Left=0 Bottom=0]"
13938     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13939     "\n\t\t:  -colors   - set colors for all intervals"
13940     "\n\t\t:  -color    - set color for specific interval"
13941     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
13942     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
13943     "\n\t\t:              at border means the value inbetween neighbor intervals,"
13944     "\n\t\t:              at center means the center value within current interval"
13945     "\n\t\t:  -labels   - set labels for all intervals"
13946     "\n\t\t:  -freeLabels - same as -labels but does not require"
13947     "\n\t\t:              matching the number of intervals"
13948     "\n\t\t:  -label    - set label for specific interval"
13949     "\n\t\t:  -title    - set title"
13950     "\n\t\t:  -reversed - setup smooth color transition between intervals"
13951     "\n\t\t:  -smoothTransition - swap colorscale direction"
13952     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
13953     __FILE__, VColorScale, group);
13954   theCommands.Add("vgraduatedtrihedron",
13955     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
13956     "\t[-namefont Name] [-valuesfont Name]\n"
13957     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
13958     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
13959     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
13960     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
13961     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
13962     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
13963     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
13964     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
13965     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
13966     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
13967     " - Displays or erases graduated trihedron"
13968     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
13969     " - namefont - font of axes names. Default: Arial\n"
13970     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
13971     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
13972     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
13973     " - valuesfont - font of axes values. Default: Arial\n"
13974     " - xcolor, ycolor, zcolor - color of axis and values\n"
13975     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
13976     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
13977     __FILE__,VGraduatedTrihedron,group);
13978   theCommands.Add("vtile" ,
13979             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
13980     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
13981     "\n\t\t:  -totalSize the size of virtual bigger viewport"
13982     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
13983     "\n\t\t:  -lowerLeft tile offset as lower left corner"
13984     "\n\t\t:  -upperLeft tile offset as upper left corner",
13985     __FILE__, VTile, group);
13986   theCommands.Add("vzlayer",
13987               "vzlayer [layerId]"
13988       "\n\t\t:         [-add|-delete|-get|-settings]"
13989       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
13990       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
13991       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
13992       "\n\t\t: ZLayer list management:"
13993       "\n\t\t:   -add      add new z layer to viewer and print its id"
13994       "\n\t\t:   -delete   delete z layer"
13995       "\n\t\t:   -get      print sequence of z layers"
13996       "\n\t\t:   -settings print status of z layer settings"
13997       "\n\t\t:   -disable  disables given setting"
13998       "\n\t\t:   -enable   enables  given setting",
13999     __FILE__,VZLayer,group);
14000   theCommands.Add("vlayerline",
14001     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
14002     __FILE__,VLayerLine,group);
14003   theCommands.Add("vgrid",
14004               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
14005       "\n\t\t:       [-step X Y] [-size DX DY]"
14006       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
14007     __FILE__, VGrid, group);
14008   theCommands.Add ("vpriviledgedplane",
14009     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
14010     "\n\t\t:   Ox, Oy, Oz - plane origin"
14011     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
14012     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
14013     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
14014     __FILE__, VPriviledgedPlane, group);
14015   theCommands.Add ("vconvert",
14016     "vconvert v [Mode={window|view}]"
14017     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
14018     "\n\t\t: vconvert x y z [Mode={window|grid}]"
14019     "\n\t\t:   window - convert to window coordinates, pixels"
14020     "\n\t\t:   view   - convert to view projection plane"
14021     "\n\t\t:   grid   - convert to model coordinates, given on grid"
14022     "\n\t\t:   ray    - convert projection ray to model coordiantes"
14023     "\n\t\t: - vconvert v window : convert view to window;"
14024     "\n\t\t: - vconvert v view   : convert window to view;"
14025     "\n\t\t: - vconvert x y window : convert view to window;"
14026     "\n\t\t: - vconvert x y view : convert window to view;"
14027     "\n\t\t: - vconvert x y : convert window to model;"
14028     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
14029     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
14030     "\n\t\t: - vconvert x y z window : convert model to window;"
14031     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
14032     "\n\t\t: Converts the given coordinates to window/view/model space.",
14033     __FILE__, VConvert, group);
14034   theCommands.Add ("vfps",
14035     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
14036     __FILE__, VFps, group);
14037   theCommands.Add ("vgldebug",
14038             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
14039     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
14040     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
14041     "\n\t\t: Debug context can be requested only on Windows"
14042     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
14043     "\n\t\t:  -sync     - request synchronized debug GL context"
14044     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
14045     "\n\t\t:              which are suppressed by default,"
14046     "\n\t\t:  -glslCode - log GLSL program source code,"
14047     "\n\t\t:              which are suppressed by default,"
14048     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
14049     "\n\t\t:              which are suppressed by default",
14050     __FILE__, VGlDebug, group);
14051   theCommands.Add ("vvbo",
14052     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
14053     __FILE__, VVbo, group);
14054   theCommands.Add ("vstereo",
14055             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
14056     "\n\t\t:         [-anaglyph Filter]"
14057     "\n\t\t: Control stereo output mode. Available modes for -mode:"
14058     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
14059     "\n\t\t:                     requires driver support."
14060     "\n\t\t:                     Should be called BEFORE vinit!"
14061     "\n\t\t:  anaglyph         - Anaglyph glasses"
14062     "\n\t\t:  rowInterlaced    - row-interlaced display"
14063     "\n\t\t:  columnInterlaced - column-interlaced display"
14064     "\n\t\t:  chessBoard       - chess-board output"
14065     "\n\t\t:  sideBySide       - horizontal pair"
14066     "\n\t\t:  overUnder        - vertical   pair"
14067     "\n\t\t: Available Anaglyph filters for -anaglyph:"
14068     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
14069     "\n\t\t:  greenMagentaSimple",
14070     __FILE__, VStereo, group);
14071   theCommands.Add ("vcaps",
14072             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
14073     "\n\t\t:       [-compatibleProfile {0|1}]"
14074     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
14075     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
14076     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
14077     "\n\t\t: Modify particular graphic driver options:"
14078     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
14079     "\n\t\t:             built-in GLSL programs"
14080     "\n\t\t:            (requires compatible profile)"
14081     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
14082     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
14083     "\n\t\t:             arrays to GPU memory)"
14084     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
14085     "\n\t\t:  vsync    - switch VSync on or off"
14086     "\n\t\t:  winBuffer - allow using window buffer for rendering"
14087     "\n\t\t: Context creation options:"
14088     "\n\t\t:  softMode          - software OpenGL implementation"
14089     "\n\t\t:  compatibleProfile - backward-compatible profile"
14090     "\n\t\t:  quadbuffer        - QuadBuffer"
14091     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
14092     "\n\t\t: rendering paths producing the same visual result when"
14093     "\n\t\t: possible."
14094     "\n\t\t: Command is intended for testing old hardware compatibility.",
14095     __FILE__, VCaps, group);
14096   theCommands.Add ("vmemgpu",
14097     "vmemgpu [f]: print system-dependent GPU memory information if available;"
14098     " with f option returns free memory in bytes",
14099     __FILE__, VMemGpu, group);
14100   theCommands.Add ("vreadpixel",
14101     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
14102     " : Read pixel value for active view",
14103     __FILE__, VReadPixel, group);
14104   theCommands.Add("diffimage",
14105             "diffimage imageFile1 imageFile2 [diffImageFile]"
14106     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
14107     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
14108     "\n\t\t: Compare two images by content and generate difference image."
14109     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
14110     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
14111     __FILE__, VDiffImage, group);
14112   theCommands.Add ("vselect",
14113     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
14114     "- emulates different types of selection:\n"
14115     "- 1) single click selection\n"
14116     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
14117     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
14118     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
14119     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
14120     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
14121     " (partial inclusion - overlap - is not allowed by default)\n"
14122     "- 5) any of these selections with shift button pressed",
14123     __FILE__, VSelect, group);
14124   theCommands.Add ("vmoveto",
14125     "vmoveto [x y] [-reset]"
14126     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
14127     "\n\t\t:   -reset resets current highlighting",
14128     __FILE__, VMoveTo, group);
14129   theCommands.Add ("vviewparams",
14130               "vviewparams [-args] [-scale [s]]"
14131       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
14132       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
14133       "\n\t\t: Manage current view parameters or prints all"
14134       "\n\t\t: current values when called without argument."
14135       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
14136       "\n\t\t:   -eye  [x y z] prints or sets eye location"
14137       "\n\t\t:   -at   [x y z] prints or sets center of look"
14138       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
14139       "\n\t\t:   -proj [x y z] prints or sets direction of look"
14140       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
14141       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
14142       "\n\t\t:                 or changes the size of its maximum dimension"
14143       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
14144     __FILE__, VViewParams, group);
14145
14146   theCommands.Add("v2dmode",
14147     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
14148     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
14149     "\n\t\t:   mode   - switches On/Off rotation mode"
14150     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
14151     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
14152     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
14153     "\n\t\t: View camera position might be changed only by commands.",
14154     __FILE__, V2DMode, group);
14155
14156   theCommands.Add("vanimation", "Alias for vanim",
14157     __FILE__, VAnimation, group);
14158
14159   theCommands.Add("vanim",
14160             "List existing animations:"
14161     "\n\t\t:  vanim"
14162     "\n\t\t: Animation playback:"
14163     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
14164     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
14165     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
14166     "\n\t\t:   -freeLook skip camera animations"
14167     "\n\t\t:   -lockLoop disable any interactions"
14168     "\n\t\t:"
14169     "\n\t\t: Animation definition:"
14170     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
14171     "\n\t\t:        [start TimeSec] [duration TimeSec]"
14172     "\n\t\t:"
14173     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
14174     "\n\t\t: specifies nested animations."
14175     "\n\t\t: There is no syntax to explicitly add new animation,"
14176     "\n\t\t: and all non-existing animations within the name will be"
14177     "\n\t\t: implicitly created on first use (including parents)."
14178     "\n\t\t:"
14179     "\n\t\t: Each animation might define the SINGLE action (see below),"
14180     "\n\t\t: like camera transition, object transformation or custom callback."
14181     "\n\t\t: Child animations can be used for defining concurrent actions."
14182     "\n\t\t:"
14183     "\n\t\t: Camera animation:"
14184     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
14185     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
14186     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
14187     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
14188     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
14189     "\n\t\t:   -atX    camera Center positions pair"
14190     "\n\t\t:   -upX    camera Up directions pair"
14191     "\n\t\t:   -scaleX camera Scale factors pair"
14192     "\n\t\t: Object animation:"
14193     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
14194     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
14195     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
14196     "\n\t\t:   -locX   object Location points pair (translation)"
14197     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
14198     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
14199     "\n\t\t: Custom callback:"
14200     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
14201     "\n\t\t:   %Pts        overall animation presentation timestamp"
14202     "\n\t\t:   %LocalPts   local animation timestamp"
14203     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
14204     "\n\t\t:"
14205     "\n\t\t: Video recording:"
14206     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
14207     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
14208     "\n\t\t:             [-crf Value] [-preset Preset]"
14209     "\n\t\t:   -fps     video framerate"
14210     "\n\t\t:   -format  file format, container (matroska, etc.)"
14211     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
14212     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
14213     "\n\t\t:   -crf     constant rate factor (specific to codec)"
14214     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
14215     __FILE__, VAnimation, group);
14216
14217   theCommands.Add("vchangeselected",
14218     "vchangeselected shape"
14219     "- adds to shape to selection or remove one from it",
14220                 __FILE__, VChangeSelected, group);
14221   theCommands.Add ("vnbselected",
14222     "vnbselected"
14223     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
14224   theCommands.Add ("vcamera",
14225               "vcamera [PrsName] [-ortho] [-projtype]"
14226       "\n\t\t:         [-persp]"
14227       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
14228       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
14229       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
14230       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
14231       "\n\t\t: Manages camera parameters."
14232       "\n\t\t: Displays frustum when presntation name PrsName is specified."
14233       "\n\t\t: Prints current value when option called without argument."
14234       "\n\t\t: Orthographic camera:"
14235       "\n\t\t:   -ortho      activate orthographic projection"
14236       "\n\t\t: Perspective camera:"
14237       "\n\t\t:   -persp      activate perspective  projection (mono)"
14238       "\n\t\t:   -fovy       field of view in y axis, in degrees"
14239       "\n\t\t:   -distance   distance of eye from camera center"
14240       "\n\t\t: Stereoscopic camera:"
14241       "\n\t\t:   -stereo     perspective  projection (stereo)"
14242       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
14243       "\n\t\t:   -rightEye   perspective  projection (right eye)"
14244       "\n\t\t:   -iod        intraocular distance value"
14245       "\n\t\t:   -iodType    distance type, absolute or relative"
14246       "\n\t\t:   -zfocus     stereographic focus value"
14247       "\n\t\t:   -zfocusType focus type, absolute or relative",
14248     __FILE__, VCamera, group);
14249   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
14250     "- vautozfit [on={1|0}] [scale]\n"
14251     "    Prints or changes parameters of automatic z-fit mode:\n"
14252     "   \"on\" - turns automatic z-fit on or off\n"
14253     "   \"scale\" - specifies factor to scale computed z range.\n",
14254     __FILE__, VAutoZFit, group);
14255   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
14256     "   vzrange                - without parameters shows current values\n"
14257     "   vzrange [znear] [zfar] - applies provided values to view",
14258     __FILE__,VZRange, group);
14259   theCommands.Add ("vpurgedisplay",
14260     "vpurgedisplay"
14261     "- removes structures which don't belong to objects displayed in neutral point",
14262     __FILE__, VPurgeDisplay, group);
14263   theCommands.Add("vsetviewsize",
14264     "vsetviewsize size",
14265     __FILE__,VSetViewSize,group);
14266   theCommands.Add("vmoveview",
14267     "vmoveview Dx Dy Dz [Start = 1|0]",
14268     __FILE__,VMoveView,group);
14269   theCommands.Add("vtranslateview",
14270     "vtranslateview Dx Dy Dz [Start = 1|0)]",
14271     __FILE__,VTranslateView,group);
14272   theCommands.Add("vturnview",
14273     "vturnview Ax Ay Az [Start = 1|0]",
14274     __FILE__,VTurnView,group);
14275   theCommands.Add("vtextureenv",
14276     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
14277     "or user-defined file and optionally applying texture mapping parameters\n"
14278     "                  Usage:\n"
14279     "                  vtextureenv off - disables environment mapping\n"
14280     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
14281     "                              std_texture = (0..7)\n"
14282     "                              rep         = {clamp|repeat}\n"
14283     "                              mod         = {decal|modulate}\n"
14284     "                              flt         = {nearest|bilinear|trilinear}\n"
14285     "                              ss, st      - scale factors for s and t texture coordinates\n"
14286     "                              ts, tt      - translation for s and t texture coordinates\n"
14287     "                              rot         - texture rotation angle in degrees",
14288     __FILE__, VTextureEnv, group);
14289   theCommands.Add("vhlr",
14290             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
14291       "\n\t\t: Hidden Line Removal algorithm."
14292       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
14293       "\n\t\t:   -algoType   type of HLR algorithm.\n",
14294     __FILE__,VHLR,group);
14295   theCommands.Add("vhlrtype",
14296               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
14297       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
14298       "\n\t\t:   'algo' - exact HLR algorithm is applied"
14299       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
14300       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
14301     __FILE__,VHLRType,group);
14302   theCommands.Add("vclipplane",
14303               "vclipplane planeName [{0|1}]"
14304       "\n\t\t:   [-equation1 A B C D]"
14305       "\n\t\t:   [-equation2 A B C D]"
14306       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
14307       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
14308       "\n\t\t:   [-maxPlanes]"
14309       "\n\t\t:   [-capping {0|1}]"
14310       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
14311       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
14312       "\n\t\t:       [-texRotate Angle]"
14313       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
14314       "\n\t\t:       [-useObjShader {0|1}]"
14315       "\n\t\t: Clipping planes management:"
14316       "\n\t\t:   -maxPlanes   print plane limit for view"
14317       "\n\t\t:   -delete      delete plane with given name"
14318       "\n\t\t:   {off|on|0|1} turn clipping on/off"
14319       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
14320       "\n\t\t:                applied to active View when list is omitted"
14321       "\n\t\t:   -equation A B C D change plane equation"
14322       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
14323       "\n\t\t: Capping options:"
14324       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
14325       "\n\t\t:   -color R G B          set capping color"
14326       "\n\t\t:   -transparency Value   set capping transparency 0..1"
14327       "\n\t\t:   -texName Texture      set capping texture"
14328       "\n\t\t:   -texScale SX SY       set capping tex scale"
14329       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
14330       "\n\t\t:   -texRotate Angle      set capping tex rotation"
14331       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
14332       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
14333       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
14334       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
14335       __FILE__, VClipPlane, group);
14336   theCommands.Add("vdefaults",
14337                "vdefaults [-absDefl value]"
14338        "\n\t\t:           [-devCoeff value]"
14339        "\n\t\t:           [-angDefl value]"
14340        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
14341     , __FILE__, VDefaults, group);
14342   theCommands.Add("vlight",
14343     "tool to manage light sources, without arguments shows list of lights."
14344     "\n    Main commands: "
14345     "\n      '-clear' to clear lights"
14346     "\n      '-{def}aults' to load deafault lights"
14347     "\n      '-add' <type> to add any light source"
14348     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
14349     "\n      'change' <lightId> to edit light source with specified lightId"
14350     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
14351     "\n        -layer Id"
14352     "\n        -{pos}ition X Y Z"
14353     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
14354     "\n        -color colorName"
14355     "\n        -{head}light 0|1"
14356     "\n        -{sm}oothness value"
14357     "\n        -{int}ensity value"
14358     "\n        -{constAtten}uation value"
14359     "\n        -{linearAtten}uation value"
14360     "\n        -angle angleDeg"
14361     "\n        -{spotexp}onent value"
14362     "\n        -local|-global"
14363     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
14364     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
14365     __FILE__, VLight, group);
14366   theCommands.Add("vraytrace",
14367             "vraytrace [0|1]"
14368     "\n\t\t: Turns on/off ray-tracing renderer."
14369     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
14370     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
14371     __FILE__, VRenderParams, group);
14372   theCommands.Add("vrenderparams",
14373     "\n    Manages rendering parameters: "
14374     "\n      '-raster'                   Disables GPU ray-tracing"
14375     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
14376     "\n      '-lineFeather  > 0'         Sets line feather factor"
14377     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
14378     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
14379     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
14380     "\n      '-rendScale    value        Rendering resolution scale factor"
14381     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
14382     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
14383     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
14384     "\n      '-reflections  on|off'      Enables/disables specular reflections"
14385     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
14386     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
14387     "\n      '-gi           on|off'      Enables/disables global illumination effects"
14388     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
14389     "\n      '-env          on|off'      Enables/disables environment map background"
14390     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
14391     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
14392     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
14393     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
14394     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
14395     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
14396     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
14397     "\n      '-shadingModel model'       Controls shading model from enumeration"
14398     "\n                                  color, flat, gouraud, phong"
14399     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
14400     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
14401     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
14402     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
14403     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
14404     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
14405     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
14406     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
14407     "\n                                  Show/hide performance counters (flags can be combined)"
14408     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
14409     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
14410     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
14411     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
14412     "\n                                        set state to check structures culled previously."
14413     "\n    Unlike vcaps, these parameters dramatically change visual properties."
14414     "\n    Command is intended to control presentation quality depending on"
14415     "\n    hardware capabilities and performance.",
14416     __FILE__, VRenderParams, group);
14417   theCommands.Add("vstatprofiler",
14418     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
14419     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
14420     "\n                |triagles|points|geomMem|textureMem|frameMem"
14421     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
14422     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
14423     "\n                [-noredraw]"
14424     "\n\t\t: Prints rendering statistics."
14425     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
14426     "\n\t\t:   else - print all performance counters set previously."
14427     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
14428     __FILE__, VStatProfiler, group);
14429   theCommands.Add ("vplace",
14430             "vplace dx dy"
14431     "\n\t\t: Places the point (in pixels) at the center of the window",
14432     __FILE__, VPlace, group);
14433   theCommands.Add("vxrotate",
14434     "vxrotate",
14435     __FILE__,VXRotate,group);
14436
14437     theCommands.Add("vmanipulator",
14438       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
14439       "\n    tool to create and manage AIS manipulators."
14440       "\n    Options: "
14441       "\n      '-attach AISObject'                 attach manipulator to AISObject"
14442       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
14443       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
14444       "\n      '-enableModes    {0|1}'             enable modes when attaching"
14445       "\n      '-detach'                           detach manipulator"
14446       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
14447       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
14448       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
14449       "\n      '-move x y z'                     - move attached object"
14450       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
14451       "\n      '-scale factor'                   - scale attached object"
14452       "\n      '-autoActivate      {0|1}'        - set activation on detection"
14453       "\n      '-followTranslation {0|1}'        - set following translation transform"
14454       "\n      '-followRotation    {0|1}'        - set following rotation transform"
14455       "\n      '-followDragging    {0|1}'        - set following dragging transform"
14456       "\n      '-gap value'                      - set gap between sub-parts"
14457       "\n      '-part axis mode    {0|1}'        - set visual part"
14458       "\n      '-parts axis mode   {0|1}'        - set visual part"
14459       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
14460       "\n      '-size value'                     - set size of manipulator"
14461       "\n      '-zoomable {0|1}'                 - set zoom persistence",
14462     __FILE__, VManipulator, group);
14463
14464   theCommands.Add("vselprops",
14465     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
14466     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
14467     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
14468     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
14469     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
14470     "\n    -pickStrategy {first|topmost} : defines picking strategy"
14471     "\n                            'first'   to pick first acceptable (default)"
14472     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
14473     "\n    -pixTol    value        : sets up pixel tolerance"
14474     "\n    -dispMode  dispMode     : sets display mode for highlighting"
14475     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
14476     "\n    -color     {name|r g b} : sets highlight color"
14477     "\n    -transp    value        : sets transparency coefficient for highlight"
14478     "\n    -material  material     : sets highlight material"
14479     "\n    -print                  : prints current state of all mentioned parameters",
14480     __FILE__, VSelectionProperties, group);
14481   theCommands.Add ("vhighlightselected",
14482                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
14483                    __FILE__, VSelectionProperties, group);
14484
14485   theCommands.Add ("vseldump",
14486                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
14487                    "\n\t\t: Generate an image based on detection results:"
14488                    "\n\t\t:   depth       normalized depth values"
14489                    "\n\t\t:   unnormDepth unnormalized depth values"
14490                    "\n\t\t:   object      color of detected object"
14491                    "\n\t\t:   owner       color of detected owner"
14492                    "\n\t\t:   selMode     color of selection mode"
14493                    "\n\t\t:   entity      color of etected entity",
14494                    __FILE__, VDumpSelectionImage, group);
14495
14496 #if defined(_WIN32)
14497   theCommands.Add("vprogressive",
14498     "vprogressive",
14499     __FILE__, VProgressiveMode, group);
14500 #endif
14501 }
14502