0030715: Configuration, CMake - error build with QTANGLE
[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 : ViewProject: implements VAxo, VTop, VLeft, ...
3184 //purpose  : Switches to an axonometric, top, left and other views
3185 //==============================================================================
3186
3187 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
3188 {
3189   if ( ViewerTest::CurrentView().IsNull() )
3190   {
3191     di<<"Call vinit before this command, please\n";
3192     return 1;
3193   }
3194
3195   ViewerTest::CurrentView()->SetProj(ori);
3196   return 0;
3197 }
3198
3199 //==============================================================================
3200 //function : VAxo
3201 //purpose  : Switch to an Axonometric view
3202 //Draw arg : No args
3203 //==============================================================================
3204
3205 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
3206 {
3207   return ViewProject(di, V3d_XposYnegZpos);
3208 }
3209
3210 //==============================================================================
3211 //function : VTop
3212 //purpose  : Switch to a Top View
3213 //Draw arg : No args
3214 //==============================================================================
3215
3216 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
3217 {
3218   return ViewProject(di, V3d_Zpos);
3219 }
3220
3221 //==============================================================================
3222 //function : VBottom
3223 //purpose  : Switch to a Bottom View
3224 //Draw arg : No args
3225 //==============================================================================
3226
3227 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
3228 {
3229   return ViewProject(di, V3d_Zneg);
3230 }
3231
3232 //==============================================================================
3233 //function : VLeft
3234 //purpose  : Switch to a Left View
3235 //Draw arg : No args
3236 //==============================================================================
3237
3238 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
3239 {
3240   return ViewProject(di, V3d_Xneg);
3241 }
3242
3243 //==============================================================================
3244 //function : VRight
3245 //purpose  : Switch to a Right View
3246 //Draw arg : No args
3247 //==============================================================================
3248
3249 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
3250 {
3251   return ViewProject(di, V3d_Xpos);
3252 }
3253
3254 //==============================================================================
3255 //function : VFront
3256 //purpose  : Switch to a Front View
3257 //Draw arg : No args
3258 //==============================================================================
3259
3260 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
3261 {
3262   return ViewProject(di, V3d_Yneg);
3263 }
3264
3265 //==============================================================================
3266 //function : VBack
3267 //purpose  : Switch to a Back View
3268 //Draw arg : No args
3269 //==============================================================================
3270
3271 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
3272 {
3273   return ViewProject(di, V3d_Ypos);
3274 }
3275
3276 //==============================================================================
3277 //function : VHelp
3278 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
3279 //Draw arg : No args
3280 //==============================================================================
3281
3282 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3283 {
3284
3285   di << "Q : Quit the application\n";
3286
3287   di << "=========================\n";
3288   di << "F : FitAll\n";
3289   di << "T : TopView\n";
3290   di << "B : BottomView\n";
3291   di << "R : RightView\n";
3292   di << "L : LeftView\n";
3293   di << "A : AxonometricView\n";
3294   di << "D : ResetView\n";
3295
3296   di << "=========================\n";
3297   di << "S : Shading\n";
3298   di << "W : Wireframe\n";
3299   di << "H : HidelLineRemoval\n";
3300   di << "U : Unset display mode\n";
3301   di << "Delete : Remove selection from viewer\n";
3302
3303   di << "=========================\n";
3304   di << "Selection mode \n";
3305   di << "0 : Shape\n";
3306   di << "1 : Vertex\n";
3307   di << "2 : Edge\n";
3308   di << "3 : Wire\n";
3309   di << "4 : Face\n";
3310   di << "5 : Shell\n";
3311   di << "6 : Solid\n";
3312   di << "7 : Compound\n";
3313
3314   di << "=========================\n";
3315   di << "Z : Switch Z clipping On/Off\n";
3316   di << ", : Hilight next detected\n";
3317   di << ". : Hilight previous detected\n";
3318
3319   return 0;
3320 }
3321
3322 #ifdef _WIN32
3323
3324 static Standard_Boolean Ppick = 0;
3325 static Standard_Integer Pargc = 0;
3326 static const char**           Pargv = NULL;
3327
3328
3329 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
3330                                           UINT Msg,
3331                                           WPARAM wParam,
3332                                           LPARAM lParam )
3333 {
3334   if (!ViewerTest_myViews.IsEmpty()) {
3335
3336     WPARAM fwKeys = wParam;
3337
3338     switch( Msg ) {
3339     case WM_CLOSE:
3340        {
3341          // Delete view from map of views
3342          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
3343          return 0;
3344        }
3345        break;
3346     case WM_ACTIVATE:
3347       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
3348         || ViewerTest::CurrentView().IsNull())
3349       {
3350         // Activate inactive window
3351         if(GetWindowHandle(VT_GetWindow()) != hwnd)
3352         {
3353           ActivateView (FindViewIdByWindowHandle(hwnd));
3354         }
3355       }
3356       break;
3357
3358     case WM_LBUTTONUP:
3359       if (IsDragged && !DragFirst)
3360       {
3361         if (!GetActiveAISManipulator().IsNull())
3362         {
3363           GetActiveAISManipulator()->StopTransform();
3364           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
3365         }
3366
3367         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
3368         {
3369           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
3370           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
3371         }
3372
3373         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
3374       }
3375       IsDragged = Standard_False;
3376       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3377
3378     case WM_RBUTTONUP:
3379       if (IsDragged && !DragFirst)
3380       {
3381         if (!GetActiveAISManipulator().IsNull())
3382         {
3383           GetActiveAISManipulator()->StopTransform (Standard_False);
3384           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
3385         }
3386         IsDragged = Standard_False;
3387       }
3388       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
3389
3390     case WM_LBUTTONDOWN:
3391       if (!GetActiveAISManipulator().IsNull())
3392       {
3393         IsDragged = ( fwKeys == MK_LBUTTON );
3394       }
3395       else
3396       {
3397         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
3398       }
3399
3400       if (IsDragged)
3401       {
3402         DragFirst = Standard_True;
3403         X_ButtonPress = LOWORD(lParam);
3404         Y_ButtonPress = HIWORD(lParam);
3405       }
3406       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3407
3408     case WM_MOUSEMOVE:
3409       if (IsDragged)
3410       {
3411         X_Motion = LOWORD (lParam);
3412         Y_Motion = HIWORD (lParam);
3413         if (!GetActiveAISManipulator().IsNull())
3414         {
3415           if (DragFirst)
3416           {
3417             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
3418           }
3419           else
3420           {
3421             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
3422             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
3423           }
3424         }
3425         else
3426         {
3427           bool toRedraw = false;
3428           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
3429           {
3430             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
3431             toRedraw = true;
3432           }
3433
3434           RECT aRect;
3435           if (GetClientRect (hwnd, &aRect))
3436           {
3437             int aHeight = aRect.bottom - aRect.top;
3438             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
3439             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
3440             toRedraw = true;
3441           }
3442           if (toRedraw)
3443           {
3444             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
3445           }
3446         }
3447
3448         DragFirst = Standard_False;
3449       }
3450       else
3451         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3452       break;
3453
3454     default:
3455       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3456     }
3457     return 0;
3458   }
3459   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
3460 }
3461
3462
3463 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
3464                                        UINT Msg,
3465                                        WPARAM wParam,
3466                                        LPARAM lParam )
3467 {
3468   static int Up = 1;
3469   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3470   if (aView.IsNull())
3471   {
3472     return DefWindowProcW (hwnd, Msg, wParam, lParam);
3473   }
3474
3475     PAINTSTRUCT    ps;
3476
3477     switch( Msg ) {
3478     case WM_PAINT:
3479       BeginPaint(hwnd, &ps);
3480       EndPaint(hwnd, &ps);
3481       VT_ProcessExpose();
3482       break;
3483
3484     case WM_SIZE:
3485       VT_ProcessConfigure();
3486       break;
3487     case WM_MOVE:
3488     case WM_MOVING:
3489     case WM_SIZING:
3490       switch (aView->RenderingParams().StereoMode)
3491       {
3492         case Graphic3d_StereoMode_RowInterlaced:
3493         case Graphic3d_StereoMode_ColumnInterlaced:
3494         case Graphic3d_StereoMode_ChessBoard:
3495           VT_ProcessConfigure(); // track window moves to reverse stereo pair
3496           break;
3497         default:
3498           break;
3499       }
3500       break;
3501
3502     case WM_KEYDOWN:
3503       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
3504       {
3505         char c[2];
3506         c[0] = (char) wParam;
3507         c[1] = '\0';
3508         if (wParam == VK_DELETE)
3509         {
3510           c[0] = THE_KEY_DELETE;
3511         }
3512         else if (wParam == VK_ESCAPE)
3513         {
3514           c[0] = THE_KEY_ESCAPE;
3515         }
3516         // comma
3517         else if (wParam == VK_OEM_COMMA)
3518         {
3519           c[0] = ',';
3520         }
3521         // dot
3522         else if (wParam == VK_OEM_PERIOD)
3523         {
3524           c[0] = '.';
3525         }
3526         else if (wParam == VK_DIVIDE)
3527         {
3528           c[0] = '/';
3529         }
3530         // dot
3531         else if (wParam == VK_MULTIPLY)
3532         {
3533           c[0] = '*';
3534         }
3535         VT_ProcessKeyPress (c);
3536       }
3537       break;
3538
3539     case WM_LBUTTONUP:
3540     case WM_MBUTTONUP:
3541     case WM_RBUTTONUP:
3542       Up = 1;
3543       VT_ProcessButton3Release();
3544       break;
3545
3546     case WM_LBUTTONDOWN:
3547     case WM_MBUTTONDOWN:
3548     case WM_RBUTTONDOWN:
3549       {
3550         WPARAM fwKeys = wParam;
3551
3552         Up = 0;
3553
3554         X_ButtonPress = LOWORD(lParam);
3555         Y_ButtonPress = HIWORD(lParam);
3556
3557         if (Msg == WM_LBUTTONDOWN)
3558         {
3559           if ((fwKeys & MK_CONTROL) != 0)
3560           {
3561             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
3562           }
3563           else
3564           {
3565             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
3566           }
3567         }
3568         else if (Msg == WM_RBUTTONDOWN)
3569         {
3570           // Start rotation
3571           VT_ProcessButton3Press();
3572         }
3573       }
3574       break;
3575
3576     case WM_MOUSEWHEEL:
3577     {
3578       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3579       if (wParam & MK_CONTROL)
3580       {
3581         if (aView->Camera()->IsStereo())
3582         {
3583           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
3584           if (aFocus > 0.2
3585            && aFocus < 2.0)
3586           {
3587             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
3588             aView->Redraw();
3589           }
3590         }
3591       }
3592       else
3593       {
3594         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
3595       }
3596       break;
3597     }
3598
3599     case WM_MOUSEMOVE:
3600       {
3601         //cout << "\t WM_MOUSEMOVE" << endl;
3602         WPARAM fwKeys = wParam;
3603         X_Motion = LOWORD(lParam);
3604         Y_Motion = HIWORD(lParam);
3605
3606         if ( Up &&
3607           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
3608           {
3609             Up = 0;
3610             X_ButtonPress = LOWORD(lParam);
3611             Y_ButtonPress = HIWORD(lParam);
3612
3613             if ((fwKeys & MK_RBUTTON) != 0) {
3614               // Start rotation
3615               VT_ProcessButton3Press();
3616             }
3617           }
3618
3619           if ((fwKeys & MK_CONTROL) != 0)
3620           {
3621             if ((fwKeys & MK_LBUTTON) != 0)
3622             {
3623               ProcessControlButton1Motion();
3624             }
3625             else if ((fwKeys & MK_MBUTTON) != 0
3626                  || ((fwKeys & MK_LBUTTON) != 0
3627                   && (fwKeys & MK_RBUTTON) != 0))
3628             {
3629               VT_ProcessControlButton2Motion();
3630             }
3631             else if ((fwKeys & MK_RBUTTON) != 0)
3632             {
3633               VT_ProcessControlButton3Motion();
3634             }
3635           }
3636           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
3637           {
3638             VT_ProcessMotion();
3639           }
3640       }
3641       break;
3642
3643     default:
3644       return DefWindowProcW (hwnd, Msg, wParam, lParam);
3645     }
3646     return 0L;
3647 }
3648
3649 //==============================================================================
3650 //function : ViewerMainLoop
3651 //purpose  : Get a Event on the view and dispatch it
3652 //==============================================================================
3653
3654
3655 int ViewerMainLoop(Standard_Integer argc, const char** argv)
3656 {
3657   Ppick = (argc > 0)? 1 : 0;
3658   Pargc = argc;
3659   Pargv = argv;
3660
3661   if ( Ppick ) {
3662     MSG msg;
3663     msg.wParam = 1;
3664
3665     cout << "Start picking" << endl;
3666
3667     while ( Ppick == 1 ) {
3668       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
3669       if (GetMessageW (&msg, NULL, 0, 0))
3670       {
3671         TranslateMessage (&msg);
3672         DispatchMessageW (&msg);
3673       }
3674     }
3675
3676     cout << "Picking done" << endl;
3677   }
3678
3679   return Ppick;
3680 }
3681
3682 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
3683
3684 int min( int a, int b )
3685 {
3686   if( a<b )
3687     return a;
3688   else
3689     return b;
3690 }
3691
3692 int max( int a, int b )
3693 {
3694   if( a>b )
3695     return a;
3696   else
3697     return b;
3698 }
3699
3700 int ViewerMainLoop (Standard_Integer argc, const char** argv)
3701 {
3702   static XEvent aReport;
3703   const Standard_Boolean toPick = argc > 0;
3704   Standard_Boolean toPickMore = toPick;
3705   Display* aDisplay = GetDisplayConnection()->GetDisplay();
3706   XNextEvent (aDisplay, &aReport);
3707
3708   // Handle event for the chosen display connection
3709   switch (aReport.type)
3710   {
3711     case ClientMessage:
3712     {
3713       if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
3714       {
3715         // Close the window
3716         ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
3717         return toPick ? 0 : 1;
3718       }
3719       break;
3720     }
3721     case FocusIn:
3722     {
3723       // Activate inactive view
3724       Window aWindow = GetWindowHandle(VT_GetWindow());
3725       if (aWindow != aReport.xfocus.window)
3726       {
3727         ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
3728       }
3729       break;
3730     }
3731     case Expose:
3732     {
3733       Window anXWindow = GetWindowHandle (VT_GetWindow());
3734       if (anXWindow == aReport.xexpose.window)
3735       {
3736         VT_ProcessExpose();
3737       }
3738
3739       // remove all the ExposureMask and process them at once
3740       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3741       {
3742         if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
3743         {
3744           break;
3745         }
3746       }
3747
3748       break;
3749     }
3750     case ConfigureNotify:
3751     {
3752       // remove all the StructureNotifyMask and process them at once
3753       Window anXWindow = GetWindowHandle (VT_GetWindow());
3754       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3755       {
3756         if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
3757         {
3758           break;
3759         }
3760       }
3761
3762       if (anXWindow == aReport.xconfigure.window)
3763       {
3764         VT_ProcessConfigure();
3765       }
3766       break;
3767     }
3768     case KeyPress:
3769     {
3770       KeySym aKeySym;
3771       char aKeyBuf[11];
3772       XComposeStatus status_in_out;
3773       int aKeyLen = XLookupString ((XKeyEvent* )&aReport, (char* )aKeyBuf, 10, &aKeySym, &status_in_out);
3774       aKeyBuf[aKeyLen] = '\0';
3775       if (aKeyLen != 0)
3776       {
3777         VT_ProcessKeyPress (aKeyBuf);
3778       }
3779       break;
3780     }
3781     case ButtonPress:
3782     {
3783       X_ButtonPress = aReport.xbutton.x;
3784       Y_ButtonPress = aReport.xbutton.y;
3785       if (aReport.xbutton.button == Button1)
3786       {
3787         if (aReport.xbutton.state & ControlMask)
3788         {
3789           toPickMore = VT_ProcessButton1Press (argc, argv, toPick, (aReport.xbutton.state & ShiftMask) != 0);
3790         }
3791         else
3792         {
3793           IsDragged = Standard_True;
3794           DragFirst = Standard_True;
3795         }
3796       }
3797       else if (aReport.xbutton.button == Button3)
3798       {
3799         // Start rotation
3800         VT_ProcessButton3Press();
3801       }
3802       break;
3803     }
3804     case ButtonRelease:
3805     {
3806       if (!IsDragged)
3807       {
3808         VT_ProcessButton3Release();
3809         break;
3810       }
3811
3812       Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3813       if (aContext.IsNull())
3814       {
3815         std::cout << "Error: No active view.\n";
3816         return 0;
3817       }
3818
3819       if (!DragFirst
3820         && aContext->IsDisplayed (GetRubberBand()))
3821       {
3822         aContext->Remove (GetRubberBand(), Standard_False);
3823         aContext->CurrentViewer()->RedrawImmediate();
3824       }
3825
3826       if (aReport.xbutton.button != Button1)
3827       {
3828         break;
3829       }
3830
3831       const Standard_Boolean isShiftPressed = (aReport.xbutton.state & ShiftMask) != 0;
3832       if (DragFirst)
3833       {
3834         if (isShiftPressed)
3835         {
3836           aContext->ShiftSelect (Standard_True);
3837         }
3838         else
3839         {
3840           aContext->Select (Standard_True);
3841         }
3842       }
3843       else
3844       {
3845         if (isShiftPressed)
3846         {
3847           aContext->ShiftSelect (Min (X_ButtonPress, X_Motion), Min (Y_ButtonPress, Y_Motion),
3848                                  Max (X_ButtonPress, X_Motion), Max (Y_ButtonPress, Y_Motion),
3849                                  ViewerTest::CurrentView(), Standard_True);
3850         }
3851         else
3852         {
3853           aContext->Select (Min (X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
3854                             Max (X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
3855                             ViewerTest::CurrentView(), Standard_True);
3856         }
3857       }
3858       IsDragged = Standard_False;
3859       break;
3860     }
3861     case MotionNotify:
3862     {
3863       Window anXWindow = GetWindowHandle (VT_GetWindow());
3864       if (anXWindow != aReport.xmotion.window)
3865       {
3866         break;
3867       }
3868
3869       // remove all the ButtonMotionMask and process them at once
3870       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3871       {
3872         if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
3873         {
3874           break;
3875         }
3876       }
3877
3878       if (IsDragged)
3879       {
3880         if (!DragFirst
3881           && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
3882         {
3883           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
3884         }
3885
3886         X_Motion = aReport.xmotion.x;
3887         Y_Motion = aReport.xmotion.y;
3888         DragFirst = Standard_False;
3889
3890         Window aWindow = GetWindowHandle(VT_GetWindow());
3891         Window aRoot;
3892         int anX, anY;
3893         unsigned int aWidth, aHeight, aBorderWidth, aDepth;
3894         XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
3895         GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
3896         ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, AIS_DS_Displayed);
3897         ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
3898       }
3899       else
3900       {
3901         X_Motion = aReport.xmotion.x;
3902         Y_Motion = aReport.xmotion.y;
3903         if ((aReport.xmotion.state & ControlMask) != 0)
3904         {
3905           if ((aReport.xmotion.state & Button1Mask) != 0)
3906           {
3907             ProcessControlButton1Motion();
3908           }
3909           else if ((aReport.xmotion.state & Button2Mask) != 0)
3910           {
3911             VT_ProcessControlButton2Motion();
3912           }
3913           else if ((aReport.xmotion.state & Button3Mask) != 0)
3914           {
3915             VT_ProcessControlButton3Motion();
3916           }
3917         }
3918         else
3919         {
3920           VT_ProcessMotion();
3921         }
3922       }
3923       break;
3924     }
3925   }
3926   return (!toPick || toPickMore) ? 1 : 0;
3927 }
3928
3929 //==============================================================================
3930 //function : VProcessEvents
3931 //purpose  : manage the event in the Viewer window (see Tcl_CreateFileHandler())
3932 //==============================================================================
3933 static void VProcessEvents (ClientData theDispX, int)
3934 {
3935   Display* aDispX = (Display* )theDispX;
3936   Handle(Aspect_DisplayConnection) aDispConn;
3937   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
3938        aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
3939   {
3940     const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
3941     if (aDispConnTmp->GetDisplay() == aDispX)
3942     {
3943       aDispConn = aDispConnTmp;
3944       break;
3945     }
3946   }
3947   if (aDispConn.IsNull())
3948   {
3949     std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
3950     return;
3951   }
3952
3953   // process new events in queue
3954   SetDisplayConnection (aDispConn);
3955   int aNbRemain = 0;
3956   for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
3957   {
3958     const int anEventResult = ViewerMainLoop (0, NULL);
3959     if (anEventResult == 0)
3960     {
3961       return;
3962     }
3963
3964     aNbRemain = XPending (aDispX);
3965     if (++anEventIter >= aNbEventsMax
3966      || aNbRemain <= 0)
3967     {
3968       break;
3969     }
3970   }
3971
3972   // Listening X events through Tcl_CreateFileHandler() callback is fragile,
3973   // it is possible that new events will arrive to queue before the end of this callback
3974   // so that either this callback should go into an infinite loop (blocking processing of other events)
3975   // or to keep unprocessed events till the next queue update (which can arrive not soon).
3976   // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
3977   if (aNbRemain != 0)
3978   {
3979     XEvent aDummyEvent;
3980     memset (&aDummyEvent, 0, sizeof(aDummyEvent));
3981     aDummyEvent.type = ClientMessage;
3982     aDummyEvent.xclient.format = 32;
3983     XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
3984     XFlush (aDispX);
3985   }
3986
3987   if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
3988   {
3989     SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
3990   }
3991 }
3992 #endif
3993
3994 //==============================================================================
3995 //function : OSWindowSetup
3996 //purpose  : Setup for the X11 window to be able to cath the event
3997 //==============================================================================
3998
3999
4000 static void OSWindowSetup()
4001 {
4002 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
4003   // X11
4004
4005   Window  window   = VT_GetWindow()->XWindow();
4006   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
4007   Display *aDisplay = GetDisplayConnection()->GetDisplay();
4008   XSynchronize(aDisplay, 1);
4009
4010   // X11 : For keyboard on SUN
4011   XWMHints wmhints;
4012   wmhints.flags = InputHint;
4013   wmhints.input = 1;
4014
4015   XSetWMHints( aDisplay, window, &wmhints);
4016
4017   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
4018     ButtonPressMask | ButtonReleaseMask |
4019     StructureNotifyMask |
4020     PointerMotionMask |
4021     Button1MotionMask | Button2MotionMask |
4022     Button3MotionMask | FocusChangeMask
4023     );
4024   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
4025   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
4026
4027   XSynchronize(aDisplay, 0);
4028
4029 #else
4030   // _WIN32
4031 #endif
4032
4033 }
4034
4035 //==============================================================================
4036 //function : VFit
4037 //purpose  :
4038 //==============================================================================
4039
4040 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
4041 {
4042   const Handle(V3d_View) aView = ViewerTest::CurrentView();
4043   if (aView.IsNull())
4044   {
4045     std::cout << "Error: no active viewer!\n";
4046     return 1;
4047   }
4048
4049   Standard_Boolean toFit = Standard_True;
4050   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
4051   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4052   {
4053     TCollection_AsciiString anArg (theArgv[anArgIter]);
4054     anArg.LowerCase();
4055     if (anUpdateTool.parseRedrawMode (anArg))
4056     {
4057       continue;
4058     }
4059     else if (anArg == "-selected")
4060     {
4061       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
4062       toFit = Standard_False;
4063     }
4064     else
4065     {
4066       std::cout << "Syntax error at '" << anArg << "'\n";
4067     }
4068   }
4069
4070   if (toFit)
4071   {
4072     aView->FitAll (0.01, Standard_False);
4073   }
4074   return 0;
4075 }
4076
4077 //=======================================================================
4078 //function : VFitArea
4079 //purpose  : Fit view to show area located between two points
4080 //         : given in world 2D or 3D coordinates.
4081 //=======================================================================
4082 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
4083 {
4084   Handle(V3d_View) aView = ViewerTest::CurrentView();
4085   if (aView.IsNull())
4086   {
4087     std::cerr << theArgVec[0] << "Error: No active view.\n";
4088     return 1;
4089   }
4090
4091   // Parse arguments.
4092   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
4093   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
4094
4095   if (theArgNb == 5)
4096   {
4097     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
4098     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
4099     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
4100     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
4101   }
4102   else if (theArgNb == 7)
4103   {
4104     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
4105     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
4106     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
4107     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
4108     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
4109     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
4110   }
4111   else
4112   {
4113     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
4114     theDI.PrintHelp(theArgVec[0]);
4115     return 1;
4116   }
4117
4118   // Convert model coordinates to view space
4119   Handle(Graphic3d_Camera) aCamera = aView->Camera();
4120   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
4121   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
4122
4123   // Determine fit area
4124   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
4125   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
4126
4127   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
4128
4129   if (aDiagonal < Precision::Confusion())
4130   {
4131     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
4132     return 1;
4133   }
4134
4135   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
4136   return 0;
4137 }
4138
4139 //==============================================================================
4140 //function : VZFit
4141 //purpose  : ZFitall, no DRAW arguments
4142 //Draw arg : No args
4143 //==============================================================================
4144 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
4145 {
4146   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
4147
4148   if (aCurrentView.IsNull())
4149   {
4150     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
4151     return 1;
4152   }
4153
4154   if (theArgsNb == 1)
4155   {
4156     aCurrentView->ZFitAll();
4157     aCurrentView->Redraw();
4158     return 0;
4159   }
4160
4161   Standard_Real aScale = 1.0;
4162
4163   if (theArgsNb >= 2)
4164   {
4165     aScale = Draw::Atoi (theArgVec[1]);
4166   }
4167
4168   aCurrentView->ZFitAll (aScale);
4169   aCurrentView->Redraw();
4170
4171   return 0;
4172 }
4173
4174 //==============================================================================
4175 //function : VRepaint
4176 //purpose  :
4177 //==============================================================================
4178 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
4179 {
4180   Handle(V3d_View) aView = ViewerTest::CurrentView();
4181   if (aView.IsNull())
4182   {
4183     std::cout << "Error: no active viewer!\n";
4184     return 1;
4185   }
4186
4187   Standard_Boolean isImmediateUpdate = Standard_False;
4188   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4189   {
4190     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4191     anArg.LowerCase();
4192     if (anArg == "-immediate"
4193      || anArg == "-imm")
4194     {
4195       isImmediateUpdate = Standard_True;
4196       if (anArgIter + 1 < theArgNb
4197        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
4198       {
4199         ++anArgIter;
4200       }
4201     }
4202     else if (anArg == "-continuous"
4203           || anArg == "-cont"
4204           || anArg == "-fps"
4205           || anArg == "-framerate")
4206     {
4207       Standard_Real aFps = -1.0;
4208       if (anArgIter + 1 < theArgNb
4209        && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
4210       {
4211         aFps = Draw::Atof (theArgVec[++anArgIter]);
4212       }
4213
4214       ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
4215       if (Abs (aFps) >= 1.0)
4216       {
4217         aRedrawer.Start (aView->Window(), aFps);
4218       }
4219       else
4220       {
4221         aRedrawer.Stop();
4222       }
4223     }
4224     else
4225     {
4226       std::cout << "Syntax error at '" << anArg << "'\n";
4227       return 1;
4228     }
4229   }
4230
4231   if (isImmediateUpdate)
4232   {
4233     aView->RedrawImmediate();
4234   }
4235   else
4236   {
4237     aView->Redraw();
4238   }
4239   return 0;
4240 }
4241
4242 //==============================================================================
4243 //function : VClear
4244 //purpose  : Remove all the object from the viewer
4245 //Draw arg : No args
4246 //==============================================================================
4247
4248 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
4249 {
4250   Handle(V3d_View) V = ViewerTest::CurrentView();
4251   if(!V.IsNull())
4252     ViewerTest::Clear();
4253   return 0;
4254 }
4255
4256 //==============================================================================
4257 //function : VPick
4258 //purpose  :
4259 //==============================================================================
4260
4261 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4262 { if (ViewerTest::CurrentView().IsNull() ) return 1;
4263
4264 if ( argc < 4 ) {
4265   di << argv[0] << "Invalid number of arguments\n";
4266   return 1;
4267 }
4268
4269 while (ViewerMainLoop( argc, argv)) {
4270 }
4271
4272 return 0;
4273 }
4274
4275 namespace
4276 {
4277
4278   //! Changes the background
4279   //! @param theDrawInterpretor the interpreter of the Draw Harness application
4280   //! @param theNumberOfCommandLineArguments the number of passed command line arguments
4281   //! @param theCommandLineArguments the array of command line arguments
4282   //! @return TCL_OK if changing was successful, or TCL_ERROR otherwise
4283   static int vbackground (Draw_Interpretor&      theDrawInterpretor,
4284                           const Standard_Integer theNumberOfCommandLineArguments,
4285                           const char** const     theCommandLineArguments)
4286   {
4287     if (theNumberOfCommandLineArguments < 1)
4288     {
4289       return TCL_ERROR;
4290     }
4291     BackgroundChanger aBackgroundChanger;
4292     if (!aBackgroundChanger.ProcessCommandLine (theDrawInterpretor,
4293                                                 theNumberOfCommandLineArguments,
4294                                                 theCommandLineArguments))
4295     {
4296       theDrawInterpretor << "Wrong command arguments.\n"
4297                             "Type 'help "
4298                          << theCommandLineArguments[0] << "' for information about command options and its arguments.\n";
4299       return TCL_ERROR;
4300     }
4301     return TCL_OK;
4302   }
4303
4304 } // namespace
4305
4306 //==============================================================================
4307 //function : VScale
4308 //purpose  : View Scaling
4309 //==============================================================================
4310
4311 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4312 {
4313   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4314   if ( V3dView.IsNull() ) return 1;
4315
4316   if ( argc != 4 ) {
4317     di << argv[0] << "Invalid number of arguments\n";
4318     return 1;
4319   }
4320   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
4321   return 0;
4322 }
4323 //==============================================================================
4324 //function : VZBuffTrihedron
4325 //purpose  :
4326 //==============================================================================
4327
4328 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
4329                             Standard_Integer  theArgNb,
4330                             const char**      theArgVec)
4331 {
4332   Handle(V3d_View) aView = ViewerTest::CurrentView();
4333   if (aView.IsNull())
4334   {
4335     std::cout << "Error: no active viewer!\n";
4336     return 1;
4337   }
4338
4339   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4340
4341   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
4342   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
4343   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
4344   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
4345   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
4346   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
4347   Standard_Real                 aScale        = 0.1;
4348   Standard_Real                 aSizeRatio    = 0.8;
4349   Standard_Real                 anArrowDiam   = 0.05;
4350   Standard_Integer              aNbFacets     = 12;
4351   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4352   {
4353     Standard_CString        anArg = theArgVec[anArgIter];
4354     TCollection_AsciiString aFlag (anArg);
4355     aFlag.LowerCase();
4356     if (anUpdateTool.parseRedrawMode (aFlag))
4357     {
4358       continue;
4359     }
4360     else if (aFlag == "-on")
4361     {
4362       continue;
4363     }
4364     else if (aFlag == "-off")
4365     {
4366       aView->TriedronErase();
4367       return 0;
4368     }
4369     else if (aFlag == "-pos"
4370           || aFlag == "-position"
4371           || aFlag == "-corner")
4372     {
4373       if (++anArgIter >= theArgNb)
4374       {
4375         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4376         return 1;
4377       }
4378
4379       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
4380       aPosName.LowerCase();
4381       if (aPosName == "center")
4382       {
4383         aPosition = Aspect_TOTP_CENTER;
4384       }
4385       else if (aPosName == "left_lower"
4386             || aPosName == "lower_left"
4387             || aPosName == "leftlower"
4388             || aPosName == "lowerleft")
4389       {
4390         aPosition = Aspect_TOTP_LEFT_LOWER;
4391       }
4392       else if (aPosName == "left_upper"
4393             || aPosName == "upper_left"
4394             || aPosName == "leftupper"
4395             || aPosName == "upperleft")
4396       {
4397         aPosition = Aspect_TOTP_LEFT_UPPER;
4398       }
4399       else if (aPosName == "right_lower"
4400             || aPosName == "lower_right"
4401             || aPosName == "rightlower"
4402             || aPosName == "lowerright")
4403       {
4404         aPosition = Aspect_TOTP_RIGHT_LOWER;
4405       }
4406       else if (aPosName == "right_upper"
4407             || aPosName == "upper_right"
4408             || aPosName == "rightupper"
4409             || aPosName == "upperright")
4410       {
4411         aPosition = Aspect_TOTP_RIGHT_UPPER;
4412       }
4413       else
4414       {
4415         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
4416         return 1;
4417       }
4418     }
4419     else if (aFlag == "-type")
4420     {
4421       if (++anArgIter >= theArgNb)
4422       {
4423         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4424         return 1;
4425       }
4426
4427       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
4428       aTypeName.LowerCase();
4429       if (aTypeName == "wireframe"
4430        || aTypeName == "wire")
4431       {
4432         aVisType = V3d_WIREFRAME;
4433       }
4434       else if (aTypeName == "zbuffer"
4435             || aTypeName == "shaded")
4436       {
4437         aVisType = V3d_ZBUFFER;
4438       }
4439       else
4440       {
4441         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
4442       }
4443     }
4444     else if (aFlag == "-scale")
4445     {
4446       if (++anArgIter >= theArgNb)
4447       {
4448         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4449         return 1;
4450       }
4451
4452       aScale = Draw::Atof (theArgVec[anArgIter]);
4453     }
4454     else if (aFlag == "-size"
4455           || aFlag == "-sizeratio")
4456     {
4457       if (++anArgIter >= theArgNb)
4458       {
4459         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4460         return 1;
4461       }
4462
4463       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
4464     }
4465     else if (aFlag == "-arrowdiam"
4466           || aFlag == "-arrowdiameter")
4467     {
4468       if (++anArgIter >= theArgNb)
4469       {
4470         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4471         return 1;
4472       }
4473
4474       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
4475     }
4476     else if (aFlag == "-nbfacets")
4477     {
4478       if (++anArgIter >= theArgNb)
4479       {
4480         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4481         return 1;
4482       }
4483
4484       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
4485     }
4486     else if (aFlag == "-colorlabel"
4487           || aFlag == "-colorlabels")
4488     {
4489       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4490                                                            theArgVec + anArgIter + 1,
4491                                                            aLabelsColor);
4492       if (aNbParsed == 0)
4493       {
4494         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4495         return 1;
4496       }
4497       anArgIter += aNbParsed;
4498     }
4499     else if (aFlag == "-colorarrowx")
4500     {
4501       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4502                                                            theArgVec + anArgIter + 1,
4503                                                            anArrowColorX);
4504       if (aNbParsed == 0)
4505       {
4506         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4507         return 1;
4508       }
4509       anArgIter += aNbParsed;
4510     }
4511     else if (aFlag == "-colorarrowy")
4512     {
4513       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4514                                                            theArgVec + anArgIter + 1,
4515                                                            anArrowColorY);
4516       if (aNbParsed == 0)
4517       {
4518         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4519         return 1;
4520       }
4521       anArgIter += aNbParsed;
4522     }
4523     else if (aFlag == "-colorarrowz")
4524     {
4525       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4526                                                            theArgVec + anArgIter + 1,
4527                                                            anArrowColorZ);
4528       if (aNbParsed == 0)
4529       {
4530         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4531         return 1;
4532       }
4533       anArgIter += aNbParsed;
4534     }
4535     else
4536     {
4537       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4538       return 1;
4539     }
4540   }
4541
4542   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
4543                                aSizeRatio, anArrowDiam, aNbFacets);
4544   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
4545   aView->ZFitAll();
4546   return 0;
4547 }
4548
4549 //==============================================================================
4550 //function : VRotate
4551 //purpose  : Camera Rotating
4552 //==============================================================================
4553
4554 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
4555 {
4556   Handle(V3d_View) aView = ViewerTest::CurrentView();
4557   if (aView.IsNull())
4558   {
4559     std::cout << "No active view!\n";
4560     return 1;
4561   }
4562
4563   Standard_Boolean hasFlags = Standard_False;
4564   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4565   {
4566     Standard_CString        anArg (theArgVec[anArgIter]);
4567     TCollection_AsciiString aFlag (anArg);
4568     aFlag.LowerCase();
4569     if (aFlag == "-mousestart"
4570      || aFlag == "-mousefrom")
4571     {
4572       hasFlags = Standard_True;
4573       if (anArgIter + 2 >= theArgNb)
4574       {
4575         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4576         return 1;
4577       }
4578
4579       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4580       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4581       aView->StartRotation (anX, anY);
4582     }
4583     else if (aFlag == "-mousemove")
4584     {
4585       hasFlags = Standard_True;
4586       if (anArgIter + 2 >= theArgNb)
4587       {
4588         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4589         return 1;
4590       }
4591
4592       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4593       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4594       aView->Rotation (anX, anY);
4595     }
4596     else if (theArgNb != 4
4597           && theArgNb != 7)
4598     {
4599       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4600       return 1;
4601     }
4602   }
4603
4604   if (hasFlags)
4605   {
4606     return 0;
4607   }
4608   else if (theArgNb == 4)
4609   {
4610     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4611     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4612     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4613     aView->Rotate (anAX, anAY, anAZ);
4614     return 0;
4615   }
4616   else if (theArgNb == 7)
4617   {
4618     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4619     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4620     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4621
4622     Standard_Real anX = Draw::Atof (theArgVec[4]);
4623     Standard_Real anY = Draw::Atof (theArgVec[5]);
4624     Standard_Real anZ = Draw::Atof (theArgVec[6]);
4625
4626     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
4627     return 0;
4628   }
4629
4630   std::cout << "Error: Invalid number of arguments\n";
4631   return 1;
4632 }
4633
4634 //==============================================================================
4635 //function : VZoom
4636 //purpose  : View zoom in / out (relative to current zoom)
4637 //==============================================================================
4638
4639 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4640   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4641   if ( V3dView.IsNull() ) {
4642     return 1;
4643   }
4644
4645   if ( argc == 2 ) {
4646     Standard_Real coef = Draw::Atof(argv[1]);
4647     if ( coef <= 0.0 ) {
4648       di << argv[1] << "Invalid value\n";
4649       return 1;
4650     }
4651     V3dView->SetZoom( Draw::Atof(argv[1]) );
4652     return 0;
4653   } else {
4654     di << argv[0] << " Invalid number of arguments\n";
4655     return 1;
4656   }
4657 }
4658
4659 //==============================================================================
4660 //function : VPan
4661 //purpose  : View panning (in pixels)
4662 //==============================================================================
4663
4664 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4665   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4666   if ( V3dView.IsNull() ) return 1;
4667
4668   if ( argc == 3 ) {
4669     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
4670     return 0;
4671   } else {
4672     di << argv[0] << " Invalid number of arguments\n";
4673     return 1;
4674   }
4675 }
4676
4677 //==============================================================================
4678 //function : VPlace
4679 //purpose  : Place the point (in pixels) at the center of the window
4680 //==============================================================================
4681 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
4682 {
4683   Handle(V3d_View) aView = ViewerTest::CurrentView();
4684   if (aView.IsNull())
4685   {
4686     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
4687     return 1;
4688   }
4689
4690   if (theArgNb != 3)
4691   {
4692     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
4693     return 1;
4694   }
4695
4696   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
4697
4698   return 0;
4699 }
4700
4701 static int VColorScale (Draw_Interpretor& theDI,
4702                         Standard_Integer  theArgNb,
4703                         const char**      theArgVec)
4704 {
4705   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4706   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
4707   if (aContext.IsNull())
4708   {
4709     std::cout << "Error: no active view!\n";
4710     return 1;
4711   }
4712   if (theArgNb <= 1)
4713   {
4714     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
4715     return 1;
4716   }
4717
4718   Handle(AIS_ColorScale) aColorScale;
4719   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
4720   {
4721     // find existing object
4722     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
4723     if (aColorScale.IsNull())
4724     {
4725       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
4726       return 1;
4727     }
4728   }
4729
4730   if (theArgNb <= 2)
4731   {
4732     if (aColorScale.IsNull())
4733     {
4734       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
4735       return 1;
4736     }
4737
4738     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
4739           << "Min range: "            << aColorScale->GetMin() << "\n"
4740           << "Max range: "            << aColorScale->GetMax() << "\n"
4741           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
4742           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
4743           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
4744           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
4745           << "Label position: ";
4746     switch (aColorScale->GetLabelPosition())
4747     {
4748       case Aspect_TOCSP_NONE:
4749         theDI << "None\n";
4750         break;
4751       case Aspect_TOCSP_LEFT:
4752         theDI << "Left\n";
4753         break;
4754       case Aspect_TOCSP_RIGHT:
4755         theDI << "Right\n";
4756         break;
4757       case Aspect_TOCSP_CENTER:
4758         theDI << "Center\n";
4759         break;
4760     }
4761     return 0;
4762   }
4763
4764   if (aColorScale.IsNull())
4765   {
4766     aColorScale = new AIS_ColorScale();
4767     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4768     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4769   }
4770
4771   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
4772   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
4773   {
4774     Standard_CString        anArg = theArgVec[anArgIter];
4775     TCollection_AsciiString aFlag (anArg);
4776     aFlag.LowerCase();
4777     if (anUpdateTool.parseRedrawMode (aFlag))
4778     {
4779       continue;
4780     }
4781     else if (aFlag == "-range")
4782     {
4783       if (anArgIter + 3 >= theArgNb)
4784       {
4785         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4786         return 1;
4787       }
4788
4789       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
4790       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
4791       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
4792       if (!aRangeMin.IsRealValue()
4793        || !aRangeMax.IsRealValue())
4794       {
4795         std::cout << "Error: the range values should be real!\n";
4796         return 1;
4797       }
4798       else if (!aNbIntervals.IsIntegerValue())
4799       {
4800         std::cout << "Error: the number of intervals should be integer!\n";
4801         return 1;
4802       }
4803
4804       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
4805       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
4806     }
4807     else if (aFlag == "-font")
4808     {
4809       if (anArgIter + 1 >= theArgNb)
4810       {
4811         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4812         return 1;
4813       }
4814       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
4815       if (!aFontArg.IsIntegerValue())
4816       {
4817         std::cout << "Error: HeightFont value should be integer!\n";
4818         return 1;
4819       }
4820
4821       aColorScale->SetTextHeight (aFontArg.IntegerValue());
4822       anArgIter += 1;
4823     }
4824     else if (aFlag == "-textpos")
4825     {
4826       if (anArgIter + 1 >= theArgNb)
4827       {
4828         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4829         return 1;
4830       }
4831
4832       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
4833       aTextPosArg.LowerCase();
4834       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
4835       if (aTextPosArg == "none")
4836       {
4837         aLabPosition = Aspect_TOCSP_NONE;
4838       }
4839       else if (aTextPosArg == "left")
4840       {
4841         aLabPosition = Aspect_TOCSP_LEFT;
4842       }
4843       else if (aTextPosArg == "right")
4844       {
4845         aLabPosition = Aspect_TOCSP_RIGHT;
4846       }
4847       else if (aTextPosArg == "center")
4848       {
4849         aLabPosition = Aspect_TOCSP_CENTER;
4850       }
4851       else
4852       {
4853         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
4854         return 1;
4855       }
4856       aColorScale->SetLabelPosition (aLabPosition);
4857     }
4858     else if (aFlag == "-logarithmic"
4859           || aFlag == "-log")
4860     {
4861       if (anArgIter + 1 >= theArgNb)
4862       {
4863         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4864         return 1;
4865       }
4866
4867       Standard_Boolean IsLog;
4868       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
4869       {
4870         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4871         return 1;
4872       }
4873       aColorScale->SetLogarithmic (IsLog);
4874     }
4875     else if (aFlag == "-huerange"
4876           || aFlag == "-hue")
4877     {
4878       if (anArgIter + 2 >= theArgNb)
4879       {
4880         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4881         return 1;
4882       }
4883
4884       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
4885       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
4886       aColorScale->SetHueRange (aHueMin, aHueMax);
4887     }
4888     else if (aFlag == "-colorrange")
4889     {
4890       Quantity_Color aColorMin, aColorMax;
4891       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4892                                                             theArgVec + (anArgIter + 1),
4893                                                             aColorMin);
4894       anArgIter += aNbParsed1;
4895       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4896                                                             theArgVec + (anArgIter + 1),
4897                                                             aColorMax);
4898       anArgIter += aNbParsed2;
4899       if (aNbParsed1 == 0
4900        || aNbParsed2 == 0)
4901       {
4902         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4903         return 1;
4904       }
4905
4906       aColorScale->SetColorRange (aColorMin, aColorMax);
4907     }
4908     else if (aFlag == "-reversed"
4909           || aFlag == "-inverted"
4910           || aFlag == "-topdown"
4911           || aFlag == "-bottomup")
4912     {
4913       Standard_Boolean toEnable = Standard_True;
4914       if (anArgIter + 1 < theArgNb
4915        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
4916       {
4917         ++anArgIter;
4918       }
4919       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
4920     }
4921     else if (aFlag == "-smooth"
4922           || aFlag == "-smoothtransition")
4923     {
4924       Standard_Boolean toEnable = Standard_True;
4925       if (anArgIter + 1 < theArgNb
4926        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4927       {
4928         ++anArgIter;
4929       }
4930       aColorScale->SetSmoothTransition (toEnable);
4931     }
4932     else if (aFlag == "-xy")
4933     {
4934       if (anArgIter + 2 >= theArgNb)
4935       {
4936         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4937         return 1;
4938       }
4939
4940       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
4941       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
4942       if (!anX.IsIntegerValue()
4943        || !anY.IsIntegerValue())
4944       {
4945         std::cout << "Error: coordinates should be integer values!\n";
4946         return 1;
4947       }
4948
4949       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
4950     }
4951     else if (aFlag == "-width"
4952           || aFlag == "-w"
4953           || aFlag == "-breadth")
4954     {
4955       if (anArgIter + 1 >= theArgNb)
4956       {
4957         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4958         return 1;
4959       }
4960
4961       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
4962       if (!aBreadth.IsIntegerValue())
4963       {
4964         std::cout << "Error: a width should be an integer value!\n";
4965         return 1;
4966       }
4967       aColorScale->SetBreadth (aBreadth.IntegerValue());
4968     }
4969     else if (aFlag == "-height"
4970           || aFlag == "-h")
4971     {
4972       if (anArgIter + 1 >= theArgNb)
4973       {
4974         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4975         return 1;
4976       }
4977
4978       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
4979       if (!aHeight.IsIntegerValue())
4980       {
4981         std::cout << "Error: a width should be an integer value!\n";
4982         return 1;
4983       }
4984       aColorScale->SetHeight (aHeight.IntegerValue());
4985     }
4986     else if (aFlag == "-color")
4987     {
4988       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4989       {
4990         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
4991         return 1;
4992       }
4993       else if (anArgIter + 2 >= theArgNb)
4994       {
4995         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4996         return 1;
4997       }
4998
4999       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
5000       if (!anInd.IsIntegerValue())
5001       {
5002         std::cout << "Error: Index value should be integer!\n";
5003         return 1;
5004       }
5005       const Standard_Integer anIndex = anInd.IntegerValue();
5006       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
5007       {
5008         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
5009         return 1;
5010       }
5011
5012       Quantity_Color aColor;
5013       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
5014                                                            theArgVec + (anArgIter + 1),
5015                                                            aColor);
5016       if (aNbParsed == 0)
5017       {
5018         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
5019         return 1;
5020       }
5021       aColorScale->SetIntervalColor (aColor, anIndex);
5022       aColorScale->SetColorType (Aspect_TOCSD_USER);
5023       anArgIter += aNbParsed;
5024     }
5025     else if (aFlag == "-label")
5026     {
5027       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
5028       {
5029         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
5030         return 1;
5031       }
5032       else if (anArgIter + 2 >= theArgNb)
5033       {
5034         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5035         return 1;
5036       }
5037
5038       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
5039       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
5040       {
5041         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
5042         return 1;
5043       }
5044
5045       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
5046       aColorScale->SetLabel     (aText, anIndex);
5047       aColorScale->SetLabelType (Aspect_TOCSD_USER);
5048       anArgIter += 2;
5049     }
5050     else if (aFlag == "-labelat"
5051           || aFlag == "-labat"
5052           || aFlag == "-labelatborder"
5053           || aFlag == "-labatborder"
5054           || aFlag == "-labelatcenter"
5055           || aFlag == "-labatcenter")
5056     {
5057       Standard_Boolean toEnable = Standard_True;
5058       if (aFlag == "-labelat"
5059        || aFlag == "-labat")
5060       {
5061         Standard_Integer aLabAtBorder = -1;
5062         if (++anArgIter >= theArgNb)
5063         {
5064           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
5065           anAtBorder.LowerCase();
5066           if (anAtBorder == "border")
5067           {
5068             aLabAtBorder = 1;
5069           }
5070           else if (anAtBorder == "center")
5071           {
5072             aLabAtBorder = 0;
5073           }
5074         }
5075         if (aLabAtBorder == -1)
5076         {
5077           std::cout << "Syntax error at argument '" << anArg << "'!\n";
5078           return 1;
5079         }
5080         toEnable = (aLabAtBorder == 1);
5081       }
5082       else if (anArgIter + 1 < theArgNb
5083             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
5084       {
5085         ++anArgIter;
5086       }
5087       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
5088                                   || aFlag == "-labatcenter"
5089                                    ? !toEnable
5090                                    :  toEnable);
5091     }
5092     else if (aFlag == "-colors")
5093     {
5094       Aspect_SequenceOfColor aSeq;
5095       for (;;)
5096       {
5097         Quantity_Color aColor;
5098         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
5099                                                              theArgVec + (anArgIter + 1),
5100                                                              aColor);
5101         if (aNbParsed == 0)
5102         {
5103           break;
5104         }
5105         anArgIter += aNbParsed;
5106         aSeq.Append (aColor);
5107       }
5108       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
5109       {
5110         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
5111                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
5112         return 1;
5113       }
5114
5115       aColorScale->SetColors    (aSeq);
5116       aColorScale->SetColorType (Aspect_TOCSD_USER);
5117     }
5118     else if (aFlag == "-labels"
5119           || aFlag == "-freelabels")
5120     {
5121       if (anArgIter + 1 >= theArgNb)
5122       {
5123         std::cout << "Syntax error at argument '" << anArg << "'!\n";
5124         return 1;
5125       }
5126
5127       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
5128                                  ? aColorScale->GetNumberOfIntervals() + 1
5129                                  : aColorScale->GetNumberOfIntervals();
5130       if (aFlag == "-freelabels")
5131       {
5132         ++anArgIter;
5133         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
5134       }
5135       if (anArgIter + aNbLabels >= theArgNb)
5136       {
5137         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
5138         return 1;
5139       }
5140
5141       TColStd_SequenceOfExtendedString aSeq;
5142       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
5143       {
5144         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
5145       }
5146       aColorScale->SetLabels (aSeq);
5147       aColorScale->SetLabelType (Aspect_TOCSD_USER);
5148     }
5149     else if (aFlag == "-title")
5150     {
5151       if (anArgIter + 1 >= theArgNb)
5152       {
5153         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5154         return 1;
5155       }
5156
5157       Standard_Boolean isTwoArgs = Standard_False;
5158       if (anArgIter + 2 < theArgNb)
5159       {
5160         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
5161         aSecondArg.LowerCase();
5162       Standard_DISABLE_DEPRECATION_WARNINGS
5163         if (aSecondArg == "none")
5164         {
5165           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
5166           isTwoArgs = Standard_True;
5167         }
5168         else if (aSecondArg == "left")
5169         {
5170           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
5171           isTwoArgs = Standard_True;
5172         }
5173         else if (aSecondArg == "right")
5174         {
5175           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
5176           isTwoArgs = Standard_True;
5177         }
5178         else if (aSecondArg == "center")
5179         {
5180           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
5181           isTwoArgs = Standard_True;
5182         }
5183       Standard_ENABLE_DEPRECATION_WARNINGS
5184       }
5185
5186       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
5187       if (isTwoArgs)
5188       {
5189         anArgIter += 1;
5190       }
5191       anArgIter += 1;
5192     }
5193     else if (aFlag == "-demoversion"
5194           || aFlag == "-demo")
5195     {
5196       aColorScale->SetPosition (0, 0);
5197       aColorScale->SetTextHeight (16);
5198       aColorScale->SetRange (0.0, 100.0);
5199       aColorScale->SetNumberOfIntervals (10);
5200       aColorScale->SetBreadth (0);
5201       aColorScale->SetHeight  (0);
5202       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
5203       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
5204       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
5205     }
5206     else if (aFlag == "-findcolor")
5207     {
5208       if (anArgIter + 1 >= theArgNb)
5209       {
5210         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
5211         return 1;
5212       }
5213
5214       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
5215
5216       if (!anArg1.IsRealValue())
5217       {
5218         std::cout << "Error: the value should be real!\n";
5219         return 1;
5220       }
5221
5222       Quantity_Color aColor;
5223       aColorScale->FindColor (anArg1.RealValue(), aColor);
5224       theDI << Quantity_Color::StringName (aColor.Name());
5225       return 0;
5226     }
5227     else
5228     {
5229       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
5230       return 1;
5231     }
5232   }
5233
5234   Standard_Integer aWinWidth = 0, aWinHeight = 0;
5235   aView->Window()->Size (aWinWidth, aWinHeight);
5236   if (aColorScale->GetBreadth() == 0)
5237   {
5238     aColorScale->SetBreadth (aWinWidth);
5239   }
5240   if (aColorScale->GetHeight() == 0)
5241   {
5242     aColorScale->SetHeight (aWinHeight);
5243   }
5244   aColorScale->SetToUpdate();
5245   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
5246   return 0;
5247 }
5248
5249 //==============================================================================
5250 //function : VGraduatedTrihedron
5251 //purpose  : Displays or hides a graduated trihedron
5252 //==============================================================================
5253 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
5254                                   Quantity_Color& theColor)
5255 {
5256   Quantity_NameOfColor aColorName;
5257   TCollection_AsciiString aVal = theValue;
5258   aVal.UpperCase();
5259   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
5260   {
5261     return Standard_False;
5262   }
5263   theColor = Quantity_Color (aColorName);
5264   return Standard_True;
5265 }
5266
5267 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
5268 {
5269   if (theArgNum < 2)
5270   {
5271     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
5272               << theArgs[0] <<"' for more information.\n";
5273     return 1;  //TCL_ERROR
5274   }
5275
5276   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
5277   TCollection_AsciiString aParseKey;
5278   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
5279   {
5280     TCollection_AsciiString anArg (theArgs [anArgIt]);
5281
5282     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
5283     {
5284       aParseKey = anArg;
5285       aParseKey.Remove (1);
5286       aParseKey.LowerCase();
5287       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
5288       continue;
5289     }
5290
5291     if (aParseKey.IsEmpty())
5292     {
5293       continue;
5294     }
5295
5296     aMapOfArgs(aParseKey)->Append (anArg);
5297   }
5298
5299   // Check parameters
5300   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
5301        aMapIt.More(); aMapIt.Next())
5302   {
5303     const TCollection_AsciiString& aKey = aMapIt.Key();
5304     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
5305
5306     // Bool key, without arguments
5307     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
5308         && anArgs->IsEmpty())
5309     {
5310       continue;
5311     }
5312
5313     // One argument
5314     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
5315           && anArgs->Length() == 1)
5316     {
5317       continue;
5318     }
5319
5320     // On/off arguments
5321     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
5322         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
5323         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
5324         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
5325         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
5326     {
5327       continue;
5328     }
5329
5330     // One string argument
5331     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
5332           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
5333           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5334     {
5335       continue;
5336     }
5337
5338     // One integer argument
5339     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
5340           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
5341           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
5342           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
5343          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
5344     {
5345       continue;
5346     }
5347
5348     // One real argument
5349     if ( aKey.IsEqual ("arrowlength")
5350          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
5351     {
5352       continue;
5353     }
5354
5355     // Two string arguments
5356     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
5357          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5358     {
5359       continue;
5360     }
5361
5362     TCollection_AsciiString aLowerKey;
5363     aLowerKey  = "-";
5364     aLowerKey += aKey;
5365     aLowerKey.LowerCase();
5366     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
5367     std::cout << "Type help for more information.\n";
5368     return 1;
5369   }
5370
5371   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
5372   if (anAISContext.IsNull())
5373   {
5374     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
5375     return 1;
5376   }
5377
5378   Standard_Boolean toDisplay = Standard_True;
5379   Quantity_Color aColor;
5380   Graphic3d_GraduatedTrihedron aTrihedronData;
5381   // Process parameters
5382   Handle(TColStd_HSequenceOfAsciiString) aValues;
5383   if (aMapOfArgs.Find ("off", aValues))
5384   {
5385     toDisplay = Standard_False;
5386   }
5387
5388   // AXES NAMES
5389   if (aMapOfArgs.Find ("xname", aValues))
5390   {
5391     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
5392   }
5393   if (aMapOfArgs.Find ("yname", aValues))
5394   {
5395     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
5396   }
5397   if (aMapOfArgs.Find ("zname", aValues))
5398   {
5399     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
5400   }
5401   if (aMapOfArgs.Find ("xdrawname", aValues))
5402   {
5403     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5404   }
5405   if (aMapOfArgs.Find ("ydrawname", aValues))
5406   {
5407     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5408   }
5409   if (aMapOfArgs.Find ("zdrawname", aValues))
5410   {
5411     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5412   }
5413   if (aMapOfArgs.Find ("xnameoffset", aValues))
5414   {
5415     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5416   }
5417   if (aMapOfArgs.Find ("ynameoffset", aValues))
5418   {
5419     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5420   }
5421   if (aMapOfArgs.Find ("znameoffset", aValues))
5422   {
5423     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5424   }
5425
5426   // COLORS
5427   if (aMapOfArgs.Find ("xnamecolor", aValues))
5428   {
5429     if (!GetColor (aValues->Value(1), aColor))
5430     {
5431       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
5432       return 1;
5433     }
5434     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
5435   }
5436   if (aMapOfArgs.Find ("ynamecolor", aValues))
5437   {
5438     if (!GetColor (aValues->Value(1), aColor))
5439     {
5440       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
5441       return 1;
5442     }
5443     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
5444   }
5445   if (aMapOfArgs.Find ("znamecolor", aValues))
5446   {
5447     if (!GetColor (aValues->Value(1), aColor))
5448     {
5449       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
5450       return 1;
5451     }
5452     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
5453   }
5454   if (aMapOfArgs.Find ("xcolor", aValues))
5455   {
5456     if (!GetColor (aValues->Value(1), aColor))
5457     {
5458       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
5459       return 1;
5460     }
5461     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
5462   }
5463   if (aMapOfArgs.Find ("ycolor", aValues))
5464   {
5465     if (!GetColor (aValues->Value(1), aColor))
5466     {
5467       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
5468       return 1;
5469     }
5470     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
5471   }
5472   if (aMapOfArgs.Find ("zcolor", aValues))
5473   {
5474     if (!GetColor (aValues->Value(1), aColor))
5475     {
5476       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
5477       return 1;
5478     }
5479     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
5480   }
5481
5482   // TICKMARKS
5483   if (aMapOfArgs.Find ("xticks", aValues))
5484   {
5485     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5486   }
5487   if (aMapOfArgs.Find ("yticks", aValues))
5488   {
5489     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5490   }
5491   if (aMapOfArgs.Find ("zticks", aValues))
5492   {
5493     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5494   }
5495   if (aMapOfArgs.Find ("xticklength", aValues))
5496   {
5497     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5498   }
5499   if (aMapOfArgs.Find ("yticklength", aValues))
5500   {
5501     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5502   }
5503   if (aMapOfArgs.Find ("zticklength", aValues))
5504   {
5505     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5506   }
5507   if (aMapOfArgs.Find ("xdrawticks", aValues))
5508   {
5509     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5510   }
5511   if (aMapOfArgs.Find ("ydrawticks", aValues))
5512   {
5513     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5514   }
5515   if (aMapOfArgs.Find ("zdrawticks", aValues))
5516   {
5517     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5518   }
5519
5520   // VALUES
5521   if (aMapOfArgs.Find ("xdrawvalues", aValues))
5522   {
5523     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5524   }
5525   if (aMapOfArgs.Find ("ydrawvalues", aValues))
5526   {
5527     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5528   }
5529   if (aMapOfArgs.Find ("zdrawvalues", aValues))
5530   {
5531     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5532   }
5533   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
5534   {
5535     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5536   }
5537   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
5538   {
5539     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5540   }
5541   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
5542   {
5543     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5544   }
5545
5546   // ARROWS
5547   if (aMapOfArgs.Find ("arrowlength", aValues))
5548   {
5549     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
5550   }
5551
5552   // FONTS
5553   if (aMapOfArgs.Find ("namefont", aValues))
5554   {
5555     aTrihedronData.SetNamesFont (aValues->Value(1));
5556   }
5557   if (aMapOfArgs.Find ("valuesfont", aValues))
5558   {
5559     aTrihedronData.SetValuesFont (aValues->Value(1));
5560   }
5561
5562   if (aMapOfArgs.Find ("drawgrid", aValues))
5563   {
5564     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
5565   }
5566   if (aMapOfArgs.Find ("drawaxes", aValues))
5567   {
5568     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
5569   }
5570
5571   // The final step: display of erase trihedron
5572   if (toDisplay)
5573   {
5574     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
5575   }
5576   else
5577   {
5578     ViewerTest::CurrentView()->GraduatedTrihedronErase();
5579   }
5580
5581   ViewerTest::GetAISContext()->UpdateCurrentViewer();
5582   ViewerTest::CurrentView()->Redraw();
5583
5584   return 0;
5585 }
5586
5587 //==============================================================================
5588 //function : VTile
5589 //purpose  :
5590 //==============================================================================
5591 static int VTile (Draw_Interpretor& theDI,
5592                   Standard_Integer  theArgNb,
5593                   const char**      theArgVec)
5594 {
5595   Handle(V3d_View) aView = ViewerTest::CurrentView();
5596   if (aView.IsNull())
5597   {
5598     std::cerr << "Error: no active viewer.\n";
5599     return 1;
5600   }
5601
5602   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
5603   if (theArgNb < 2)
5604   {
5605     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
5606           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
5607           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
5608     return 0;
5609   }
5610
5611   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
5612   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5613   {
5614     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5615     anArg.LowerCase();
5616     if (anArg == "-lowerleft"
5617      || anArg == "-upperleft")
5618     {
5619       if (anArgIter + 3 < theArgNb)
5620       {
5621         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5622         return 1;
5623       }
5624       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
5625       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5626       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5627     }
5628     else if (anArg == "-total"
5629           || anArg == "-totalsize"
5630           || anArg == "-viewsize")
5631     {
5632       if (anArgIter + 3 < theArgNb)
5633       {
5634         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5635         return 1;
5636       }
5637       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5638       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5639       if (aTile.TotalSize.x() < 1
5640        || aTile.TotalSize.y() < 1)
5641       {
5642         std::cerr << "Error: total size is incorrect.\n";
5643         return 1;
5644       }
5645     }
5646     else if (anArg == "-tilesize")
5647     {
5648       if (anArgIter + 3 < theArgNb)
5649       {
5650         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5651         return 1;
5652       }
5653
5654       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5655       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5656       if (aTile.TileSize.x() < 1
5657        || aTile.TileSize.y() < 1)
5658       {
5659         std::cerr << "Error: tile size is incorrect.\n";
5660         return 1;
5661       }
5662     }
5663     else if (anArg == "-unset")
5664     {
5665       aView->Camera()->SetTile (Graphic3d_CameraTile());
5666       aView->Redraw();
5667       return 0;
5668     }
5669   }
5670
5671   if (aTile.TileSize.x() < 1
5672    || aTile.TileSize.y() < 1)
5673   {
5674     std::cerr << "Error: tile size is undefined.\n";
5675     return 1;
5676   }
5677   else if (aTile.TotalSize.x() < 1
5678         || aTile.TotalSize.y() < 1)
5679   {
5680     std::cerr << "Error: total size is undefined.\n";
5681     return 1;
5682   }
5683
5684   aView->Camera()->SetTile (aTile);
5685   aView->Redraw();
5686   return 0;
5687 }
5688
5689 //! Format ZLayer ID.
5690 inline const char* formZLayerId (const Standard_Integer theLayerId)
5691 {
5692   switch (theLayerId)
5693   {
5694     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
5695     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
5696     case Graphic3d_ZLayerId_Top:     return "[TOP]";
5697     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
5698     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
5699     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
5700   }
5701   return "";
5702 }
5703
5704 //! Print the ZLayer information.
5705 inline void printZLayerInfo (Draw_Interpretor& theDI,
5706                              const Graphic3d_ZLayerSettings& theLayer)
5707 {
5708   if (!theLayer.Name().IsEmpty())
5709   {
5710     theDI << "  Name: " << theLayer.Name() << "\n";
5711   }
5712   if (theLayer.IsImmediate())
5713   {
5714     theDI << "  Immediate: TRUE\n";
5715   }
5716   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
5717   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
5718   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
5719   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
5720   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
5721   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
5722   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
5723   {
5724     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
5725   }
5726 }
5727
5728 //==============================================================================
5729 //function : VZLayer
5730 //purpose  : Test z layer operations for v3d viewer
5731 //==============================================================================
5732 static int VZLayer (Draw_Interpretor& theDI,
5733                     Standard_Integer  theArgNb,
5734                     const char**      theArgVec)
5735 {
5736   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5737   if (aContextAIS.IsNull())
5738   {
5739     std::cout << "No active viewer!\n";
5740     return 1;
5741   }
5742
5743   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
5744   if (theArgNb < 2)
5745   {
5746     TColStd_SequenceOfInteger aLayers;
5747     aViewer->GetAllZLayers (aLayers);
5748     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5749     {
5750       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
5751       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
5752       printZLayerInfo (theDI, aSettings);
5753     }
5754     return 1;
5755   }
5756
5757   Standard_Integer anArgIter = 1;
5758   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5759   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
5760   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5761   {
5762     ++anArgIter;
5763   }
5764
5765   {
5766     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
5767     if (aFirstArg.IsIntegerValue())
5768     {
5769       ++anArgIter;
5770       aLayerId = aFirstArg.IntegerValue();
5771     }
5772     else
5773     {
5774       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
5775       {
5776         ++anArgIter;
5777       }
5778     }
5779   }
5780
5781   for (; anArgIter < theArgNb; ++anArgIter)
5782   {
5783     // perform operation
5784     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5785     anArg.LowerCase();
5786     if (anUpdateTool.parseRedrawMode (anArg))
5787     {
5788       //
5789     }
5790     else if (anArg == "-add"
5791           || anArg == "add")
5792     {
5793       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5794       if (!aViewer->AddZLayer (aLayerId))
5795       {
5796         std::cout << "Error: can not add a new z layer!\n";
5797         return 0;
5798       }
5799
5800       theDI << aLayerId;
5801     }
5802     else if (anArg == "-del"
5803           || anArg == "-delete"
5804           || anArg == "del")
5805     {
5806       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5807       {
5808         if (++anArgIter >= theArgNb)
5809         {
5810           std::cout << "Syntax error: id of z layer to remove is missing\n";
5811           return 1;
5812         }
5813
5814         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5815       }
5816
5817       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
5818        || aLayerId == Graphic3d_ZLayerId_Default
5819        || aLayerId == Graphic3d_ZLayerId_Top
5820        || aLayerId == Graphic3d_ZLayerId_Topmost
5821        || aLayerId == Graphic3d_ZLayerId_TopOSD
5822        || aLayerId == Graphic3d_ZLayerId_BotOSD)
5823       {
5824         std::cout << "Syntax error: standard Z layer can not be removed\n";
5825         return 1;
5826       }
5827
5828       // move all object displayed in removing layer to default layer
5829       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5830            anObjIter.More(); anObjIter.Next())
5831       {
5832         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
5833         if (aPrs.IsNull()
5834          || aPrs->ZLayer() != aLayerId)
5835         {
5836           continue;
5837         }
5838         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
5839       }
5840
5841       if (!aViewer->RemoveZLayer (aLayerId))
5842       {
5843         std::cout << "Z layer can not be removed!\n";
5844       }
5845       else
5846       {
5847         theDI << aLayerId << " ";
5848       }
5849     }
5850     else if (anArg == "-get"
5851           || anArg == "get")
5852     {
5853       TColStd_SequenceOfInteger aLayers;
5854       aViewer->GetAllZLayers (aLayers);
5855       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5856       {
5857         theDI << aLayeriter.Value() << " ";
5858       }
5859
5860       theDI << "\n";
5861     }
5862     else if (anArg == "-name")
5863     {
5864       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5865       {
5866         std::cout << "Syntax error: id of Z layer is missing\n";
5867         return 1;
5868       }
5869
5870       if (++anArgIter >= theArgNb)
5871       {
5872         std::cout << "Syntax error: name is missing\n";
5873         return 1;
5874       }
5875
5876       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5877       aSettings.SetName (theArgVec[anArgIter]);
5878       aViewer->SetZLayerSettings (aLayerId, aSettings);
5879     }
5880     else if (anArg == "-origin")
5881     {
5882       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5883       {
5884         std::cout << "Syntax error: id of Z layer is missing\n";
5885         return 1;
5886       }
5887
5888       if (anArgIter + 2 >= theArgNb)
5889       {
5890         std::cout << "Syntax error: origin coordinates are missing\n";
5891         return 1;
5892       }
5893
5894       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5895       gp_XYZ anOrigin;
5896       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5897       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5898       anOrigin.SetZ (0.0);
5899       if (anArgIter + 3 < theArgNb)
5900       {
5901         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5902         anArgIter += 3;
5903       }
5904       else
5905       {
5906         anArgIter += 2;
5907       }
5908       aSettings.SetOrigin (anOrigin);
5909       aViewer->SetZLayerSettings (aLayerId, aSettings);
5910     }
5911     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5912           && anArgIter + 1 < theArgNb
5913           && (anArg == "-cullingdistance"
5914            || anArg == "-cullingdist"
5915            || anArg == "-culldistance"
5916            || anArg == "-culldist"
5917            || anArg == "-distcull"
5918            || anArg == "-distculling"
5919            || anArg == "-distanceculling"))
5920     {
5921       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5922       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5923       aSettings.SetCullingDistance (aDist);
5924       aViewer->SetZLayerSettings (aLayerId, aSettings);
5925     }
5926     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5927           && anArgIter + 1 < theArgNb
5928           && (anArg == "-cullingsize"
5929            || anArg == "-cullsize"
5930            || anArg == "-sizecull"
5931            || anArg == "-sizeculling"))
5932     {
5933       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5934       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5935       aSettings.SetCullingSize (aSize);
5936       aViewer->SetZLayerSettings (aLayerId, aSettings);
5937     }
5938     else if (anArg == "-settings"
5939           || anArg == "settings")
5940     {
5941       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5942       {
5943         if (++anArgIter >= theArgNb)
5944         {
5945           std::cout << "Syntax error: id of Z layer is missing\n";
5946           return 1;
5947         }
5948
5949         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5950       }
5951
5952       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5953       printZLayerInfo (theDI, aSettings);
5954     }
5955     else if (anArg == "-enable"
5956           || anArg == "enable"
5957           || anArg == "-disable"
5958           || anArg == "disable")
5959     {
5960       const Standard_Boolean toEnable = anArg == "-enable"
5961                                      || anArg == "enable";
5962       if (++anArgIter >= theArgNb)
5963       {
5964         std::cout << "Syntax error: option name is missing\n";
5965         return 1;
5966       }
5967
5968       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5969       aSubOp.LowerCase();
5970       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5971       {
5972         if (++anArgIter >= theArgNb)
5973         {
5974           std::cout << "Syntax error: id of Z layer is missing\n";
5975           return 1;
5976         }
5977
5978         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5979       }
5980
5981       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5982       if (aSubOp == "depthtest"
5983        || aSubOp == "test")
5984       {
5985         aSettings.SetEnableDepthTest (toEnable);
5986       }
5987       else if (aSubOp == "depthwrite"
5988             || aSubOp == "write")
5989       {
5990         aSettings.SetEnableDepthWrite (toEnable);
5991       }
5992       else if (aSubOp == "depthclear"
5993             || aSubOp == "clear")
5994       {
5995         aSettings.SetClearDepth (toEnable);
5996       }
5997       else if (aSubOp == "depthoffset"
5998             || aSubOp == "offset")
5999       {
6000         Graphic3d_PolygonOffset aParams;
6001         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
6002         if (toEnable)
6003         {
6004           if (anArgIter + 2 >= theArgNb)
6005           {
6006             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
6007             return 1;
6008           }
6009
6010           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
6011           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
6012         }
6013         aSettings.SetPolygonOffset (aParams);
6014       }
6015       else if (aSubOp == "positiveoffset"
6016             || aSubOp == "poffset")
6017       {
6018         if (toEnable)
6019         {
6020           aSettings.SetDepthOffsetPositive();
6021         }
6022         else
6023         {
6024           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
6025         }
6026       }
6027       else if (aSubOp == "negativeoffset"
6028             || aSubOp == "noffset")
6029       {
6030         if (toEnable)
6031         {
6032           aSettings.SetDepthOffsetNegative();
6033         }
6034         else
6035         {
6036           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
6037         }
6038       }
6039       else if (aSubOp == "textureenv")
6040       {
6041         aSettings.SetEnvironmentTexture (toEnable);
6042       }
6043
6044       aViewer->SetZLayerSettings (aLayerId, aSettings);
6045     }
6046     else
6047     {
6048       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
6049       return 1;
6050     }
6051   }
6052
6053   return 0;
6054 }
6055
6056 // The interactive presentation of 2d layer item
6057 // for "vlayerline" command it provides a presentation of
6058 // line with user-defined linewidth, linetype and transparency.
6059 class V3d_LineItem : public AIS_InteractiveObject
6060 {
6061 public:
6062   // CASCADE RTTI
6063   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
6064
6065   // constructor
6066   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
6067                                Standard_Real X2, Standard_Real Y2,
6068                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
6069                                Standard_Real theWidth    = 0.5,
6070                                Standard_Real theTransp   = 1.0);
6071
6072   private:
6073
6074   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
6075                 const Handle(Prs3d_Presentation)& thePresentation,
6076                 const Standard_Integer theMode) Standard_OVERRIDE;
6077
6078   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
6079                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
6080   {}
6081
6082 private:
6083
6084   Standard_Real       myX1, myY1, myX2, myY2;
6085   Aspect_TypeOfLine   myType;
6086   Standard_Real       myWidth;
6087 };
6088
6089 // default constructor for line item
6090 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
6091                            Standard_Real X2, Standard_Real Y2,
6092                            Aspect_TypeOfLine theType,
6093                            Standard_Real theWidth,
6094                            Standard_Real theTransp) :
6095   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
6096   myType(theType), myWidth(theWidth)
6097 {
6098   SetTransparency (1-theTransp);
6099 }
6100
6101 // render line
6102 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
6103                             const Handle(Prs3d_Presentation)& thePresentation,
6104                             const Standard_Integer /*theMode*/)
6105 {
6106   thePresentation->Clear();
6107   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
6108   Standard_Integer aWidth, aHeight;
6109   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
6110   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
6111   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
6112   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
6113   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
6114   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
6115   aGroup->SetPrimitivesAspect (anAspect->Aspect());
6116   aGroup->AddPrimitiveArray (aPrim);
6117 }
6118
6119 //=============================================================================
6120 //function : VLayerLine
6121 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
6122 //         : linewidth, transparency coefficient
6123 //============================================================================
6124 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
6125 {
6126   // get the active view
6127   Handle(V3d_View) aView = ViewerTest::CurrentView();
6128   if (aView.IsNull())
6129   {
6130     di << "Call vinit before!\n";
6131     return 1;
6132   }
6133   else if (argc < 5)
6134   {
6135     di << "Use: " << argv[0];
6136     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
6137     di << " linetype : { 0 | 1 | 2 | 3 } \n";
6138     di << "              0 - solid  \n";
6139     di << "              1 - dashed \n";
6140     di << "              2 - dot    \n";
6141     di << "              3 - dashdot\n";
6142     di << " transparency : { 0.0 - 1.0 } \n";
6143     di << "                  0.0 - transparent\n";
6144     di << "                  1.0 - visible    \n";
6145     return 1;
6146   }
6147
6148   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6149   // get the input params
6150   Standard_Real X1 = Draw::Atof(argv[1]);
6151   Standard_Real Y1 = Draw::Atof(argv[2]);
6152   Standard_Real X2 = Draw::Atof(argv[3]);
6153   Standard_Real Y2 = Draw::Atof(argv[4]);
6154
6155   Standard_Real aWidth = 0.5;
6156   Standard_Real aTransparency = 1.0;
6157
6158   // has width
6159   if (argc > 5)
6160     aWidth = Draw::Atof(argv[5]);
6161
6162   // select appropriate line type
6163   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
6164   if (argc > 6
6165   && !ViewerTest::ParseLineType (argv[6], aLineType))
6166   {
6167     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
6168     return 1;
6169   }
6170
6171   // has transparency
6172   if (argc > 7)
6173   {
6174     aTransparency = Draw::Atof(argv[7]);
6175     if (aTransparency < 0 || aTransparency > 1.0)
6176       aTransparency = 1.0;
6177   }
6178
6179   static Handle (V3d_LineItem) aLine;
6180   if (!aLine.IsNull())
6181   {
6182     aContext->Erase (aLine, Standard_False);
6183   }
6184   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
6185                             aLineType, aWidth,
6186                             aTransparency);
6187
6188   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
6189   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
6190   aLine->SetToUpdate();
6191   aContext->Display (aLine, Standard_True);
6192
6193   return 0;
6194 }
6195
6196
6197 //==============================================================================
6198 //function : VGrid
6199 //purpose  :
6200 //==============================================================================
6201
6202 static int VGrid (Draw_Interpretor& /*theDI*/,
6203                   Standard_Integer  theArgNb,
6204                   const char**      theArgVec)
6205 {
6206   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
6207   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6208   if (aView.IsNull() || aViewer.IsNull())
6209   {
6210     std::cerr << "Error: no active view\n";
6211     return 1;
6212   }
6213
6214   Aspect_GridType     aType = aViewer->GridType();
6215   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
6216   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
6217   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
6218   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
6219   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6220   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6221   {
6222     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6223     anArg.LowerCase();
6224     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
6225     {
6226       continue;
6227     }
6228     else if (anArgIter + 1 < theArgNb
6229           && anArg == "-type")
6230     {
6231       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
6232       anArgNext.LowerCase();
6233       if (anArgNext == "r"
6234        || anArgNext == "rect"
6235        || anArgNext == "rectangular")
6236       {
6237         aType = Aspect_GT_Rectangular;
6238       }
6239       else if (anArgNext == "c"
6240             || anArgNext == "circ"
6241             || anArgNext == "circular")
6242       {
6243         aType = Aspect_GT_Circular;
6244       }
6245       else
6246       {
6247         std::cout << "Syntax error at '" << anArgNext << "'\n";
6248         return 1;
6249       }
6250     }
6251     else if (anArgIter + 1 < theArgNb
6252           && anArg == "-mode")
6253     {
6254       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
6255       anArgNext.LowerCase();
6256       if (anArgNext == "l"
6257        || anArgNext == "line"
6258        || anArgNext == "lines")
6259       {
6260         aMode = Aspect_GDM_Lines;
6261       }
6262       else if (anArgNext == "p"
6263             || anArgNext == "point"
6264             || anArgNext == "points")
6265       {
6266         aMode = Aspect_GDM_Points;
6267       }
6268       else
6269       {
6270         std::cout << "Syntax error at '" << anArgNext << "'\n";
6271         return 1;
6272       }
6273     }
6274     else if (anArgIter + 2 < theArgNb
6275           && (anArg == "-origin"
6276            || anArg == "-orig"))
6277     {
6278       hasOrigin = true;
6279       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6280                               Draw::Atof (theArgVec[anArgIter + 2]));
6281       anArgIter += 2;
6282     }
6283     else if (anArgIter + 2 < theArgNb
6284           && anArg == "-step")
6285     {
6286       hasStep = true;
6287       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6288                             Draw::Atof (theArgVec[anArgIter + 2]));
6289       if (aNewStepXY.x() <= 0.0
6290        || aNewStepXY.y() <= 0.0)
6291       {
6292         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6293         return 1;
6294       }
6295       anArgIter += 2;
6296     }
6297     else if (anArgIter + 1 < theArgNb
6298           && (anArg == "-angle"
6299            || anArg == "-rotangle"
6300            || anArg == "-rotationangle"))
6301     {
6302       hasRotAngle = true;
6303       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
6304     }
6305     else if (anArgIter + 1 < theArgNb
6306           && (anArg == "-zoffset"
6307            || anArg == "-dz"))
6308     {
6309       hasZOffset = true;
6310       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
6311     }
6312     else if (anArgIter + 1 < theArgNb
6313           && anArg == "-radius")
6314     {
6315       hasSize = true;
6316       ++anArgIter;
6317       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
6318       if (aNewStepXY.x() <= 0.0)
6319       {
6320         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
6321         return 1;
6322       }
6323     }
6324     else if (anArgIter + 2 < theArgNb
6325           && anArg == "-size")
6326     {
6327       hasSize = true;
6328       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6329                             Draw::Atof (theArgVec[anArgIter + 2]));
6330       if (aNewStepXY.x() <= 0.0
6331        || aNewStepXY.y() <= 0.0)
6332       {
6333         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6334         return 1;
6335       }
6336       anArgIter += 2;
6337     }
6338     else if (anArg == "r"
6339           || anArg == "rect"
6340           || anArg == "rectangular")
6341     {
6342       aType = Aspect_GT_Rectangular;
6343     }
6344     else if (anArg == "c"
6345           || anArg == "circ"
6346           || anArg == "circular")
6347     {
6348       aType = Aspect_GT_Circular;
6349     }
6350     else if (anArg == "l"
6351           || anArg == "line"
6352           || anArg == "lines")
6353     {
6354       aMode = Aspect_GDM_Lines;
6355     }
6356     else if (anArg == "p"
6357           || anArg == "point"
6358           || anArg == "points")
6359     {
6360       aMode = Aspect_GDM_Points;
6361     }
6362     else if (anArgIter + 1 >= theArgNb
6363           && anArg == "off")
6364     {
6365       aViewer->DeactivateGrid();
6366       return 0;
6367     }
6368     else
6369     {
6370       std::cout << "Syntax error at '" << anArg << "'\n";
6371       return 1;
6372     }
6373   }
6374
6375   if (aType == Aspect_GT_Rectangular)
6376   {
6377     Graphic3d_Vec2d anOrigXY, aStepXY;
6378     Standard_Real aRotAngle = 0.0;
6379     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6380     if (hasOrigin)
6381     {
6382       anOrigXY = aNewOriginXY;
6383     }
6384     if (hasStep)
6385     {
6386       aStepXY = aNewStepXY;
6387     }
6388     if (hasRotAngle)
6389     {
6390       aRotAngle = aNewRotAngle;
6391     }
6392     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6393     if (hasSize || hasZOffset)
6394     {
6395       Graphic3d_Vec3d aSize;
6396       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6397       if (hasSize)
6398       {
6399         aSize.x() = aNewSizeXY.x();
6400         aSize.y() = aNewSizeXY.y();
6401       }
6402       if (hasZOffset)
6403       {
6404         aSize.z() = aNewZOffset;
6405       }
6406       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6407     }
6408   }
6409   else if (aType == Aspect_GT_Circular)
6410   {
6411     Graphic3d_Vec2d anOrigXY;
6412     Standard_Real aRadiusStep;
6413     Standard_Integer aDivisionNumber;
6414     Standard_Real aRotAngle = 0.0;
6415     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6416     if (hasOrigin)
6417     {
6418       anOrigXY = aNewOriginXY;
6419     }
6420     if (hasStep)
6421     {
6422       aRadiusStep     = aNewStepXY[0];
6423       aDivisionNumber = (int )aNewStepXY[1];
6424       if (aDivisionNumber < 1)
6425       {
6426         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
6427         return 1;
6428       }
6429     }
6430     if (hasRotAngle)
6431     {
6432       aRotAngle = aNewRotAngle;
6433     }
6434
6435     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6436     if (hasSize || hasZOffset)
6437     {
6438       Standard_Real aRadius = 0.0, aZOffset = 0.0;
6439       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
6440       if (hasSize)
6441       {
6442         aRadius = aNewSizeXY.x();
6443         if (aNewSizeXY.y() != 0.0)
6444         {
6445           std::cout << "Syntax error: circular size should be specified as radius\n";
6446           return 1;
6447         }
6448       }
6449       if (hasZOffset)
6450       {
6451         aZOffset = aNewZOffset;
6452       }
6453       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
6454     }
6455   }
6456   aViewer->ActivateGrid (aType, aMode);
6457   return 0;
6458 }
6459
6460 //==============================================================================
6461 //function : VPriviledgedPlane
6462 //purpose  :
6463 //==============================================================================
6464
6465 static int VPriviledgedPlane (Draw_Interpretor& theDI,
6466                               Standard_Integer  theArgNb,
6467                               const char**      theArgVec)
6468 {
6469   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
6470   {
6471     std::cerr << "Error: wrong number of arguments! See usage:\n";
6472     theDI.PrintHelp (theArgVec[0]);
6473     return 1;
6474   }
6475
6476   // get the active viewer
6477   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6478   if (aViewer.IsNull())
6479   {
6480     std::cerr << "Error: no active viewer. Please call vinit.\n";
6481     return 1;
6482   }
6483
6484   if (theArgNb == 1)
6485   {
6486     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
6487     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
6488     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
6489     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
6490     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
6491           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
6492           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
6493     return 0;
6494   }
6495
6496   Standard_Integer anArgIdx = 1;
6497   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
6498   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
6499   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
6500   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
6501   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
6502   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
6503
6504   gp_Ax3 aPriviledgedPlane;
6505   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
6506   gp_Dir aNorm (aNormX, aNormY, aNormZ);
6507   if (theArgNb > 7)
6508   {
6509     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
6510     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
6511     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
6512     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
6513     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
6514   }
6515   else
6516   {
6517     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
6518   }
6519
6520   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
6521
6522   return 0;
6523 }
6524
6525 //==============================================================================
6526 //function : VConvert
6527 //purpose  :
6528 //==============================================================================
6529
6530 static int VConvert (Draw_Interpretor& theDI,
6531                      Standard_Integer  theArgNb,
6532                      const char**      theArgVec)
6533 {
6534   // get the active view
6535   Handle(V3d_View) aView = ViewerTest::CurrentView();
6536   if (aView.IsNull())
6537   {
6538     std::cerr << "Error: no active view. Please call vinit.\n";
6539     return 1;
6540   }
6541
6542   enum { Model, Ray, View, Window, Grid } aMode = Model;
6543
6544   // access coordinate arguments
6545   TColStd_SequenceOfReal aCoord;
6546   Standard_Integer anArgIdx = 1;
6547   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
6548   {
6549     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6550     if (!anArg.IsRealValue())
6551     {
6552       break;
6553     }
6554     aCoord.Append (anArg.RealValue());
6555   }
6556
6557   // non-numeric argument too early
6558   if (aCoord.IsEmpty())
6559   {
6560     std::cerr << "Error: wrong number of arguments! See usage:\n";
6561     theDI.PrintHelp (theArgVec[0]);
6562     return 1;
6563   }
6564
6565   // collect all other arguments and options
6566   for (; anArgIdx < theArgNb; ++anArgIdx)
6567   {
6568     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6569     anArg.LowerCase();
6570     if      (anArg == "window") aMode = Window;
6571     else if (anArg == "view")   aMode = View;
6572     else if (anArg == "grid")   aMode = Grid;
6573     else if (anArg == "ray")    aMode = Ray;
6574     else
6575     {
6576       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
6577       theDI.PrintHelp (theArgVec[0]);
6578       return 1;
6579     }
6580   }
6581
6582   // complete input checks
6583   if ((aCoord.Length() == 1 && theArgNb > 3) ||
6584       (aCoord.Length() == 2 && theArgNb > 4) ||
6585       (aCoord.Length() == 3 && theArgNb > 5))
6586   {
6587     std::cerr << "Error: wrong number of arguments! See usage:\n";
6588     theDI.PrintHelp (theArgVec[0]);
6589     return 1;
6590   }
6591
6592   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6593   Standard_Integer aXYp[2] = {0, 0};
6594
6595   // convert one-dimensional coordinate
6596   if (aCoord.Length() == 1)
6597   {
6598     switch (aMode)
6599     {
6600       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
6601       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
6602       default:
6603         std::cerr << "Error: wrong arguments! See usage:\n";
6604         theDI.PrintHelp (theArgVec[0]);
6605         return 1;
6606     }
6607   }
6608
6609   // convert 2D coordinates from projection or view reference space
6610   if (aCoord.Length() == 2)
6611   {
6612     switch (aMode)
6613     {
6614       case Model :
6615         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6616         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6617         return 0;
6618
6619       case View :
6620         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
6621         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
6622         return 0;
6623
6624       case Window :
6625         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
6626         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6627         return 0;
6628
6629       case Grid :
6630         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6631         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
6632         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6633         return 0;
6634
6635       case Ray :
6636         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
6637                                 (Standard_Integer) aCoord (2),
6638                                 aXYZ[0], aXYZ[1], aXYZ[2],
6639                                 aXYZ[3], aXYZ[4], aXYZ[5]);
6640         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6641         return 0;
6642
6643       default:
6644         std::cerr << "Error: wrong arguments! See usage:\n";
6645         theDI.PrintHelp (theArgVec[0]);
6646         return 1;
6647     }
6648   }
6649
6650   // convert 3D coordinates from view reference space
6651   else if (aCoord.Length() == 3)
6652   {
6653     switch (aMode)
6654     {
6655       case Window :
6656         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
6657         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6658         return 0;
6659
6660       case Grid :
6661         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
6662         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6663         return 0;
6664
6665       default:
6666         std::cerr << "Error: wrong arguments! See usage:\n";
6667         theDI.PrintHelp (theArgVec[0]);
6668         return 1;
6669     }
6670   }
6671
6672   return 0;
6673 }
6674
6675 //==============================================================================
6676 //function : VFps
6677 //purpose  :
6678 //==============================================================================
6679
6680 static int VFps (Draw_Interpretor& theDI,
6681                  Standard_Integer  theArgNb,
6682                  const char**      theArgVec)
6683 {
6684   // get the active view
6685   Handle(V3d_View) aView = ViewerTest::CurrentView();
6686   if (aView.IsNull())
6687   {
6688     std::cerr << "No active view. Please call vinit.\n";
6689     return 1;
6690   }
6691
6692   Standard_Integer aFramesNb = -1;
6693   Standard_Real aDuration = -1.0;
6694   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6695   {
6696     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6697     anArg.LowerCase();
6698     if (aDuration < 0.0
6699      && anArgIter + 1 < theArgNb
6700      && (anArg == "-duration"
6701       || anArg == "-dur"
6702       || anArg == "-time"))
6703     {
6704       aDuration = Draw::Atof (theArgVec[++anArgIter]);
6705     }
6706     else if (aFramesNb < 0
6707           && anArg.IsIntegerValue())
6708     {
6709       aFramesNb = anArg.IntegerValue();
6710       if (aFramesNb <= 0)
6711       {
6712         std::cerr << "Syntax error at '" << anArg << "'\n";
6713         return 1;
6714       }
6715     }
6716     else
6717     {
6718       std::cerr << "Syntax error at '" << anArg << "'\n";
6719       return 1;
6720     }
6721   }
6722   if (aFramesNb < 0 && aDuration < 0.0)
6723   {
6724     aFramesNb = 100;
6725   }
6726
6727   // the time is meaningless for first call
6728   // due to async OpenGl rendering
6729   aView->Redraw();
6730
6731   // redraw view in loop to estimate average values
6732   OSD_Timer aTimer;
6733   aTimer.Start();
6734   Standard_Integer aFrameIter = 1;
6735   for (;; ++aFrameIter)
6736   {
6737     aView->Redraw();
6738     if ((aFramesNb > 0
6739       && aFrameIter >= aFramesNb)
6740      || (aDuration > 0.0
6741       && aTimer.ElapsedTime() >= aDuration))
6742     {
6743       break;
6744     }
6745   }
6746   aTimer.Stop();
6747   Standard_Real aCpu;
6748   const Standard_Real aTime = aTimer.ElapsedTime();
6749   aTimer.OSD_Chronometer::Show (aCpu);
6750
6751   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
6752   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
6753
6754   // return statistics
6755   theDI << "FPS: " << aFpsAver << "\n"
6756         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
6757
6758   // compute additional statistics in ray-tracing mode
6759   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
6760   if (aParams.Method == Graphic3d_RM_RAYTRACING)
6761   {
6762     Graphic3d_Vec2i aWinSize (0, 0);
6763     aView->Window()->Size (aWinSize.x(), aWinSize.y());
6764
6765     // 1 shadow ray and 1 secondary ray pew each bounce
6766     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
6767     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
6768   }
6769
6770   return 0;
6771 }
6772
6773 //! Auxiliary function for parsing glsl dump level argument.
6774 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
6775                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
6776 {
6777   TCollection_AsciiString aTypeStr (theArg);
6778   aTypeStr.LowerCase();
6779   if (aTypeStr == "off"
6780    || aTypeStr == "0")
6781   {
6782     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6783   }
6784   else if (aTypeStr == "short")
6785   {
6786     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
6787   }
6788   else if (aTypeStr == "full"
6789         || aTypeStr == "1")
6790   {
6791     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6792   }
6793   else
6794   {
6795     return Standard_False;
6796   }
6797   return Standard_True;
6798 }
6799
6800 //==============================================================================
6801 //function : VGlDebug
6802 //purpose  :
6803 //==============================================================================
6804
6805 static int VGlDebug (Draw_Interpretor& theDI,
6806                      Standard_Integer  theArgNb,
6807                      const char**      theArgVec)
6808 {
6809   Handle(OpenGl_GraphicDriver) aDriver;
6810   Handle(V3d_View) aView = ViewerTest::CurrentView();
6811   if (!aView.IsNull())
6812   {
6813     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
6814   }
6815   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
6816   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
6817
6818   if (theArgNb < 2)
6819   {
6820     TCollection_AsciiString aDebActive, aSyncActive;
6821     if (aCaps == NULL)
6822     {
6823       aCaps = aDefCaps;
6824     }
6825     else
6826     {
6827       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
6828                                                                   "GL_ARB_debug_output");
6829       aDebActive = isActive ? " (active)" : " (inactive)";
6830       if (isActive)
6831       {
6832         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
6833         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
6834       }
6835     }
6836
6837     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
6838       + "glslSourceCode: "
6839       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
6840          ? "Off"
6841          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
6842           ? "Short"
6843           : "Full")
6844       + "\n";
6845     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
6846           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
6847           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
6848           << aGlslCodeDebugStatus
6849           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
6850     return 0;
6851   }
6852
6853   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6854   {
6855     Standard_CString        anArg     = theArgVec[anArgIter];
6856     TCollection_AsciiString anArgCase (anArg);
6857     anArgCase.LowerCase();
6858     Standard_Boolean toEnableDebug = Standard_True;
6859     if (anArgCase == "-glsl"
6860      || anArgCase == "-glslwarn"
6861      || anArgCase == "-glslwarns"
6862      || anArgCase == "-glslwarnings")
6863     {
6864       Standard_Boolean toShowWarns = Standard_True;
6865       if (++anArgIter < theArgNb
6866       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
6867       {
6868         --anArgIter;
6869       }
6870       aDefCaps->glslWarnings = toShowWarns;
6871       if (aCaps != NULL)
6872       {
6873         aCaps->glslWarnings = toShowWarns;
6874       }
6875     }
6876     else if (anArgCase == "-extra"
6877           || anArgCase == "-extramsg"
6878           || anArgCase == "-extramessages")
6879     {
6880       Standard_Boolean toShow = Standard_True;
6881       if (++anArgIter < theArgNb
6882       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
6883       {
6884         --anArgIter;
6885       }
6886       aDefCaps->suppressExtraMsg = !toShow;
6887       if (aCaps != NULL)
6888       {
6889         aCaps->suppressExtraMsg = !toShow;
6890       }
6891     }
6892     else if (anArgCase == "-noextra"
6893           || anArgCase == "-noextramsg"
6894           || anArgCase == "-noextramessages")
6895     {
6896       Standard_Boolean toSuppress = Standard_True;
6897       if (++anArgIter < theArgNb
6898       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
6899       {
6900         --anArgIter;
6901       }
6902       aDefCaps->suppressExtraMsg = toSuppress;
6903       if (aCaps != NULL)
6904       {
6905         aCaps->suppressExtraMsg = toSuppress;
6906       }
6907     }
6908     else if (anArgCase == "-sync")
6909     {
6910       Standard_Boolean toSync = Standard_True;
6911       if (++anArgIter < theArgNb
6912       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
6913       {
6914         --anArgIter;
6915       }
6916       aDefCaps->contextSyncDebug = toSync;
6917       if (toSync)
6918       {
6919         aDefCaps->contextDebug = Standard_True;
6920       }
6921     }
6922     else if (anArgCase == "-glslsourcecode"
6923           || anArgCase == "-glslcode")
6924     {
6925       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6926       if (++anArgIter < theArgNb
6927       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
6928       {
6929         --anArgIter;
6930       }
6931       aDefCaps->glslDumpLevel = aGslsDumpLevel;
6932       if (aCaps != NULL)
6933       {
6934         aCaps->glslDumpLevel = aGslsDumpLevel;
6935       }
6936     }
6937     else if (anArgCase == "-debug")
6938     {
6939       if (++anArgIter < theArgNb
6940       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
6941       {
6942         --anArgIter;
6943       }
6944       aDefCaps->contextDebug = toEnableDebug;
6945     }
6946     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
6947           && (anArgIter + 1 == theArgNb))
6948     {
6949       // simple alias to turn on almost everything
6950       aDefCaps->contextDebug     = toEnableDebug;
6951       aDefCaps->contextSyncDebug = toEnableDebug;
6952       aDefCaps->glslWarnings     = toEnableDebug;
6953       if (!toEnableDebug)
6954       {
6955         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6956       }
6957       aDefCaps->suppressExtraMsg = !toEnableDebug;
6958       if (aCaps != NULL)
6959       {
6960         aCaps->contextDebug     = toEnableDebug;
6961         aCaps->contextSyncDebug = toEnableDebug;
6962         aCaps->glslWarnings     = toEnableDebug;
6963         if (!toEnableDebug)
6964         {
6965           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6966         }
6967         aCaps->suppressExtraMsg = !toEnableDebug;
6968       }
6969     }
6970     else
6971     {
6972       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
6973       return 1;
6974     }
6975   }
6976
6977   return 0;
6978 }
6979
6980 //==============================================================================
6981 //function : VVbo
6982 //purpose  :
6983 //==============================================================================
6984
6985 static int VVbo (Draw_Interpretor& theDI,
6986                  Standard_Integer  theArgNb,
6987                  const char**      theArgVec)
6988 {
6989   const Standard_Boolean toSet    = (theArgNb > 1);
6990   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
6991   if (toSet)
6992   {
6993     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
6994   }
6995
6996   // get the context
6997   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6998   if (aContextAIS.IsNull())
6999   {
7000     if (!toSet)
7001     {
7002       std::cerr << "No active view!\n";
7003     }
7004     return 1;
7005   }
7006   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
7007   if (!aDriver.IsNull())
7008   {
7009     if (!toSet)
7010     {
7011       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
7012     }
7013     else
7014     {
7015       aDriver->ChangeOptions().vboDisable = toUseVbo;
7016     }
7017   }
7018
7019   return 0;
7020 }
7021
7022 //==============================================================================
7023 //function : VCaps
7024 //purpose  :
7025 //==============================================================================
7026
7027 static int VCaps (Draw_Interpretor& theDI,
7028                   Standard_Integer  theArgNb,
7029                   const char**      theArgVec)
7030 {
7031   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
7032   Handle(OpenGl_GraphicDriver)   aDriver;
7033   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7034   if (!aContext.IsNull())
7035   {
7036     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
7037     aCaps   = &aDriver->ChangeOptions();
7038   }
7039
7040   if (theArgNb < 2)
7041   {
7042     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
7043     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
7044     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
7045     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
7046     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
7047     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
7048     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
7049     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
7050     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
7051     return 0;
7052   }
7053
7054   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
7055   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
7056   {
7057     Standard_CString        anArg     = theArgVec[anArgIter];
7058     TCollection_AsciiString anArgCase (anArg);
7059     anArgCase.LowerCase();
7060     if (anUpdateTool.parseRedrawMode (anArg))
7061     {
7062       continue;
7063     }
7064     else if (anArgCase == "-vsync"
7065           || anArgCase == "-swapinterval")
7066     {
7067       Standard_Boolean toEnable = Standard_True;
7068       if (++anArgIter < theArgNb
7069       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7070       {
7071         --anArgIter;
7072       }
7073       aCaps->swapInterval = toEnable;
7074     }
7075     else if (anArgCase == "-ffp")
7076     {
7077       Standard_Boolean toEnable = Standard_True;
7078       if (++anArgIter < theArgNb
7079       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7080       {
7081         --anArgIter;
7082       }
7083       aCaps->ffpEnable = toEnable;
7084     }
7085     else if (anArgCase == "-polygonmode")
7086     {
7087       Standard_Boolean toEnable = Standard_True;
7088       if (++anArgIter < theArgNb
7089       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7090       {
7091         --anArgIter;
7092       }
7093       aCaps->usePolygonMode = toEnable;
7094     }
7095     else if (anArgCase == "-vbo")
7096     {
7097       Standard_Boolean toEnable = Standard_True;
7098       if (++anArgIter < theArgNb
7099       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7100       {
7101         --anArgIter;
7102       }
7103       aCaps->vboDisable = !toEnable;
7104     }
7105     else if (anArgCase == "-sprite"
7106           || anArgCase == "-sprites")
7107     {
7108       Standard_Boolean toEnable = Standard_True;
7109       if (++anArgIter < theArgNb
7110       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7111       {
7112         --anArgIter;
7113       }
7114       aCaps->pntSpritesDisable = !toEnable;
7115     }
7116     else if (anArgCase == "-softmode")
7117     {
7118       Standard_Boolean toEnable = Standard_True;
7119       if (++anArgIter < theArgNb
7120       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7121       {
7122         --anArgIter;
7123       }
7124       aCaps->contextNoAccel = toEnable;
7125     }
7126     else if (anArgCase == "-winbuffer"
7127           || anArgCase == "-windowbuffer"
7128           || anArgCase == "-usewinbuffer"
7129           || anArgCase == "-usewindowbuffer"
7130           || anArgCase == "-usesystembuffer")
7131     {
7132       Standard_Boolean toEnable = Standard_True;
7133       if (++anArgIter < theArgNb
7134       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7135       {
7136         --anArgIter;
7137       }
7138       aCaps->useSystemBuffer = toEnable;
7139     }
7140     else if (anArgCase == "-accel"
7141           || anArgCase == "-acceleration")
7142     {
7143       Standard_Boolean toEnable = Standard_True;
7144       if (++anArgIter < theArgNb
7145       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7146       {
7147         --anArgIter;
7148       }
7149       aCaps->contextNoAccel = !toEnable;
7150     }
7151     else if (anArgCase == "-compat"
7152           || anArgCase == "-compatprofile"
7153           || anArgCase == "-compatible"
7154           || anArgCase == "-compatibleprofile")
7155     {
7156       Standard_Boolean toEnable = Standard_True;
7157       if (++anArgIter < theArgNb
7158       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7159       {
7160         --anArgIter;
7161       }
7162       aCaps->contextCompatible = toEnable;
7163       if (!aCaps->contextCompatible)
7164       {
7165         aCaps->ffpEnable = Standard_False;
7166       }
7167     }
7168     else if (anArgCase == "-core"
7169           || anArgCase == "-coreprofile")
7170     {
7171       Standard_Boolean toEnable = Standard_True;
7172       if (++anArgIter < theArgNb
7173       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7174       {
7175         --anArgIter;
7176       }
7177       aCaps->contextCompatible = !toEnable;
7178       if (!aCaps->contextCompatible)
7179       {
7180         aCaps->ffpEnable = Standard_False;
7181       }
7182     }
7183     else if (anArgCase == "-stereo"
7184           || anArgCase == "-quadbuffer")
7185     {
7186       Standard_Boolean toEnable = Standard_True;
7187       if (++anArgIter < theArgNb
7188       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7189       {
7190         --anArgIter;
7191       }
7192       aCaps->contextStereo = toEnable;
7193     }
7194     else
7195     {
7196       std::cout << "Error: unknown argument '" << anArg << "'\n";
7197       return 1;
7198     }
7199   }
7200   if (aCaps != &ViewerTest_myDefaultCaps)
7201   {
7202     ViewerTest_myDefaultCaps = *aCaps;
7203   }
7204   return 0;
7205 }
7206
7207 //==============================================================================
7208 //function : VMemGpu
7209 //purpose  :
7210 //==============================================================================
7211
7212 static int VMemGpu (Draw_Interpretor& theDI,
7213                     Standard_Integer  theArgNb,
7214                     const char**      theArgVec)
7215 {
7216   // get the context
7217   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
7218   if (aContextAIS.IsNull())
7219   {
7220     std::cerr << "No active view. Please call vinit.\n";
7221     return 1;
7222   }
7223
7224   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
7225   if (aDriver.IsNull())
7226   {
7227     std::cerr << "Graphic driver not available.\n";
7228     return 1;
7229   }
7230
7231   Standard_Size aFreeBytes = 0;
7232   TCollection_AsciiString anInfo;
7233   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
7234   {
7235     std::cerr << "Information not available.\n";
7236     return 1;
7237   }
7238
7239   if (theArgNb > 1 && *theArgVec[1] == 'f')
7240   {
7241     theDI << Standard_Real (aFreeBytes);
7242   }
7243   else
7244   {
7245     theDI << anInfo;
7246   }
7247
7248   return 0;
7249 }
7250
7251 // ==============================================================================
7252 // function : VReadPixel
7253 // purpose  :
7254 // ==============================================================================
7255 static int VReadPixel (Draw_Interpretor& theDI,
7256                        Standard_Integer  theArgNb,
7257                        const char**      theArgVec)
7258 {
7259   // get the active view
7260   Handle(V3d_View) aView = ViewerTest::CurrentView();
7261   if (aView.IsNull())
7262   {
7263     std::cerr << "No active view. Please call vinit.\n";
7264     return 1;
7265   }
7266   else if (theArgNb < 3)
7267   {
7268     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
7269     return 1;
7270   }
7271
7272   Image_Format         aFormat     = Image_Format_RGBA;
7273   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
7274
7275   Standard_Integer aWidth, aHeight;
7276   aView->Window()->Size (aWidth, aHeight);
7277   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
7278   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
7279   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
7280   {
7281     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
7282     return 1;
7283   }
7284
7285   Standard_Boolean toShowName = Standard_False;
7286   Standard_Boolean toShowHls  = Standard_False;
7287   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
7288   {
7289     TCollection_AsciiString aParam (theArgVec[anIter]);
7290     aParam.LowerCase();
7291     if (aParam == "-rgb"
7292      || aParam == "rgb")
7293     {
7294       aFormat     = Image_Format_RGB;
7295       aBufferType = Graphic3d_BT_RGB;
7296     }
7297     else if (aParam == "-hls"
7298           || aParam == "hls")
7299     {
7300       aFormat     = Image_Format_RGB;
7301       aBufferType = Graphic3d_BT_RGB;
7302       toShowHls   = Standard_True;
7303     }
7304     else if (aParam == "-rgbf"
7305           || aParam == "rgbf")
7306     {
7307       aFormat     = Image_Format_RGBF;
7308       aBufferType = Graphic3d_BT_RGB;
7309     }
7310     else if (aParam == "-rgba"
7311           || aParam == "rgba")
7312     {
7313       aFormat     = Image_Format_RGBA;
7314       aBufferType = Graphic3d_BT_RGBA;
7315     }
7316     else if (aParam == "-rgbaf"
7317           || aParam == "rgbaf")
7318     {
7319       aFormat     = Image_Format_RGBAF;
7320       aBufferType = Graphic3d_BT_RGBA;
7321     }
7322     else if (aParam == "-depth"
7323           || aParam == "depth")
7324     {
7325       aFormat     = Image_Format_GrayF;
7326       aBufferType = Graphic3d_BT_Depth;
7327     }
7328     else if (aParam == "-name"
7329           || aParam == "name")
7330     {
7331       toShowName = Standard_True;
7332     }
7333     else
7334     {
7335       std::cout << "Syntax error at '" << aParam << "'\n";
7336     }
7337   }
7338
7339   Image_PixMap anImage;
7340   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
7341   {
7342     std::cerr << "Image allocation failed\n";
7343     return 1;
7344   }
7345   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
7346   {
7347     std::cerr << "Image dump failed\n";
7348     return 1;
7349   }
7350
7351   // redirect possible warning messages that could have been added by ToPixMap
7352   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
7353   // contaminate result of the command
7354   Standard_CString aWarnLog = theDI.Result();
7355   if (aWarnLog != NULL && aWarnLog[0] != '\0')
7356   {
7357     std::cout << aWarnLog << std::endl;
7358   }
7359   theDI.Reset();
7360
7361   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
7362   if (toShowName)
7363   {
7364     if (aBufferType == Graphic3d_BT_RGBA)
7365     {
7366       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
7367     }
7368     else
7369     {
7370       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
7371     }
7372   }
7373   else
7374   {
7375     switch (aBufferType)
7376     {
7377       default:
7378       case Graphic3d_BT_RGB:
7379       {
7380         if (toShowHls)
7381         {
7382           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
7383         }
7384         else
7385         {
7386           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
7387         }
7388         break;
7389       }
7390       case Graphic3d_BT_RGBA:
7391       {
7392         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
7393         break;
7394       }
7395       case Graphic3d_BT_Depth:
7396       {
7397         theDI << aColor.GetRGB().Red();
7398         break;
7399       }
7400     }
7401   }
7402
7403   return 0;
7404 }
7405
7406 //! Auxiliary presentation for an image plane.
7407 class ViewerTest_ImagePrs : public AIS_InteractiveObject
7408 {
7409 public:
7410   //! Main constructor.
7411   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
7412                        const Standard_Real theWidth,
7413                        const Standard_Real theHeight,
7414                        const TCollection_AsciiString& theLabel)
7415   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
7416   {
7417     SetDisplayMode (0);
7418     SetHilightMode (1);
7419     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
7420     {
7421       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
7422       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
7423       Graphic3d_MaterialAspect aMat;
7424       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
7425       aMat.SetAmbient  (1.0);
7426       aMat.SetDiffuse  (1.0);
7427       aMat.SetSpecular (1.0);
7428       aMat.SetEmissive (1.0);
7429       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
7430       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
7431       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
7432       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
7433       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7434       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
7435       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7436       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7437       aFillAspect->SetFrontMaterial (aMat);
7438       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
7439       aFillAspect->SetTextureMapOn();
7440     }
7441     {
7442       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
7443       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
7444       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
7445       myDrawer->SetTextAspect (aTextAspect);
7446     }
7447     {
7448       const gp_Dir aNorm (0.0, 0.0, 1.0);
7449       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
7450       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
7451       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
7452       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
7453       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
7454       myTris->AddEdge (1);
7455       myTris->AddEdge (2);
7456       myTris->AddEdge (3);
7457       myTris->AddEdge (3);
7458       myTris->AddEdge (2);
7459       myTris->AddEdge (4);
7460
7461       myRect = new Graphic3d_ArrayOfPolylines (4);
7462       myRect->AddVertex (myTris->Vertice (1));
7463       myRect->AddVertex (myTris->Vertice (3));
7464       myRect->AddVertex (myTris->Vertice (4));
7465       myRect->AddVertex (myTris->Vertice (2));
7466     }
7467   }
7468
7469   //! Returns TRUE for accepted display modes.
7470   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7471
7472   //! Compute presentation.
7473   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7474   {
7475     switch (theMode)
7476     {
7477       case 0:
7478       {
7479         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7480         aGroup->AddPrimitiveArray (myTris);
7481         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7482         aGroup->AddPrimitiveArray (myRect);
7483         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7484         return;
7485       }
7486       case 1:
7487       {
7488         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7489         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7490         aGroup->AddPrimitiveArray (myRect);
7491         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7492         return;
7493       }
7494     }
7495   }
7496
7497   //! Compute selection.
7498   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7499   {
7500     if (theMode == 0)
7501     {
7502       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7503       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7504       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7505       theSel->Add (aSensitive);
7506     }
7507   }
7508
7509 private:
7510   Handle(Graphic3d_ArrayOfTriangles) myTris;
7511   Handle(Graphic3d_ArrayOfPolylines) myRect;
7512   TCollection_AsciiString myLabel;
7513   Standard_Real myWidth;
7514   Standard_Real myHeight;
7515 };
7516
7517 //==============================================================================
7518 //function : VDiffImage
7519 //purpose  : The draw-command compares two images.
7520 //==============================================================================
7521
7522 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7523 {
7524   if (theArgNb < 3)
7525   {
7526     std::cout << "Syntax error: not enough arguments.\n";
7527     return 1;
7528   }
7529
7530   Standard_Integer anArgIter = 1;
7531   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7532   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7533   TCollection_AsciiString aDiffImagePath;
7534   Standard_Real    aTolColor        = -1.0;
7535   Standard_Integer toBlackWhite     = -1;
7536   Standard_Integer isBorderFilterOn = -1;
7537   Standard_Boolean isOldSyntax = Standard_False;
7538   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7539   for (; anArgIter < theArgNb; ++anArgIter)
7540   {
7541     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7542     anArg.LowerCase();
7543     if (anArgIter + 1 < theArgNb
7544      && (anArg == "-toleranceofcolor"
7545       || anArg == "-tolerancecolor"
7546       || anArg == "-tolerance"
7547       || anArg == "-toler"))
7548     {
7549       aTolColor = Atof (theArgVec[++anArgIter]);
7550       if (aTolColor < 0.0 || aTolColor > 1.0)
7551       {
7552         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7553         return 1;
7554       }
7555     }
7556     else if (anArg == "-blackwhite")
7557     {
7558       Standard_Boolean toEnable = Standard_True;
7559       if (anArgIter + 1 < theArgNb
7560        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7561       {
7562         ++anArgIter;
7563       }
7564       toBlackWhite = toEnable ? 1 : 0;
7565     }
7566     else if (anArg == "-borderfilter")
7567     {
7568       Standard_Boolean toEnable = Standard_True;
7569       if (anArgIter + 1 < theArgNb
7570        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7571       {
7572         ++anArgIter;
7573       }
7574       isBorderFilterOn = toEnable ? 1 : 0;
7575     }
7576     else if (anArg == "-exitonclose")
7577     {
7578       Draw_ToExitOnCloseView = true;
7579       if (anArgIter + 1 < theArgNb
7580        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
7581       {
7582         ++anArgIter;
7583       }
7584     }
7585     else if (anArg == "-closeonescape"
7586           || anArg == "-closeonesc")
7587     {
7588       Draw_ToCloseViewOnEsc = true;
7589       if (anArgIter + 1 < theArgNb
7590        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
7591       {
7592         ++anArgIter;
7593       }
7594     }
7595     else if (anArgIter + 3 < theArgNb
7596           && anArg == "-display")
7597     {
7598       aViewName   = theArgVec[++anArgIter];
7599       aPrsNameRef = theArgVec[++anArgIter];
7600       aPrsNameNew = theArgVec[++anArgIter];
7601       if (anArgIter + 1 < theArgNb
7602       && *theArgVec[anArgIter + 1] != '-')
7603       {
7604         aPrsNameDiff = theArgVec[++anArgIter];
7605       }
7606     }
7607     else if (aTolColor < 0.0
7608           && anArg.IsRealValue())
7609     {
7610       isOldSyntax = Standard_True;
7611       aTolColor = anArg.RealValue();
7612       if (aTolColor < 0.0 || aTolColor > 1.0)
7613       {
7614         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7615         return 1;
7616       }
7617     }
7618     else if (isOldSyntax
7619           && toBlackWhite == -1
7620           && (anArg == "0" || anArg == "1"))
7621     {
7622       toBlackWhite = anArg == "1" ? 1 : 0;
7623     }
7624     else if (isOldSyntax
7625           && isBorderFilterOn == -1
7626           && (anArg == "0" || anArg == "1"))
7627     {
7628       isBorderFilterOn = anArg == "1" ? 1 : 0;
7629     }
7630     else if (aDiffImagePath.IsEmpty())
7631     {
7632       aDiffImagePath = theArgVec[anArgIter];
7633     }
7634     else
7635     {
7636       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7637       return 1;
7638     }
7639   }
7640
7641   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7642   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7643   if (!anImgRef->Load (anImgPathRef))
7644   {
7645     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7646     return 1;
7647   }
7648   if (!anImgNew->Load (anImgPathNew))
7649   {
7650     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7651     return 1;
7652   }
7653
7654   // compare the images
7655   Image_Diff aComparer;
7656   Standard_Integer aDiffColorsNb = -1;
7657   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7658   {
7659     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7660     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7661     aDiffColorsNb = aComparer.Compare();
7662     theDI << aDiffColorsNb << "\n";
7663   }
7664
7665   // save image of difference
7666   Handle(Image_AlienPixMap) aDiff;
7667   if (aDiffColorsNb > 0
7668   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7669   {
7670     aDiff = new Image_AlienPixMap();
7671     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7672     {
7673       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7674       return 1;
7675     }
7676     aComparer.SaveDiffImage (*aDiff);
7677     if (!aDiffImagePath.IsEmpty()
7678      && !aDiff->Save (aDiffImagePath))
7679     {
7680       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7681       return 1;
7682     }
7683   }
7684
7685   if (aViewName.IsEmpty())
7686   {
7687     return 0;
7688   }
7689
7690   ViewerTest_Names aViewNames (aViewName);
7691   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7692   {
7693     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7694     theDI.Eval (aCommand.ToCString());
7695   }
7696
7697   Standard_Integer aPxLeft = 0;
7698   Standard_Integer aPxTop  = 0;
7699   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7700   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7701                               ? int(anImgRef->SizeY() * 2)
7702                               : int(anImgRef->SizeY());
7703   TCollection_AsciiString aDisplayName;
7704   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7705                                                             aViewName, aDisplayName);
7706
7707   Standard_Real aRatio = anImgRef->Ratio();
7708   Standard_Real aSizeX = 1.0;
7709   Standard_Real aSizeY = aSizeX / aRatio;
7710   {
7711     OSD_Path aPath (anImgPathRef);
7712     TCollection_AsciiString aLabelRef;
7713     if (!aPath.Name().IsEmpty())
7714     {
7715       aLabelRef = aPath.Name() + aPath.Extension();
7716     }
7717     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7718
7719     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7720     gp_Trsf aTrsfRef;
7721     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7722     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7723     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7724   }
7725   {
7726     OSD_Path aPath (anImgPathNew);
7727     TCollection_AsciiString aLabelNew;
7728     if (!aPath.Name().IsEmpty())
7729     {
7730       aLabelNew = aPath.Name() + aPath.Extension();
7731     }
7732     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7733
7734     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7735     gp_Trsf aTrsfRef;
7736     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7737     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7738     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7739   }
7740   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7741   if (!aDiff.IsNull())
7742   {
7743     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7744     gp_Trsf aTrsfDiff;
7745     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7746     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7747   }
7748   if (!aPrsNameDiff.IsEmpty())
7749   {
7750     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7751   }
7752   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7753   ViewerTest::CurrentView()->FitAll();
7754   return 0;
7755 }
7756
7757 //=======================================================================
7758 //function : VSelect
7759 //purpose  : Emulates different types of selection by mouse:
7760 //           1) single click selection
7761 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7762 //           3) selection with polygon having corners at
7763 //           pixel positions (x1,y1),...,(xn,yn)
7764 //           4) any of these selections with shift button pressed
7765 //=======================================================================
7766 static Standard_Integer VSelect (Draw_Interpretor& di,
7767                                  Standard_Integer argc,
7768                                  const char ** argv)
7769 {
7770   if(argc < 3)
7771   {
7772     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
7773     return 1;
7774   }
7775
7776   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
7777   if(myAIScontext.IsNull())
7778   {
7779     di << "use 'vinit' command before " << argv[0] << "\n";
7780     return 1;
7781   }
7782
7783   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
7784   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
7785   TCollection_AsciiString anArg;
7786   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
7787   anArg.LowerCase();
7788   if (anArg == "-allowoverlap")
7789   {
7790     Standard_Boolean isValidated = isShiftSelection ? argc == 8
7791       : argc == 7;
7792     if (!isValidated)
7793     {
7794       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
7795       return 1;
7796     }
7797
7798     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
7799     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
7800     aCoordsNb -= 2;
7801   }
7802
7803   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7804   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
7805   if(aCoordsNb == 2)
7806   {
7807     if(isShiftSelection)
7808       aCurrentEventManager->ShiftSelect();
7809     else
7810       aCurrentEventManager->Select();
7811   }
7812   else if(aCoordsNb == 4)
7813   {
7814     if(isShiftSelection)
7815       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
7816     else
7817       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
7818   }
7819   else
7820   {
7821     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
7822
7823     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
7824       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
7825
7826     if(isShiftSelection)
7827       aCurrentEventManager->ShiftSelect(aPolyline);
7828     else
7829       aCurrentEventManager->Select(aPolyline);
7830   }
7831   return 0;
7832 }
7833
7834 //=======================================================================
7835 //function : VMoveTo
7836 //purpose  : Emulates cursor movement to defined pixel position
7837 //=======================================================================
7838 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7839                                 Standard_Integer theNbArgs,
7840                                 const char**     theArgVec)
7841 {
7842   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7843   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7844   if (aContext.IsNull())
7845   {
7846     std::cout << "Error: no active View\n";
7847     return 1;
7848   }
7849
7850   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7851   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7852   {
7853     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7854     anArgStr.LowerCase();
7855     if (anArgStr == "-reset"
7856      || anArgStr == "-clear")
7857     {
7858       if (anArgIter + 1 < theNbArgs)
7859       {
7860         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7861         return 1;
7862       }
7863
7864       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7865                                        && aContext->CurrentViewer()->GridEcho();
7866       if (toEchoGrid)
7867       {
7868         aContext->CurrentViewer()->HideGridEcho (aView);
7869       }
7870       if (aContext->ClearDetected() || toEchoGrid)
7871       {
7872         aContext->CurrentViewer()->RedrawImmediate();
7873       }
7874       return 0;
7875     }
7876     else if (aMousePos.x() == IntegerLast()
7877           && anArgStr.IsIntegerValue())
7878     {
7879       aMousePos.x() = anArgStr.IntegerValue();
7880     }
7881     else if (aMousePos.y() == IntegerLast()
7882           && anArgStr.IsIntegerValue())
7883     {
7884       aMousePos.y() = anArgStr.IntegerValue();
7885     }
7886     else
7887     {
7888       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7889       return 1;
7890     }
7891   }
7892
7893   if (aMousePos.x() == IntegerLast()
7894    || aMousePos.y() == IntegerLast())
7895   {
7896     std::cout << "Syntax error: wrong number of arguments\n";
7897     return 1;
7898   }
7899
7900   ViewerTest::CurrentEventManager()->MoveTo (aMousePos.x(), aMousePos.y());
7901   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7902   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7903   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7904   {
7905     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7906     {
7907       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7908       break;
7909     }
7910   }
7911   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7912   return 0;
7913 }
7914
7915 namespace
7916 {
7917   //! Global map storing all animations registered in ViewerTest.
7918   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7919
7920   //! The animation calling the Draw Harness command.
7921   class ViewerTest_AnimationProc : public AIS_Animation
7922   {
7923   public:
7924
7925     //! Main constructor.
7926     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7927                               Draw_Interpretor* theDI,
7928                               const TCollection_AsciiString& theCommand)
7929     : AIS_Animation (theAnimationName),
7930       myDrawInter(theDI),
7931       myCommand  (theCommand)
7932     {
7933       //
7934     }
7935
7936   protected:
7937
7938     //! Evaluate the command.
7939     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7940     {
7941       TCollection_AsciiString aCmd = myCommand;
7942       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7943       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7944       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7945       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7946       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7947       myDrawInter->Eval (aCmd.ToCString());
7948     }
7949
7950     //! Find the keyword in the command and replace it with value.
7951     //! @return the position of the keyword to pass value
7952     void replace (TCollection_AsciiString&       theCmd,
7953                   const TCollection_AsciiString& theKey,
7954                   const TCollection_AsciiString& theVal)
7955     {
7956       TCollection_AsciiString aCmd (theCmd);
7957       aCmd.LowerCase();
7958       const Standard_Integer aPos = aCmd.Search (theKey);
7959       if (aPos == -1)
7960       {
7961         return;
7962       }
7963
7964       TCollection_AsciiString aPart1, aPart2;
7965       Standard_Integer aPart1To = aPos - 1;
7966       if (aPart1To >= 1
7967        && aPart1To <= theCmd.Length())
7968       {
7969         aPart1 = theCmd.SubString (1, aPart1To);
7970       }
7971
7972       Standard_Integer aPart2From = aPos + theKey.Length();
7973       if (aPart2From >= 1
7974        && aPart2From <= theCmd.Length())
7975       {
7976         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7977       }
7978
7979       theCmd = aPart1 + theVal + aPart2;
7980     }
7981
7982   protected:
7983
7984     Draw_Interpretor*       myDrawInter;
7985     TCollection_AsciiString myCommand;
7986
7987   };
7988
7989   //! Replace the animation with the new one.
7990   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7991                                 Handle(AIS_Animation)&       theAnimation,
7992                                 const Handle(AIS_Animation)& theAnimationNew)
7993   {
7994     theAnimationNew->CopyFrom (theAnimation);
7995     if (!theParentAnimation.IsNull())
7996     {
7997       theParentAnimation->Replace (theAnimation, theAnimationNew);
7998     }
7999     else
8000     {
8001       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
8002       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
8003     }
8004     theAnimation = theAnimationNew;
8005   }
8006
8007   //! Parse the point.
8008   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
8009   {
8010     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
8011     if (!anXYZ[0].IsRealValue()
8012      || !anXYZ[1].IsRealValue()
8013      || !anXYZ[2].IsRealValue())
8014     {
8015       return Standard_False;
8016     }
8017
8018     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
8019     return Standard_True;
8020   }
8021
8022   //! Parse the quaternion.
8023   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
8024   {
8025     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
8026     if (!anXYZW[0].IsRealValue()
8027      || !anXYZW[1].IsRealValue()
8028      || !anXYZW[2].IsRealValue()
8029      || !anXYZW[3].IsRealValue())
8030     {
8031       return Standard_False;
8032     }
8033
8034     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
8035     return Standard_True;
8036   }
8037
8038   //! Auxiliary class for flipping image upside-down.
8039   class ImageFlipper
8040   {
8041   public:
8042
8043     //! Empty constructor.
8044     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
8045
8046     //! Perform flipping.
8047     Standard_Boolean FlipY (Image_PixMap& theImage)
8048     {
8049       if (theImage.IsEmpty()
8050        || theImage.SizeX() == 0
8051        || theImage.SizeY() == 0)
8052       {
8053         return Standard_False;
8054       }
8055
8056       const Standard_Size aRowSize = theImage.SizeRowBytes();
8057       if (myTmp.Size() < aRowSize
8058       && !myTmp.Allocate (aRowSize))
8059       {
8060         return Standard_False;
8061       }
8062
8063       // for odd height middle row should be left as is
8064       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
8065       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
8066       {
8067         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
8068         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
8069         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
8070         memcpy (aTop,               aBot,         aRowSize);
8071         memcpy (aBot,               myTmp.Data(), aRowSize);
8072       }
8073       return Standard_True;
8074     }
8075
8076   private:
8077     NCollection_Buffer myTmp;
8078   };
8079
8080 }
8081
8082 //=================================================================================================
8083 //function : VViewParams
8084 //purpose  : Gets or sets AIS View characteristics
8085 //=================================================================================================
8086 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8087 {
8088   Handle(V3d_View) aView = ViewerTest::CurrentView();
8089   if (aView.IsNull())
8090   {
8091     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
8092     return 1;
8093   }
8094
8095   Standard_Boolean toSetProj     = Standard_False;
8096   Standard_Boolean toSetUp       = Standard_False;
8097   Standard_Boolean toSetAt       = Standard_False;
8098   Standard_Boolean toSetEye      = Standard_False;
8099   Standard_Boolean toSetScale    = Standard_False;
8100   Standard_Boolean toSetSize     = Standard_False;
8101   Standard_Boolean toSetCenter2d = Standard_False;
8102   Standard_Real    aViewScale = aView->Scale();
8103   Standard_Real    aViewSize  = 1.0;
8104   Graphic3d_Vec2i  aCenter2d;
8105   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
8106   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
8107   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
8108   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
8109   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
8110   if (theArgsNb == 1)
8111   {
8112     // print all of the available view parameters
8113     char aText[4096];
8114     Sprintf (aText,
8115              "Scale: %g\n"
8116              "Proj:  %12g %12g %12g\n"
8117              "Up:    %12g %12g %12g\n"
8118              "At:    %12g %12g %12g\n"
8119              "Eye:   %12g %12g %12g\n",
8120               aViewScale,
8121               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
8122               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
8123               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
8124               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
8125     theDi << aText;
8126     return 0;
8127   }
8128
8129   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8130   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8131   {
8132     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8133     anArg.LowerCase();
8134     if (anUpdateTool.parseRedrawMode (anArg))
8135     {
8136       continue;
8137     }
8138     else if (anArg == "-cmd"
8139           || anArg == "-command"
8140           || anArg == "-args")
8141     {
8142       char aText[4096];
8143       Sprintf (aText,
8144                "-scale %g "
8145                "-proj %g %g %g "
8146                "-up %g %g %g "
8147                "-at %g %g %g\n",
8148                 aViewScale,
8149                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
8150                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
8151                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
8152       theDi << aText;
8153     }
8154     else if (anArg == "-scale"
8155           || anArg == "-size")
8156     {
8157       if (anArgIter + 1 < theArgsNb
8158        && *theArgVec[anArgIter + 1] != '-')
8159       {
8160         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
8161         if (aValueArg.IsRealValue())
8162         {
8163           ++anArgIter;
8164           if (anArg == "-scale")
8165           {
8166             toSetScale = Standard_True;
8167             aViewScale = aValueArg.RealValue();
8168           }
8169           else if (anArg == "-size")
8170           {
8171             toSetSize = Standard_True;
8172             aViewSize = aValueArg.RealValue();
8173           }
8174           continue;
8175         }
8176       }
8177       if (anArg == "-scale")
8178       {
8179         theDi << "Scale: " << aView->Scale() << "\n";
8180       }
8181       else if (anArg == "-size")
8182       {
8183         Graphic3d_Vec2d aSizeXY;
8184         aView->Size (aSizeXY.x(), aSizeXY.y());
8185         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
8186       }
8187     }
8188     else if (anArg == "-eye"
8189           || anArg == "-at"
8190           || anArg == "-up"
8191           || anArg == "-proj")
8192     {
8193       if (anArgIter + 3 < theArgsNb)
8194       {
8195         gp_XYZ anXYZ;
8196         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
8197         {
8198           anArgIter += 3;
8199           if (anArg == "-eye")
8200           {
8201             toSetEye = Standard_True;
8202             aViewEye = anXYZ;
8203           }
8204           else if (anArg == "-at")
8205           {
8206             toSetAt = Standard_True;
8207             aViewAt = anXYZ;
8208           }
8209           else if (anArg == "-up")
8210           {
8211             toSetUp = Standard_True;
8212             aViewUp = anXYZ;
8213           }
8214           else if (anArg == "-proj")
8215           {
8216             toSetProj = Standard_True;
8217             aViewProj = anXYZ;
8218           }
8219           continue;
8220         }
8221       }
8222
8223       if (anArg == "-eye")
8224       {
8225         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
8226       }
8227       else if (anArg == "-at")
8228       {
8229         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
8230       }
8231       else if (anArg == "-up")
8232       {
8233         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
8234       }
8235       else if (anArg == "-proj")
8236       {
8237         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
8238       }
8239     }
8240     else if (anArg == "-center")
8241     {
8242       if (anArgIter + 2 < theArgsNb)
8243       {
8244         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
8245         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
8246         if (anX.IsIntegerValue()
8247          && anY.IsIntegerValue())
8248         {
8249           toSetCenter2d = Standard_True;
8250           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
8251         }
8252       }
8253     }
8254     else
8255     {
8256       std::cout << "Syntax error at '" << anArg << "'\n";
8257       return 1;
8258     }
8259   }
8260
8261   // change view parameters in proper order
8262   if (toSetScale)
8263   {
8264     aView->SetScale (aViewScale);
8265   }
8266   if (toSetSize)
8267   {
8268     aView->SetSize (aViewSize);
8269   }
8270   if (toSetEye)
8271   {
8272     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
8273   }
8274   if (toSetAt)
8275   {
8276     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
8277   }
8278   if (toSetProj)
8279   {
8280     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
8281   }
8282   if (toSetUp)
8283   {
8284     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
8285   }
8286   if (toSetCenter2d)
8287   {
8288     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
8289   }
8290
8291   return 0;
8292 }
8293
8294 //==============================================================================
8295 //function : V2DMode
8296 //purpose  :
8297 //==============================================================================
8298 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
8299 {
8300   bool is2dMode = true;
8301   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
8302   if (aV3dView.IsNull())
8303   {
8304     std::cout << "Error: no active view.\n";
8305     return 1;
8306   }
8307   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8308   {
8309     const TCollection_AsciiString anArg = theArgVec[anArgIt];
8310     TCollection_AsciiString anArgCase = anArg;
8311     anArgCase.LowerCase();
8312     if (anArgIt + 1 < theArgsNb
8313      && anArgCase == "-name")
8314     {
8315       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
8316       TCollection_AsciiString aViewName = aViewNames.GetViewName();
8317       if (!ViewerTest_myViews.IsBound1 (aViewName))
8318       {
8319         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
8320         return 1;
8321       }
8322       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
8323     }
8324     else if (anArgCase == "-mode")
8325     {
8326       if (anArgIt + 1 < theArgsNb
8327        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
8328       {
8329         ++anArgIt;
8330       }
8331     }
8332     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
8333     {
8334       //
8335     }
8336     else
8337     {
8338       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
8339       return 1;
8340     }
8341   }
8342
8343   aV3dView->SetView2DMode (is2dMode);
8344   return 0;
8345 }
8346
8347 //==============================================================================
8348 //function : VAnimation
8349 //purpose  :
8350 //==============================================================================
8351 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
8352                                     Standard_Integer  theArgNb,
8353                                     const char**      theArgVec)
8354 {
8355   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
8356   if (theArgNb < 2)
8357   {
8358     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
8359          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
8360     {
8361       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
8362     }
8363     return 0;
8364   }
8365   if (aCtx.IsNull())
8366   {
8367     std::cout << "Error: no active view\n";
8368     return 1;
8369   }
8370
8371   Standard_Integer anArgIter = 1;
8372   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
8373   if (aNameArg.IsEmpty())
8374   {
8375     std::cout << "Syntax error: animation name is not defined.\n";
8376     return 1;
8377   }
8378
8379   TCollection_AsciiString aNameArgLower = aNameArg;
8380   aNameArgLower.LowerCase();
8381   if (aNameArgLower == "-reset"
8382    || aNameArgLower == "-clear")
8383   {
8384     ViewerTest_AnimationTimelineMap.Clear();
8385     return 0;
8386   }
8387   else if (aNameArg.Value (1) == '-')
8388   {
8389     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
8390     return 1;
8391   }
8392
8393   const char* aNameSplitter = "/";
8394   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
8395   if (aSplitPos == -1)
8396   {
8397     aNameSplitter = ".";
8398     aSplitPos = aNameArg.Search (aNameSplitter);
8399   }
8400
8401   // find existing or create a new animation by specified name within syntax "parent.child".
8402   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
8403   for (; !aNameArg.IsEmpty();)
8404   {
8405     TCollection_AsciiString aNameParent;
8406     if (aSplitPos != -1)
8407     {
8408       if (aSplitPos == aNameArg.Length())
8409       {
8410         std::cout << "Syntax error: animation name is not defined.\n";
8411         return 1;
8412       }
8413
8414       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
8415       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
8416
8417       aSplitPos = aNameArg.Search (aNameSplitter);
8418     }
8419     else
8420     {
8421       aNameParent = aNameArg;
8422       aNameArg.Clear();
8423     }
8424
8425     if (anAnimation.IsNull())
8426     {
8427       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
8428       {
8429         anAnimation = new AIS_Animation (aNameParent);
8430         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8431       }
8432       aRootAnimation = anAnimation;
8433     }
8434     else
8435     {
8436       aParentAnimation = anAnimation;
8437       anAnimation = aParentAnimation->Find (aNameParent);
8438       if (anAnimation.IsNull())
8439       {
8440         anAnimation = new AIS_Animation (aNameParent);
8441         aParentAnimation->Add (anAnimation);
8442       }
8443     }
8444   }
8445
8446   if (anArgIter >= theArgNb)
8447   {
8448     // just print the list of children
8449     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8450     {
8451       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8452     }
8453     return 0;
8454   }
8455
8456   // animation parameters
8457   Standard_Boolean toPlay = Standard_False;
8458   Standard_Real aPlaySpeed     = 1.0;
8459   Standard_Real aPlayStartTime = anAnimation->StartPts();
8460   Standard_Real aPlayDuration  = anAnimation->Duration();
8461   Standard_Boolean isFreeCamera = Standard_False;
8462   Standard_Boolean isLockLoop   = Standard_False;
8463
8464   // video recording parameters
8465   TCollection_AsciiString aRecFile;
8466   Image_VideoParams aRecParams;
8467
8468   Handle(V3d_View) aView = ViewerTest::CurrentView();
8469   for (; anArgIter < theArgNb; ++anArgIter)
8470   {
8471     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8472     anArg.LowerCase();
8473     // general options
8474     if (anArg == "-reset"
8475      || anArg == "-clear")
8476     {
8477       anAnimation->Clear();
8478     }
8479     else if (anArg == "-remove"
8480           || anArg == "-del"
8481           || anArg == "-delete")
8482     {
8483       if (!aParentAnimation.IsNull())
8484       {
8485         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8486       }
8487       else
8488       {
8489         aParentAnimation->Remove (anAnimation);
8490       }
8491     }
8492     // playback options
8493     else if (anArg == "-play")
8494     {
8495       toPlay = Standard_True;
8496       if (++anArgIter < theArgNb)
8497       {
8498         if (*theArgVec[anArgIter] == '-')
8499         {
8500           --anArgIter;
8501           continue;
8502         }
8503         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8504
8505         if (++anArgIter < theArgNb)
8506         {
8507           if (*theArgVec[anArgIter] == '-')
8508           {
8509             --anArgIter;
8510             continue;
8511           }
8512           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8513         }
8514       }
8515     }
8516     else if (anArg == "-resume")
8517     {
8518       toPlay = Standard_True;
8519       aPlayStartTime = anAnimation->ElapsedTime();
8520       if (++anArgIter < theArgNb)
8521       {
8522         if (*theArgVec[anArgIter] == '-')
8523         {
8524           --anArgIter;
8525           continue;
8526         }
8527
8528         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8529       }
8530     }
8531     else if (anArg == "-playspeed"
8532           || anArg == "-speed")
8533     {
8534       if (++anArgIter >= theArgNb)
8535       {
8536         std::cout << "Syntax error at " << anArg << ".\n";
8537         return 1;
8538       }
8539       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8540     }
8541     else if (anArg == "-lock"
8542           || anArg == "-lockloop"
8543           || anArg == "-playlockloop")
8544     {
8545       isLockLoop = Standard_True;
8546     }
8547     else if (anArg == "-freecamera"
8548           || anArg == "-playfreecamera"
8549           || anArg == "-freelook")
8550     {
8551       isFreeCamera = Standard_True;
8552     }
8553     // video recodring options
8554     else if (anArg == "-rec"
8555           || anArg == "-record")
8556     {
8557       if (++anArgIter >= theArgNb)
8558       {
8559         std::cout << "Syntax error at " << anArg << ".\n";
8560         return 1;
8561       }
8562
8563       aRecFile = theArgVec[anArgIter];
8564       if (aRecParams.FpsNum <= 0)
8565       {
8566         aRecParams.FpsNum = 24;
8567       }
8568
8569       if (anArgIter + 2 < theArgNb
8570       && *theArgVec[anArgIter + 1] != '-'
8571       && *theArgVec[anArgIter + 2] != '-')
8572       {
8573         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8574         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8575         if (aWidthArg .IsIntegerValue()
8576          && aHeightArg.IsIntegerValue())
8577         {
8578           aRecParams.Width  = aWidthArg .IntegerValue();
8579           aRecParams.Height = aHeightArg.IntegerValue();
8580           anArgIter += 2;
8581         }
8582       }
8583     }
8584     else if (anArg == "-fps")
8585     {
8586       if (++anArgIter >= theArgNb)
8587       {
8588         std::cout << "Syntax error at " << anArg << ".\n";
8589         return 1;
8590       }
8591
8592       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8593       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8594       if (aSplitIndex == 0)
8595       {
8596         aRecParams.FpsNum = aFpsArg.IntegerValue();
8597       }
8598       else
8599       {
8600         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8601         aFpsArg.Split (aFpsArg.Length() - 1);
8602         const TCollection_AsciiString aNumStr = aFpsArg;
8603         aRecParams.FpsNum = aNumStr.IntegerValue();
8604         aRecParams.FpsDen = aDenStr.IntegerValue();
8605         if (aRecParams.FpsDen < 1)
8606         {
8607           std::cout << "Syntax error at " << anArg << ".\n";
8608           return 1;
8609         }
8610       }
8611     }
8612     else if (anArg == "-format")
8613     {
8614       if (++anArgIter >= theArgNb)
8615       {
8616         std::cout << "Syntax error at " << anArg << ".\n";
8617         return 1;
8618       }
8619       aRecParams.Format = theArgVec[anArgIter];
8620     }
8621     else if (anArg == "-pix_fmt"
8622           || anArg == "-pixfmt"
8623           || anArg == "-pixelformat")
8624     {
8625       if (++anArgIter >= theArgNb)
8626       {
8627         std::cout << "Syntax error at " << anArg << ".\n";
8628         return 1;
8629       }
8630       aRecParams.PixelFormat = theArgVec[anArgIter];
8631     }
8632     else if (anArg == "-codec"
8633           || anArg == "-vcodec"
8634           || anArg == "-videocodec")
8635     {
8636       if (++anArgIter >= theArgNb)
8637       {
8638         std::cout << "Syntax error at " << anArg << ".\n";
8639         return 1;
8640       }
8641       aRecParams.VideoCodec = theArgVec[anArgIter];
8642     }
8643     else if (anArg == "-crf"
8644           || anArg == "-preset"
8645           || anArg == "-qp")
8646     {
8647       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8648       if (++anArgIter >= theArgNb)
8649       {
8650         std::cout << "Syntax error at " << anArg << ".\n";
8651         return 1;
8652       }
8653
8654       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8655     }
8656     // animation definition options
8657     else if (anArg == "-start"
8658           || anArg == "-starttime"
8659           || anArg == "-startpts")
8660     {
8661       if (++anArgIter >= theArgNb)
8662       {
8663         std::cout << "Syntax error at " << anArg << ".\n";
8664         return 1;
8665       }
8666
8667       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8668       aRootAnimation->UpdateTotalDuration();
8669     }
8670     else if (anArg == "-end"
8671           || anArg == "-endtime"
8672           || anArg == "-endpts")
8673     {
8674       if (++anArgIter >= theArgNb)
8675       {
8676         std::cout << "Syntax error at " << anArg << ".\n";
8677         return 1;
8678       }
8679
8680       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8681       aRootAnimation->UpdateTotalDuration();
8682     }
8683     else if (anArg == "-dur"
8684           || anArg == "-duration")
8685     {
8686       if (++anArgIter >= theArgNb)
8687       {
8688         std::cout << "Syntax error at " << anArg << ".\n";
8689         return 1;
8690       }
8691
8692       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8693       aRootAnimation->UpdateTotalDuration();
8694     }
8695     else if (anArg == "-command"
8696           || anArg == "-cmd"
8697           || anArg == "-invoke"
8698           || anArg == "-eval"
8699           || anArg == "-proc")
8700     {
8701       if (++anArgIter >= theArgNb)
8702       {
8703         std::cout << "Syntax error at " << anArg << ".\n";
8704         return 1;
8705       }
8706
8707       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8708       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8709     }
8710     else if (anArg == "-objecttrsf"
8711           || anArg == "-objectransformation"
8712           || anArg == "-objtransformation"
8713           || anArg == "-objtrsf"
8714           || anArg == "-object"
8715           || anArg == "-obj")
8716     {
8717       if (++anArgIter >= theArgNb)
8718       {
8719         std::cout << "Syntax error at " << anArg << ".\n";
8720         return 1;
8721       }
8722
8723       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8724       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8725       Handle(AIS_InteractiveObject) anObject;
8726       if (!aMapOfAIS.Find2 (anObjName, anObject))
8727       {
8728         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8729         return 1;
8730       }
8731
8732       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8733       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8734       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8735       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8736       Standard_Boolean isTrsfSet = Standard_False;
8737       Standard_Integer aTrsfArgIter = anArgIter + 1;
8738       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8739       {
8740         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8741         aTrsfArg.LowerCase();
8742         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8743         if (aTrsfArg.StartsWith ("-rotation")
8744          || aTrsfArg.StartsWith ("-rot"))
8745         {
8746           isTrsfSet = Standard_True;
8747           if (aTrsfArgIter + 4 >= theArgNb
8748           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8749           {
8750             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8751             return 1;
8752           }
8753           aTrsfArgIter += 4;
8754         }
8755         else if (aTrsfArg.StartsWith ("-location")
8756               || aTrsfArg.StartsWith ("-loc"))
8757         {
8758           isTrsfSet = Standard_True;
8759           if (aTrsfArgIter + 3 >= theArgNb
8760           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8761           {
8762             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8763             return 1;
8764           }
8765           aTrsfArgIter += 3;
8766         }
8767         else if (aTrsfArg.StartsWith ("-scale"))
8768         {
8769           isTrsfSet = Standard_True;
8770           if (++aTrsfArgIter >= theArgNb)
8771           {
8772             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8773             return 1;
8774           }
8775
8776           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8777           if (!aScaleStr.IsRealValue())
8778           {
8779             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8780             return 1;
8781           }
8782           aScales[anIndex] = aScaleStr.RealValue();
8783         }
8784         else
8785         {
8786           anArgIter = aTrsfArgIter - 1;
8787           break;
8788         }
8789       }
8790       if (!isTrsfSet)
8791       {
8792         std::cout << "Syntax error at " << anArg << ".\n";
8793         return 1;
8794       }
8795       else if (aTrsfArgIter >= theArgNb)
8796       {
8797         anArgIter = theArgNb;
8798       }
8799
8800       aTrsfs[0].SetRotation        (aRotQuats[0]);
8801       aTrsfs[1].SetRotation        (aRotQuats[1]);
8802       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8803       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8804       aTrsfs[0].SetScaleFactor     (aScales[0]);
8805       aTrsfs[1].SetScaleFactor     (aScales[1]);
8806
8807       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8808       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8809     }
8810     else if (anArg == "-viewtrsf"
8811           || anArg == "-view")
8812     {
8813       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8814       if (aCamAnimation.IsNull())
8815       {
8816         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8817         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8818       }
8819
8820       Handle(Graphic3d_Camera) aCams[2] =
8821       {
8822         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8823         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8824       };
8825
8826       Standard_Boolean isTrsfSet = Standard_False;
8827       Standard_Integer aViewArgIter = anArgIter + 1;
8828       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8829       {
8830         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8831         aViewArg.LowerCase();
8832         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8833         if (aViewArg.StartsWith ("-scale"))
8834         {
8835           isTrsfSet = Standard_True;
8836           if (++aViewArgIter >= theArgNb)
8837           {
8838             std::cout << "Syntax error at " << anArg << ".\n";
8839             return 1;
8840           }
8841
8842           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8843           if (!aScaleStr.IsRealValue())
8844           {
8845             std::cout << "Syntax error at " << aViewArg << ".\n";
8846             return 1;
8847           }
8848           Standard_Real aScale = aScaleStr.RealValue();
8849           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8850           aCams[anIndex]->SetScale (aScale);
8851         }
8852         else if (aViewArg.StartsWith ("-eye")
8853               || aViewArg.StartsWith ("-center")
8854               || aViewArg.StartsWith ("-at")
8855               || aViewArg.StartsWith ("-up"))
8856         {
8857           isTrsfSet = Standard_True;
8858           gp_XYZ anXYZ;
8859           if (aViewArgIter + 3 >= theArgNb
8860           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8861           {
8862             std::cout << "Syntax error at " << aViewArg << ".\n";
8863             return 1;
8864           }
8865           aViewArgIter += 3;
8866
8867           if (aViewArg.StartsWith ("-eye"))
8868           {
8869             aCams[anIndex]->SetEye (anXYZ);
8870           }
8871           else if (aViewArg.StartsWith ("-center")
8872                 || aViewArg.StartsWith ("-at"))
8873           {
8874             aCams[anIndex]->SetCenter (anXYZ);
8875           }
8876           else if (aViewArg.StartsWith ("-up"))
8877           {
8878             aCams[anIndex]->SetUp (anXYZ);
8879           }
8880         }
8881         else
8882         {
8883           anArgIter = aViewArgIter - 1;
8884           break;
8885         }
8886       }
8887       if (!isTrsfSet)
8888       {
8889         std::cout << "Syntax error at " << anArg << ".\n";
8890         return 1;
8891       }
8892       else if (aViewArgIter >= theArgNb)
8893       {
8894         anArgIter = theArgNb;
8895       }
8896
8897       aCamAnimation->SetCameraStart(aCams[0]);
8898       aCamAnimation->SetCameraEnd  (aCams[1]);
8899     }
8900     else
8901     {
8902       std::cout << "Syntax error at " << anArg << ".\n";
8903       return 1;
8904     }
8905   }
8906
8907   if (!toPlay && aRecFile.IsEmpty())
8908   {
8909     return 0;
8910   }
8911
8912   // Start animation timeline and process frame updating.
8913   TheIsAnimating = Standard_True;
8914   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8915   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8916   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8917   if (isFreeCamera)
8918   {
8919     aView->Camera()->Copy (aCameraBack);
8920   }
8921
8922   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8923   if (aRecParams.FpsNum <= 0)
8924   {
8925     while (!anAnimation->IsStopped())
8926     {
8927       aCameraBack->Copy (aView->Camera());
8928       const Standard_Real aPts = anAnimation->UpdateTimer();
8929       if (isFreeCamera)
8930       {
8931         aView->Camera()->Copy (aCameraBack);
8932       }
8933
8934       if (aPts >= anUpperPts)
8935       {
8936         anAnimation->Pause();
8937         break;
8938       }
8939
8940       if (aView->IsInvalidated())
8941       {
8942         aView->Redraw();
8943       }
8944       else
8945       {
8946         aView->RedrawImmediate();
8947       }
8948
8949       if (!isLockLoop)
8950       {
8951         // handle user events
8952         theDI.Eval ("after 1 set waiter 1");
8953         theDI.Eval ("vwait waiter");
8954       }
8955       if (!TheIsAnimating)
8956       {
8957         anAnimation->Pause();
8958         theDI << aPts;
8959         break;
8960       }
8961     }
8962
8963     if (aView->IsInvalidated())
8964     {
8965       aView->Redraw();
8966     }
8967     else
8968     {
8969       aView->RedrawImmediate();
8970     }
8971   }
8972   else
8973   {
8974     OSD_Timer aPerfTimer;
8975     aPerfTimer.Start();
8976
8977     Handle(Image_VideoRecorder) aRecorder;
8978     ImageFlipper aFlipper;
8979     Handle(Draw_ProgressIndicator) aProgress;
8980     if (!aRecFile.IsEmpty())
8981     {
8982       if (aRecParams.Width  <= 0
8983        || aRecParams.Height <= 0)
8984       {
8985         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8986       }
8987
8988       aRecorder = new Image_VideoRecorder();
8989       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8990       {
8991         std::cout << "Error: failed to open video file for recording\n";
8992         return 0;
8993       }
8994
8995       aProgress = new Draw_ProgressIndicator (theDI, 1);
8996     }
8997
8998     // Manage frame-rated animation here
8999     Standard_Real aPts = aPlayStartTime;
9000     int64_t aNbFrames = 0;
9001     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
9002     Standard_Integer aSecondsProgress = 0;
9003     for (; aPts <= anUpperPts && aPSentry.More();)
9004     {
9005       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
9006       aPts = aPlayStartTime + aRecPts;
9007       ++aNbFrames;
9008       if (!anAnimation->Update (aPts))
9009       {
9010         break;
9011       }
9012
9013       if (!aRecorder.IsNull())
9014       {
9015         V3d_ImageDumpOptions aDumpParams;
9016         aDumpParams.Width          = aRecParams.Width;
9017         aDumpParams.Height         = aRecParams.Height;
9018         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
9019         aDumpParams.StereoOptions  = V3d_SDO_MONO;
9020         aDumpParams.ToAdjustAspect = Standard_True;
9021         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
9022         {
9023           std::cout << "Error: view dump is failed!\n";
9024           return 0;
9025         }
9026         aFlipper.FlipY (aRecorder->ChangeFrame());
9027         if (!aRecorder->PushFrame())
9028         {
9029           return 0;
9030         }
9031       }
9032       else
9033       {
9034         aView->Redraw();
9035       }
9036
9037       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
9038       {
9039         aPSentry.Next();
9040         ++aSecondsProgress;
9041       }
9042     }
9043
9044     aPerfTimer.Stop();
9045     anAnimation->Stop();
9046     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
9047     theDI << "Average FPS: " << aRecFps << "\n"
9048           << "Nb. Frames: "  << Standard_Real(aNbFrames);
9049
9050     aView->Redraw();
9051   }
9052
9053   aView->SetImmediateUpdate (wasImmediateUpdate);
9054   TheIsAnimating = Standard_False;
9055   return 0;
9056 }
9057
9058
9059 //=======================================================================
9060 //function : VChangeSelected
9061 //purpose  : Adds the shape to selection or remove one from it
9062 //=======================================================================
9063 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
9064                                 Standard_Integer argc,
9065                                 const char ** argv)
9066 {
9067   if(argc != 2)
9068   {
9069     di<<"Usage : " << argv[0] << " shape \n";
9070     return 1;
9071   }
9072   //get AIS_Shape:
9073   TCollection_AsciiString aName(argv[1]);
9074   Handle(AIS_InteractiveObject) anAISObject;
9075   if (!GetMapOfAIS().Find2 (aName, anAISObject)
9076     || anAISObject.IsNull())
9077   {
9078     di<<"Use 'vdisplay' before";
9079     return 1;
9080   }
9081
9082   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
9083   return 0;
9084 }
9085
9086 //=======================================================================
9087 //function : VNbSelected
9088 //purpose  : Returns number of selected objects
9089 //=======================================================================
9090 static Standard_Integer VNbSelected (Draw_Interpretor& di,
9091                                 Standard_Integer argc,
9092                                 const char ** argv)
9093 {
9094   if(argc != 1)
9095   {
9096     di << "Usage : " << argv[0] << "\n";
9097     return 1;
9098   }
9099   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9100   if(aContext.IsNull())
9101   {
9102     di << "use 'vinit' command before " << argv[0] << "\n";
9103     return 1;
9104   }
9105   di << aContext->NbSelected() << "\n";
9106   return 0;
9107 }
9108
9109 //=======================================================================
9110 //function : VPurgeDisplay
9111 //purpose  : Switches altialiasing on or off
9112 //=======================================================================
9113 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
9114                                 Standard_Integer argc,
9115                                 const char ** argv)
9116 {
9117   if (argc > 1)
9118   {
9119     di << "Usage : " << argv[0] << "\n";
9120     return 1;
9121   }
9122   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9123   if (aContext.IsNull())
9124   {
9125     di << "use 'vinit' command before " << argv[0] << "\n";
9126     return 1;
9127   }
9128
9129   di << aContext->PurgeDisplay() << "\n";
9130   return 0;
9131 }
9132
9133 //=======================================================================
9134 //function : VSetViewSize
9135 //purpose  :
9136 //=======================================================================
9137 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
9138                                 Standard_Integer argc,
9139                                 const char ** argv)
9140 {
9141   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9142   if(aContext.IsNull())
9143   {
9144     di << "use 'vinit' command before " << argv[0] << "\n";
9145     return 1;
9146   }
9147   if(argc != 2)
9148   {
9149     di<<"Usage : " << argv[0] << " Size\n";
9150     return 1;
9151   }
9152   Standard_Real aSize = Draw::Atof (argv[1]);
9153   if (aSize <= 0.)
9154   {
9155     di<<"Bad Size value  : " << aSize << "\n";
9156     return 1;
9157   }
9158
9159   Handle(V3d_View) aView = ViewerTest::CurrentView();
9160   aView->SetSize(aSize);
9161   return 0;
9162 }
9163
9164 //=======================================================================
9165 //function : VMoveView
9166 //purpose  :
9167 //=======================================================================
9168 static Standard_Integer VMoveView (Draw_Interpretor& di,
9169                                 Standard_Integer argc,
9170                                 const char ** argv)
9171 {
9172   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9173   if(aContext.IsNull())
9174   {
9175     di << "use 'vinit' command before " << argv[0] << "\n";
9176     return 1;
9177   }
9178   if(argc < 4 || argc > 5)
9179   {
9180     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9181     return 1;
9182   }
9183   Standard_Real Dx = Draw::Atof (argv[1]);
9184   Standard_Real Dy = Draw::Atof (argv[2]);
9185   Standard_Real Dz = Draw::Atof (argv[3]);
9186   Standard_Boolean aStart = Standard_True;
9187   if (argc == 5)
9188   {
9189       aStart = (Draw::Atoi (argv[4]) > 0);
9190   }
9191
9192   Handle(V3d_View) aView = ViewerTest::CurrentView();
9193   aView->Move(Dx,Dy,Dz,aStart);
9194   return 0;
9195 }
9196
9197 //=======================================================================
9198 //function : VTranslateView
9199 //purpose  :
9200 //=======================================================================
9201 static Standard_Integer VTranslateView (Draw_Interpretor& di,
9202                                 Standard_Integer argc,
9203                                 const char ** argv)
9204 {
9205   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9206   if(aContext.IsNull())
9207   {
9208     di << "use 'vinit' command before " << argv[0] << "\n";
9209     return 1;
9210   }
9211   if(argc < 4 || argc > 5)
9212   {
9213     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9214     return 1;
9215   }
9216   Standard_Real Dx = Draw::Atof (argv[1]);
9217   Standard_Real Dy = Draw::Atof (argv[2]);
9218   Standard_Real Dz = Draw::Atof (argv[3]);
9219   Standard_Boolean aStart = Standard_True;
9220   if (argc == 5)
9221   {
9222       aStart = (Draw::Atoi (argv[4]) > 0);
9223   }
9224
9225   Handle(V3d_View) aView = ViewerTest::CurrentView();
9226   aView->Translate(Dx,Dy,Dz,aStart);
9227   return 0;
9228 }
9229
9230 //=======================================================================
9231 //function : VTurnView
9232 //purpose  :
9233 //=======================================================================
9234 static Standard_Integer VTurnView (Draw_Interpretor& di,
9235                                 Standard_Integer argc,
9236                                 const char ** argv)
9237 {
9238   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9239   if(aContext.IsNull()) {
9240     di << "use 'vinit' command before " << argv[0] << "\n";
9241     return 1;
9242   }
9243   if(argc < 4 || argc > 5){
9244     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
9245     return 1;
9246   }
9247   Standard_Real Ax = Draw::Atof (argv[1]);
9248   Standard_Real Ay = Draw::Atof (argv[2]);
9249   Standard_Real Az = Draw::Atof (argv[3]);
9250   Standard_Boolean aStart = Standard_True;
9251   if (argc == 5)
9252   {
9253       aStart = (Draw::Atoi (argv[4]) > 0);
9254   }
9255
9256   Handle(V3d_View) aView = ViewerTest::CurrentView();
9257   aView->Turn(Ax,Ay,Az,aStart);
9258   return 0;
9259 }
9260
9261 //==============================================================================
9262 //function : VTextureEnv
9263 //purpose  : ENables or disables environment mapping
9264 //==============================================================================
9265 class OCC_TextureEnv : public Graphic3d_TextureEnv
9266 {
9267 public:
9268   OCC_TextureEnv(const Standard_CString FileName);
9269   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
9270   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
9271                             const Standard_Boolean theModulateFlag,
9272                             const Graphic3d_TypeOfTextureFilter theFilter,
9273                             const Standard_ShortReal theXScale,
9274                             const Standard_ShortReal theYScale,
9275                             const Standard_ShortReal theXShift,
9276                             const Standard_ShortReal theYShift,
9277                             const Standard_ShortReal theAngle);
9278   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
9279 };
9280 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
9281
9282 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
9283   : Graphic3d_TextureEnv(theFileName)
9284 {
9285 }
9286
9287 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
9288   : Graphic3d_TextureEnv(theTexId)
9289 {
9290 }
9291
9292 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
9293                                           const Standard_Boolean theModulateFlag,
9294                                           const Graphic3d_TypeOfTextureFilter theFilter,
9295                                           const Standard_ShortReal theXScale,
9296                                           const Standard_ShortReal theYScale,
9297                                           const Standard_ShortReal theXShift,
9298                                           const Standard_ShortReal theYShift,
9299                                           const Standard_ShortReal theAngle)
9300 {
9301   myParams->SetRepeat     (theRepeatFlag);
9302   myParams->SetModulate   (theModulateFlag);
9303   myParams->SetFilter     (theFilter);
9304   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
9305   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
9306   myParams->SetRotation   (theAngle);
9307 }
9308
9309 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
9310 {
9311   // get the active view
9312   Handle(V3d_View) aView = ViewerTest::CurrentView();
9313   if (aView.IsNull())
9314   {
9315     std::cerr << "No active view. Please call vinit.\n";
9316     return 1;
9317   }
9318
9319   // Checking the input arguments
9320   Standard_Boolean anEnableFlag = Standard_False;
9321   Standard_Boolean isOk         = theArgNb >= 2;
9322   if (isOk)
9323   {
9324     TCollection_AsciiString anEnableOpt(theArgVec[1]);
9325     anEnableFlag = anEnableOpt.IsEqual("on");
9326     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
9327   }
9328   if (anEnableFlag)
9329   {
9330     isOk = (theArgNb == 3 || theArgNb == 11);
9331     if (isOk)
9332     {
9333       TCollection_AsciiString aTextureOpt(theArgVec[2]);
9334       isOk = (!aTextureOpt.IsIntegerValue() ||
9335              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
9336
9337       if (isOk && theArgNb == 11)
9338       {
9339         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
9340                                 aModulateOpt(theArgVec[4]),
9341                                 aFilterOpt  (theArgVec[5]),
9342                                 aSScaleOpt  (theArgVec[6]),
9343                                 aTScaleOpt  (theArgVec[7]),
9344                                 aSTransOpt  (theArgVec[8]),
9345                                 aTTransOpt  (theArgVec[9]),
9346                                 anAngleOpt  (theArgVec[10]);
9347         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
9348                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
9349                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
9350                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
9351                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
9352                 anAngleOpt.IsRealValue());
9353       }
9354     }
9355   }
9356
9357   if (!isOk)
9358   {
9359     std::cerr << "Usage :" << std::endl;
9360     std::cerr << theArgVec[0] << " off" << std::endl;
9361     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;
9362     return 1;
9363   }
9364
9365   if (anEnableFlag)
9366   {
9367     TCollection_AsciiString aTextureOpt(theArgVec[2]);
9368     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
9369                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
9370                                      new OCC_TextureEnv(theArgVec[2]);
9371
9372     if (theArgNb == 11)
9373     {
9374       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
9375       aTexEnv->SetTextureParameters(
9376         aRepeatOpt.  IsEqual("repeat"),
9377         aModulateOpt.IsEqual("modulate"),
9378         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
9379                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
9380                                                                            Graphic3d_TOTF_TRILINEAR,
9381         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
9382         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
9383         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
9384         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
9385         (Standard_ShortReal)Draw::Atof(theArgVec[10])
9386         );
9387     }
9388     aView->SetTextureEnv(aTexEnv);
9389   }
9390   else // Disabling environment mapping
9391   {
9392     Handle(Graphic3d_TextureEnv) aTexture;
9393     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
9394   }
9395
9396   aView->Redraw();
9397   return 0;
9398 }
9399
9400 namespace
9401 {
9402   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
9403
9404   //! Remove registered clipping plane from all views and objects.
9405   static void removePlane (MapOfPlanes& theRegPlanes,
9406                            const TCollection_AsciiString& theName)
9407   {
9408     Handle(Graphic3d_ClipPlane) aClipPlane;
9409     if (!theRegPlanes.Find (theName, aClipPlane))
9410     {
9411       std::cout << "Warning: no such plane.\n";
9412       return;
9413     }
9414
9415     theRegPlanes.UnBind (theName);
9416     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
9417          anIObjIt.More(); anIObjIt.Next())
9418     {
9419       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
9420       aPrs->RemoveClipPlane (aClipPlane);
9421     }
9422
9423     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
9424          aViewIt.More(); aViewIt.Next())
9425     {
9426       const Handle(V3d_View)& aView = aViewIt.Key2();
9427       aView->RemoveClipPlane(aClipPlane);
9428     }
9429
9430     ViewerTest::RedrawAllViews();
9431   }
9432 }
9433
9434 //===============================================================================================
9435 //function : VClipPlane
9436 //purpose  :
9437 //===============================================================================================
9438 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9439 {
9440   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9441   static MapOfPlanes aRegPlanes;
9442
9443   if (theArgsNb < 2)
9444   {
9445     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9446     {
9447       theDi << aPlaneIter.Key() << " ";
9448     }
9449     return 0;
9450   }
9451
9452   TCollection_AsciiString aCommand (theArgVec[1]);
9453   aCommand.LowerCase();
9454   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9455   if (anActiveView.IsNull())
9456   {
9457     std::cout << "Error: no active view.\n";
9458     return 1;
9459   }
9460
9461   // print maximum number of planes for current viewer
9462   if (aCommand == "-maxplanes"
9463    || aCommand == "maxplanes")
9464   {
9465     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9466           << " plane slots provided by driver.\n";
9467     return 0;
9468   }
9469
9470   // create / delete plane instance
9471   if (aCommand == "-create"
9472    || aCommand == "create"
9473    || aCommand == "-delete"
9474    || aCommand == "delete"
9475    || aCommand == "-clone"
9476    || aCommand == "clone")
9477   {
9478     if (theArgsNb < 3)
9479     {
9480       std::cout << "Syntax error: plane name is required.\n";
9481       return 1;
9482     }
9483
9484     Standard_Boolean toCreate = aCommand == "-create"
9485                              || aCommand == "create";
9486     Standard_Boolean toClone  = aCommand == "-clone"
9487                              || aCommand == "clone";
9488     Standard_Boolean toDelete = aCommand == "-delete"
9489                              || aCommand == "delete";
9490     TCollection_AsciiString aPlane (theArgVec[2]);
9491
9492     if (toCreate)
9493     {
9494       if (aRegPlanes.IsBound (aPlane))
9495       {
9496         std::cout << "Warning: existing plane has been overridden.\n";
9497         toDelete = true;
9498       }
9499       else
9500       {
9501         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9502         return 0;
9503       }
9504     }
9505     else if (toClone) // toClone
9506     {
9507       if (!aRegPlanes.IsBound (aPlane))
9508       {
9509         std::cout << "Error: no such plane.\n";
9510         return 1;
9511       }
9512       else if (theArgsNb < 4)
9513       {
9514         std::cout << "Syntax error: enter name for new plane.\n";
9515         return 1;
9516       }
9517
9518       TCollection_AsciiString aClone (theArgVec[3]);
9519       if (aRegPlanes.IsBound (aClone))
9520       {
9521         std::cout << "Error: plane name is in use.\n";
9522         return 1;
9523       }
9524
9525       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9526
9527       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9528       return 0;
9529     }
9530
9531     if (toDelete)
9532     {
9533       if (aPlane == "ALL"
9534        || aPlane == "all"
9535        || aPlane == "*")
9536       {
9537         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9538         {
9539           aPlane = aPlaneIter.Key();
9540           removePlane (aRegPlanes, aPlane);
9541           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9542         }
9543       }
9544       else
9545       {
9546         removePlane (aRegPlanes, aPlane);
9547       }
9548     }
9549
9550     if (toCreate)
9551     {
9552       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9553     }
9554     return 0;
9555   }
9556
9557   // set / unset plane command
9558   if (aCommand == "set"
9559    || aCommand == "unset")
9560   {
9561     if (theArgsNb < 5)
9562     {
9563       std::cout << "Syntax error: need more arguments.\n";
9564       return 1;
9565     }
9566
9567     // redirect to new syntax
9568     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9569     anArgVec.SetValue (1, theArgVec[0]);
9570     anArgVec.SetValue (2, theArgVec[2]);
9571     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9572     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9573     {
9574       anArgVec.SetValue (anIt, theArgVec[anIt]);
9575     }
9576
9577     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9578   }
9579
9580   // change plane command
9581   TCollection_AsciiString aPlaneName;
9582   Handle(Graphic3d_ClipPlane) aClipPlane;
9583   Standard_Integer anArgIter = 0;
9584   if (aCommand == "-change"
9585    || aCommand == "change")
9586   {
9587     // old syntax support
9588     if (theArgsNb < 3)
9589     {
9590       std::cout << "Syntax error: need more arguments.\n";
9591       return 1;
9592     }
9593
9594     anArgIter  = 3;
9595     aPlaneName = theArgVec[2];
9596     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9597     {
9598       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9599       return 1;
9600     }
9601   }
9602   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9603   {
9604     anArgIter  = 2;
9605     aPlaneName = theArgVec[1];
9606   }
9607   else
9608   {
9609     anArgIter  = 2;
9610     aPlaneName = theArgVec[1];
9611     aClipPlane = new Graphic3d_ClipPlane();
9612     aRegPlanes.Bind (aPlaneName, aClipPlane);
9613     theDi << "Created new plane " << aPlaneName << ".\n";
9614   }
9615
9616   if (theArgsNb - anArgIter < 1)
9617   {
9618     std::cout << "Syntax error: need more arguments.\n";
9619     return 1;
9620   }
9621
9622   for (; anArgIter < theArgsNb; ++anArgIter)
9623   {
9624     const char**     aChangeArgs   = theArgVec + anArgIter;
9625     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9626     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9627     aChangeArg.LowerCase();
9628
9629     Standard_Boolean toEnable = Standard_True;
9630     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9631     {
9632       aClipPlane->SetOn (toEnable);
9633     }
9634     else if (aChangeArg.StartsWith ("-equation")
9635           || aChangeArg.StartsWith ("equation"))
9636     {
9637       if (aNbChangeArgs < 5)
9638       {
9639         std::cout << "Syntax error: need more arguments.\n";
9640         return 1;
9641       }
9642
9643       Standard_Integer aSubIndex = 1;
9644       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9645       if (aPrefixLen < aChangeArg.Length())
9646       {
9647         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9648         if (!aSubStr.IsIntegerValue()
9649           || aSubStr.IntegerValue() <= 0)
9650         {
9651           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9652           return 1;
9653         }
9654         aSubIndex = aSubStr.IntegerValue();
9655       }
9656
9657       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9658       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9659       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9660       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9661       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9662       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9663       {
9664         if (aSubPln->ChainNextPlane().IsNull())
9665         {
9666           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9667         }
9668         aSubPln = aSubPln->ChainNextPlane();
9669       }
9670       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9671       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9672       anArgIter += 4;
9673     }
9674     else if ((aChangeArg == "-boxinterior"
9675            || aChangeArg == "-boxint"
9676            || aChangeArg == "-box")
9677             && aNbChangeArgs >= 7)
9678     {
9679       Graphic3d_BndBox3d aBndBox;
9680       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9681       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9682       anArgIter += 6;
9683
9684       Standard_Integer aNbSubPlanes = 6;
9685       const Graphic3d_Vec3d aDirArray[6] =
9686       {
9687         Graphic3d_Vec3d (-1, 0, 0),
9688         Graphic3d_Vec3d ( 1, 0, 0),
9689         Graphic3d_Vec3d ( 0,-1, 0),
9690         Graphic3d_Vec3d ( 0, 1, 0),
9691         Graphic3d_Vec3d ( 0, 0,-1),
9692         Graphic3d_Vec3d ( 0, 0, 1),
9693       };
9694       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9695       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9696       {
9697         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9698         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9699         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9700         if (aSubPlaneIter + 1 == aNbSubPlanes)
9701         {
9702           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9703         }
9704         else
9705         {
9706           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9707         }
9708         aSubPln = aSubPln->ChainNextPlane();
9709       }
9710     }
9711     else if (aChangeArg == "-capping"
9712           || aChangeArg == "capping")
9713     {
9714       if (aNbChangeArgs < 2)
9715       {
9716         std::cout << "Syntax error: need more arguments.\n";
9717         return 1;
9718       }
9719
9720       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9721       {
9722         aClipPlane->SetCapping (toEnable);
9723         anArgIter += 1;
9724       }
9725       else
9726       {
9727         // just skip otherwise (old syntax)
9728       }
9729     }
9730     else if (aChangeArg == "-useobjectmaterial"
9731           || aChangeArg == "-useobjectmat"
9732           || aChangeArg == "-useobjmat"
9733           || aChangeArg == "-useobjmaterial")
9734     {
9735       if (aNbChangeArgs < 2)
9736       {
9737         std::cout << "Syntax error: need more arguments.\n";
9738         return 1;
9739       }
9740
9741       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9742       {
9743         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9744         anArgIter += 1;
9745       }
9746     }
9747     else if (aChangeArg == "-useobjecttexture"
9748           || aChangeArg == "-useobjecttex"
9749           || aChangeArg == "-useobjtexture"
9750           || aChangeArg == "-useobjtex")
9751     {
9752       if (aNbChangeArgs < 2)
9753       {
9754         std::cout << "Syntax error: need more arguments.\n";
9755         return 1;
9756       }
9757
9758       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9759       {
9760         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9761         anArgIter += 1;
9762       }
9763     }
9764     else if (aChangeArg == "-useobjectshader"
9765           || aChangeArg == "-useobjshader")
9766     {
9767       if (aNbChangeArgs < 2)
9768       {
9769         std::cout << "Syntax error: need more arguments.\n";
9770         return 1;
9771       }
9772
9773       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9774       {
9775         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9776         anArgIter += 1;
9777       }
9778     }
9779     else if (aChangeArg == "-color"
9780           || aChangeArg == "color")
9781     {
9782       Quantity_Color aColor;
9783       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9784                                                            aChangeArgs + 1,
9785                                                            aColor);
9786       if (aNbParsed == 0)
9787       {
9788         std::cout << "Syntax error: need more arguments.\n";
9789         return 1;
9790       }
9791
9792       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9793       aMat.SetAmbientColor (aColor);
9794       aMat.SetDiffuseColor (aColor);
9795       aClipPlane->SetCappingMaterial (aMat);
9796       anArgIter += aNbParsed;
9797     }
9798     else if ((aChangeArg == "-transparency"
9799            || aChangeArg == "-transp")
9800           && aNbChangeArgs >= 2)
9801     {
9802       TCollection_AsciiString aValStr (aChangeArgs[1]);
9803       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9804       if (aValStr.IsRealValue())
9805       {
9806         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9807         aMat.SetTransparency ((float )aValStr.RealValue());
9808         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9809         aClipPlane->SetCappingMaterial (aMat);
9810       }
9811       else
9812       {
9813         aValStr.LowerCase();
9814         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9815         if (aValStr == "opaque")
9816         {
9817           aMode = Graphic3d_AlphaMode_Opaque;
9818         }
9819         else if (aValStr == "mask")
9820         {
9821           aMode = Graphic3d_AlphaMode_Mask;
9822         }
9823         else if (aValStr == "blend")
9824         {
9825           aMode = Graphic3d_AlphaMode_Blend;
9826         }
9827         else if (aValStr == "blendauto")
9828         {
9829           aMode = Graphic3d_AlphaMode_BlendAuto;
9830         }
9831         else
9832         {
9833           std::cout << "Syntax error at '" << aValStr << "'\n";
9834           return 1;
9835         }
9836         anAspect->SetAlphaMode (aMode);
9837         aClipPlane->SetCappingAspect (anAspect);
9838       }
9839       anArgIter += 1;
9840     }
9841     else if (aChangeArg == "-texname"
9842           || aChangeArg == "texname")
9843     {
9844       if (aNbChangeArgs < 2)
9845       {
9846         std::cout << "Syntax error: need more arguments.\n";
9847         return 1;
9848       }
9849
9850       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9851       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9852       if (!aTexture->IsDone())
9853       {
9854         aClipPlane->SetCappingTexture (NULL);
9855       }
9856       else
9857       {
9858         aTexture->EnableModulate();
9859         aTexture->EnableRepeat();
9860         aClipPlane->SetCappingTexture (aTexture);
9861       }
9862       anArgIter += 1;
9863     }
9864     else if (aChangeArg == "-texscale"
9865           || aChangeArg == "texscale")
9866     {
9867       if (aClipPlane->CappingTexture().IsNull())
9868       {
9869         std::cout << "Error: no texture is set.\n";
9870         return 1;
9871       }
9872
9873       if (aNbChangeArgs < 3)
9874       {
9875         std::cout << "Syntax error: need more arguments.\n";
9876         return 1;
9877       }
9878
9879       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9880       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9881       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9882       anArgIter += 2;
9883     }
9884     else if (aChangeArg == "-texorigin"
9885           || aChangeArg == "texorigin") // texture origin
9886     {
9887       if (aClipPlane->CappingTexture().IsNull())
9888       {
9889         std::cout << "Error: no texture is set.\n";
9890         return 1;
9891       }
9892
9893       if (aNbChangeArgs < 3)
9894       {
9895         std::cout << "Syntax error: need more arguments.\n";
9896         return 1;
9897       }
9898
9899       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9900       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9901
9902       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9903       anArgIter += 2;
9904     }
9905     else if (aChangeArg == "-texrotate"
9906           || aChangeArg == "texrotate") // texture rotation
9907     {
9908       if (aClipPlane->CappingTexture().IsNull())
9909       {
9910         std::cout << "Error: no texture is set.\n";
9911         return 1;
9912       }
9913
9914       if (aNbChangeArgs < 2)
9915       {
9916         std::cout << "Syntax error: need more arguments.\n";
9917         return 1;
9918       }
9919
9920       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9921       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9922       anArgIter += 1;
9923     }
9924     else if (aChangeArg == "-hatch"
9925           || aChangeArg == "hatch")
9926     {
9927       if (aNbChangeArgs < 2)
9928       {
9929         std::cout << "Syntax error: need more arguments.\n";
9930         return 1;
9931       }
9932
9933       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9934       aHatchStr.LowerCase();
9935       if (aHatchStr == "on")
9936       {
9937         aClipPlane->SetCappingHatchOn();
9938       }
9939       else if (aHatchStr == "off")
9940       {
9941         aClipPlane->SetCappingHatchOff();
9942       }
9943       else
9944       {
9945         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9946       }
9947       anArgIter += 1;
9948     }
9949     else if (aChangeArg == "-delete"
9950           || aChangeArg == "delete")
9951     {
9952       removePlane (aRegPlanes, aPlaneName);
9953       return 0;
9954     }
9955     else if (aChangeArg == "-set"
9956           || aChangeArg == "-unset"
9957           || aChangeArg == "-setoverrideglobal")
9958     {
9959       // set / unset plane command
9960       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9961       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9962       Standard_Integer anIt = 1;
9963       for (; anIt < aNbChangeArgs; ++anIt)
9964       {
9965         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9966         if (anEntityName.IsEmpty()
9967          || anEntityName.Value (1) == '-')
9968         {
9969           break;
9970         }
9971         else if (!toOverrideGlobal
9972                && ViewerTest_myViews.IsBound1 (anEntityName))
9973         {
9974           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9975           if (toSet)
9976           {
9977             aView->AddClipPlane (aClipPlane);
9978           }
9979           else
9980           {
9981             aView->RemoveClipPlane (aClipPlane);
9982           }
9983           continue;
9984         }
9985         else if (GetMapOfAIS().IsBound2 (anEntityName))
9986         {
9987           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9988           if (toSet)
9989           {
9990             aIObj->AddClipPlane (aClipPlane);
9991           }
9992           else
9993           {
9994             aIObj->RemoveClipPlane (aClipPlane);
9995           }
9996           if (!aIObj->ClipPlanes().IsNull())
9997           {
9998             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9999           }
10000         }
10001         else
10002         {
10003           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
10004           return 1;
10005         }
10006       }
10007
10008       if (anIt == 1)
10009       {
10010         // apply to active view
10011         if (toSet)
10012         {
10013           anActiveView->AddClipPlane (aClipPlane);
10014         }
10015         else
10016         {
10017           anActiveView->RemoveClipPlane (aClipPlane);
10018         }
10019       }
10020       else
10021       {
10022         anArgIter = anArgIter + anIt - 1;
10023       }
10024     }
10025     else
10026     {
10027       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
10028       return 1;
10029     }
10030   }
10031
10032   ViewerTest::RedrawAllViews();
10033   return 0;
10034 }
10035
10036 //===============================================================================================
10037 //function : VZRange
10038 //purpose  :
10039 //===============================================================================================
10040 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
10041 {
10042   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
10043
10044   if (aCurrentView.IsNull())
10045   {
10046     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
10047     return 1;
10048   }
10049
10050   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
10051
10052   if (theArgsNb < 2)
10053   {
10054     theDi << "ZNear: " << aCamera->ZNear() << "\n";
10055     theDi << "ZFar: " << aCamera->ZFar() << "\n";
10056     return 0;
10057   }
10058
10059   if (theArgsNb == 3)
10060   {
10061     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
10062     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
10063
10064     if (aNewZNear >= aNewZFar)
10065     {
10066       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
10067       return 1;
10068     }
10069
10070     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
10071     {
10072       std::cout << theArgVec[0] << ": invalid arguments: ";
10073       std::cout << "znear, zfar should be positive for perspective camera.\n";
10074       return 1;
10075     }
10076
10077     aCamera->SetZRange (aNewZNear, aNewZFar);
10078   }
10079   else
10080   {
10081     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
10082     return 1;
10083   }
10084
10085   aCurrentView->Redraw();
10086
10087   return 0;
10088 }
10089
10090 //===============================================================================================
10091 //function : VAutoZFit
10092 //purpose  :
10093 //===============================================================================================
10094 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
10095 {
10096   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
10097
10098   if (aCurrentView.IsNull())
10099   {
10100     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
10101     return 1;
10102   }
10103
10104   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
10105
10106   if (theArgsNb > 3)
10107   {
10108     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
10109     return 1;
10110   }
10111
10112   if (theArgsNb < 2)
10113   {
10114     theDi << "Auto z-fit mode: \n"
10115           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
10116           << "Scale: " << aScale << "\n";
10117     return 0;
10118   }
10119
10120   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
10121
10122   if (theArgsNb >= 3)
10123   {
10124     aScale = Draw::Atoi (theArgVec[2]);
10125   }
10126
10127   aCurrentView->SetAutoZFitMode (isOn, aScale);
10128   aCurrentView->AutoZFit();
10129   aCurrentView->Redraw();
10130
10131   return 0;
10132 }
10133
10134 //! Auxiliary function to print projection type
10135 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
10136 {
10137   switch (theProjType)
10138   {
10139     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
10140     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
10141     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
10142     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
10143     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
10144   }
10145   return "UNKNOWN";
10146 }
10147
10148 //===============================================================================================
10149 //function : VCamera
10150 //purpose  :
10151 //===============================================================================================
10152 static int VCamera (Draw_Interpretor& theDI,
10153                     Standard_Integer  theArgsNb,
10154                     const char**      theArgVec)
10155 {
10156   Handle(V3d_View) aView = ViewerTest::CurrentView();
10157   if (aView.IsNull())
10158   {
10159     std::cout << "Error: no active view.\n";
10160     return 1;
10161   }
10162
10163   Handle(Graphic3d_Camera) aCamera = aView->Camera();
10164   if (theArgsNb < 2)
10165   {
10166     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
10167     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
10168     theDI << "Distance:   " << aCamera->Distance() << "\n";
10169     theDI << "IOD:        " << aCamera->IOD() << "\n";
10170     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
10171     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
10172     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
10173     return 0;
10174   }
10175
10176   TCollection_AsciiString aPrsName;
10177   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10178   {
10179     Standard_CString        anArg = theArgVec[anArgIter];
10180     TCollection_AsciiString anArgCase (anArg);
10181     anArgCase.LowerCase();
10182     if (anArgCase == "-proj"
10183      || anArgCase == "-projection"
10184      || anArgCase == "-projtype"
10185      || anArgCase == "-projectiontype")
10186     {
10187       theDI << projTypeName (aCamera->ProjectionType()) << " ";
10188     }
10189     else if (anArgCase == "-ortho"
10190           || anArgCase == "-orthographic")
10191     {
10192       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
10193     }
10194     else if (anArgCase == "-persp"
10195           || anArgCase == "-perspective"
10196           || anArgCase == "-perspmono"
10197           || anArgCase == "-perspectivemono"
10198           || anArgCase == "-mono")
10199     {
10200       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10201     }
10202     else if (anArgCase == "-stereo"
10203           || anArgCase == "-stereoscopic"
10204           || anArgCase == "-perspstereo"
10205           || anArgCase == "-perspectivestereo")
10206     {
10207       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10208     }
10209     else if (anArgCase == "-left"
10210           || anArgCase == "-lefteye"
10211           || anArgCase == "-monoleft"
10212           || anArgCase == "-monolefteye"
10213           || anArgCase == "-perpsleft"
10214           || anArgCase == "-perpslefteye")
10215     {
10216       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
10217     }
10218     else if (anArgCase == "-right"
10219           || anArgCase == "-righteye"
10220           || anArgCase == "-monoright"
10221           || anArgCase == "-monorighteye"
10222           || anArgCase == "-perpsright")
10223     {
10224       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
10225     }
10226     else if (anArgCase == "-dist"
10227           || anArgCase == "-distance")
10228     {
10229       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10230       if (anArgValue != NULL
10231       && *anArgValue != '-')
10232       {
10233         ++anArgIter;
10234         aCamera->SetDistance (Draw::Atof (anArgValue));
10235         continue;
10236       }
10237       theDI << aCamera->Distance() << " ";
10238     }
10239     else if (anArgCase == "-iod")
10240     {
10241       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10242       if (anArgValue != NULL
10243       && *anArgValue != '-')
10244       {
10245         ++anArgIter;
10246         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
10247         continue;
10248       }
10249       theDI << aCamera->IOD() << " ";
10250     }
10251     else if (anArgCase == "-iodtype")
10252     {
10253       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10254       TCollection_AsciiString anValueCase (anArgValue);
10255       anValueCase.LowerCase();
10256       if (anValueCase == "abs"
10257        || anValueCase == "absolute")
10258       {
10259         ++anArgIter;
10260         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
10261         continue;
10262       }
10263       else if (anValueCase == "rel"
10264             || anValueCase == "relative")
10265       {
10266         ++anArgIter;
10267         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
10268         continue;
10269       }
10270       else if (*anArgValue != '-')
10271       {
10272         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
10273         return 1;
10274       }
10275       switch (aCamera->GetIODType())
10276       {
10277         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
10278         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
10279       }
10280     }
10281     else if (anArgCase == "-zfocus")
10282     {
10283       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10284       if (anArgValue != NULL
10285       && *anArgValue != '-')
10286       {
10287         ++anArgIter;
10288         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
10289         continue;
10290       }
10291       theDI << aCamera->ZFocus() << " ";
10292     }
10293     else if (anArgCase == "-zfocustype")
10294     {
10295       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10296       TCollection_AsciiString anValueCase (anArgValue);
10297       anValueCase.LowerCase();
10298       if (anValueCase == "abs"
10299        || anValueCase == "absolute")
10300       {
10301         ++anArgIter;
10302         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
10303         continue;
10304       }
10305       else if (anValueCase == "rel"
10306             || anValueCase == "relative")
10307       {
10308         ++anArgIter;
10309         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
10310         continue;
10311       }
10312       else if (*anArgValue != '-')
10313       {
10314         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
10315         return 1;
10316       }
10317       switch (aCamera->ZFocusType())
10318       {
10319         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
10320         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
10321       }
10322     }
10323     else if (anArgCase == "-fov"
10324           || anArgCase == "-fovy")
10325     {
10326       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10327       if (anArgValue != NULL
10328       && *anArgValue != '-')
10329       {
10330         ++anArgIter;
10331         aCamera->SetFOVy (Draw::Atof (anArgValue));
10332         continue;
10333       }
10334       theDI << aCamera->FOVy() << " ";
10335     }
10336     else if (aPrsName.IsEmpty()
10337          && !anArgCase.StartsWith ("-"))
10338     {
10339       aPrsName = anArg;
10340     }
10341     else
10342     {
10343       std::cout << "Error: unknown argument '" << anArg << "'\n";
10344       return 1;
10345     }
10346   }
10347
10348   if (aPrsName.IsEmpty()
10349    || theArgsNb > 2)
10350   {
10351     aView->AutoZFit();
10352     aView->Redraw();
10353   }
10354
10355   if (!aPrsName.IsEmpty())
10356   {
10357     Handle(AIS_CameraFrustum) aCameraFrustum;
10358     if (GetMapOfAIS().IsBound2 (aPrsName))
10359     {
10360       // find existing object
10361       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
10362       if (aCameraFrustum.IsNull())
10363       {
10364         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
10365         return 1;
10366       }
10367     }
10368
10369     if (aCameraFrustum.IsNull())
10370     {
10371       aCameraFrustum = new AIS_CameraFrustum();
10372     }
10373     else
10374     {
10375       // not include displayed object of old camera frustum in the new one.
10376       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
10377       aView->ZFitAll();
10378     }
10379     aCameraFrustum->SetCameraFrustum (aView->Camera());
10380
10381     ViewerTest::Display (aPrsName, aCameraFrustum);
10382   }
10383
10384   return 0;
10385 }
10386
10387 //! Parse stereo output mode
10388 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
10389                                          Graphic3d_StereoMode& theMode)
10390 {
10391   TCollection_AsciiString aFlag (theArg);
10392   aFlag.LowerCase();
10393   if (aFlag == "quadbuffer")
10394   {
10395     theMode = Graphic3d_StereoMode_QuadBuffer;
10396   }
10397   else if (aFlag == "anaglyph")
10398   {
10399     theMode = Graphic3d_StereoMode_Anaglyph;
10400   }
10401   else if (aFlag == "row"
10402         || aFlag == "rowinterlaced")
10403   {
10404     theMode = Graphic3d_StereoMode_RowInterlaced;
10405   }
10406   else if (aFlag == "col"
10407         || aFlag == "colinterlaced"
10408         || aFlag == "columninterlaced")
10409   {
10410     theMode = Graphic3d_StereoMode_ColumnInterlaced;
10411   }
10412   else if (aFlag == "chess"
10413         || aFlag == "chessboard")
10414   {
10415     theMode = Graphic3d_StereoMode_ChessBoard;
10416   }
10417   else if (aFlag == "sbs"
10418         || aFlag == "sidebyside")
10419   {
10420     theMode = Graphic3d_StereoMode_SideBySide;
10421   }
10422   else if (aFlag == "ou"
10423         || aFlag == "overunder")
10424   {
10425     theMode = Graphic3d_StereoMode_OverUnder;
10426   }
10427   else if (aFlag == "pageflip"
10428         || aFlag == "softpageflip")
10429   {
10430     theMode = Graphic3d_StereoMode_SoftPageFlip;
10431   }
10432   else
10433   {
10434     return Standard_False;
10435   }
10436   return Standard_True;
10437 }
10438
10439 //! Parse anaglyph filter
10440 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10441                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10442 {
10443   TCollection_AsciiString aFlag (theArg);
10444   aFlag.LowerCase();
10445   if (aFlag == "redcyansimple")
10446   {
10447     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10448   }
10449   else if (aFlag == "redcyan"
10450         || aFlag == "redcyanoptimized")
10451   {
10452     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10453   }
10454   else if (aFlag == "yellowbluesimple")
10455   {
10456     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10457   }
10458   else if (aFlag == "yellowblue"
10459         || aFlag == "yellowblueoptimized")
10460   {
10461     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10462   }
10463   else if (aFlag == "greenmagenta"
10464         || aFlag == "greenmagentasimple")
10465   {
10466     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10467   }
10468   else
10469   {
10470     return Standard_False;
10471   }
10472   return Standard_True;
10473 }
10474
10475 //==============================================================================
10476 //function : VStereo
10477 //purpose  :
10478 //==============================================================================
10479
10480 static int VStereo (Draw_Interpretor& theDI,
10481                     Standard_Integer  theArgNb,
10482                     const char**      theArgVec)
10483 {
10484   Handle(V3d_View) aView = ViewerTest::CurrentView();
10485   if (theArgNb < 2)
10486   {
10487     if (aView.IsNull())
10488     {
10489       std::cout << "Error: no active viewer!\n";
10490       return 0;
10491     }
10492
10493     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10494     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10495     if (isActive)
10496     {
10497       TCollection_AsciiString aMode;
10498       switch (aView->RenderingParams().StereoMode)
10499       {
10500         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10501         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10502         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10503         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10504         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10505         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10506         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10507         case Graphic3d_StereoMode_Anaglyph  :
10508           aMode = "anaglyph";
10509           switch (aView->RenderingParams().AnaglyphFilter)
10510           {
10511             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10512             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10513             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10514             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10515             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10516             default: break;
10517           }
10518         default: break;
10519       }
10520       theDI << "Mode " << aMode << "\n";
10521     }
10522     return 0;
10523   }
10524
10525   Handle(Graphic3d_Camera) aCamera;
10526   Graphic3d_RenderingParams*   aParams   = NULL;
10527   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10528   if (!aView.IsNull())
10529   {
10530     aParams   = &aView->ChangeRenderingParams();
10531     aMode     = aParams->StereoMode;
10532     aCamera   = aView->Camera();
10533   }
10534
10535   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10536   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10537   {
10538     Standard_CString        anArg = theArgVec[anArgIter];
10539     TCollection_AsciiString aFlag (anArg);
10540     aFlag.LowerCase();
10541     if (anUpdateTool.parseRedrawMode (aFlag))
10542     {
10543       continue;
10544     }
10545     else if (aFlag == "0"
10546           || aFlag == "off")
10547     {
10548       if (++anArgIter < theArgNb)
10549       {
10550         std::cout << "Error: wrong number of arguments!\n";
10551         return 1;
10552       }
10553
10554       if (!aCamera.IsNull()
10555        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10556       {
10557         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10558       }
10559       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10560       return 0;
10561     }
10562     else if (aFlag == "1"
10563           || aFlag == "on")
10564     {
10565       if (++anArgIter < theArgNb)
10566       {
10567         std::cout << "Error: wrong number of arguments!\n";
10568         return 1;
10569       }
10570
10571       if (!aCamera.IsNull())
10572       {
10573         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10574       }
10575       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10576       return 0;
10577     }
10578     else if (aFlag == "-reverse"
10579           || aFlag == "-reversed"
10580           || aFlag == "-swap")
10581     {
10582       Standard_Boolean toEnable = Standard_True;
10583       if (++anArgIter < theArgNb
10584       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10585       {
10586         --anArgIter;
10587       }
10588       aParams->ToReverseStereo = toEnable;
10589     }
10590     else if (aFlag == "-noreverse"
10591           || aFlag == "-noswap")
10592     {
10593       Standard_Boolean toDisable = Standard_True;
10594       if (++anArgIter < theArgNb
10595       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10596       {
10597         --anArgIter;
10598       }
10599       aParams->ToReverseStereo = !toDisable;
10600     }
10601     else if (aFlag == "-mode"
10602           || aFlag == "-stereomode")
10603     {
10604       if (++anArgIter >= theArgNb
10605       || !parseStereoMode (theArgVec[anArgIter], aMode))
10606       {
10607         std::cout << "Error: syntax error at '" << anArg << "'\n";
10608         return 1;
10609       }
10610
10611       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10612       {
10613         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10614       }
10615     }
10616     else if (aFlag == "-anaglyph"
10617           || aFlag == "-anaglyphfilter")
10618     {
10619       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10620       if (++anArgIter >= theArgNb
10621       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10622       {
10623         std::cout << "Error: syntax error at '" << anArg << "'\n";
10624         return 1;
10625       }
10626
10627       aMode = Graphic3d_StereoMode_Anaglyph;
10628       aParams->AnaglyphFilter = aFilter;
10629     }
10630     else if (parseStereoMode (anArg, aMode)) // short syntax
10631     {
10632       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10633       {
10634         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10635       }
10636     }
10637     else
10638     {
10639       std::cout << "Error: syntax error at '" << anArg << "'\n";
10640       return 1;
10641     }
10642   }
10643
10644   if (!aView.IsNull())
10645   {
10646     aParams->StereoMode = aMode;
10647     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10648   }
10649   return 0;
10650 }
10651
10652 //===============================================================================================
10653 //function : VDefaults
10654 //purpose  :
10655 //===============================================================================================
10656 static int VDefaults (Draw_Interpretor& theDi,
10657                       Standard_Integer  theArgsNb,
10658                       const char**      theArgVec)
10659 {
10660   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10661   if (aCtx.IsNull())
10662   {
10663     std::cerr << "No active viewer!\n";
10664     return 1;
10665   }
10666
10667   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10668   if (theArgsNb < 2)
10669   {
10670     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10671     {
10672       theDi << "DeflType:           relative\n"
10673             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10674     }
10675     else
10676     {
10677       theDi << "DeflType:           absolute\n"
10678             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10679     }
10680     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10681     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10682     return 0;
10683   }
10684
10685   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10686   {
10687     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10688     anArg.UpperCase();
10689     if (anArg == "-ABSDEFL"
10690      || anArg == "-ABSOLUTEDEFLECTION"
10691      || anArg == "-DEFL"
10692      || anArg == "-DEFLECTION")
10693     {
10694       if (++anArgIter >= theArgsNb)
10695       {
10696         std::cout << "Error: wrong syntax at " << anArg << "\n";
10697         return 1;
10698       }
10699       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10700       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10701     }
10702     else if (anArg == "-RELDEFL"
10703           || anArg == "-RELATIVEDEFLECTION"
10704           || anArg == "-DEVCOEFF"
10705           || anArg == "-DEVIATIONCOEFF"
10706           || anArg == "-DEVIATIONCOEFFICIENT")
10707     {
10708       if (++anArgIter >= theArgsNb)
10709       {
10710         std::cout << "Error: wrong syntax at " << anArg << "\n";
10711         return 1;
10712       }
10713       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10714       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10715     }
10716     else if (anArg == "-ANGDEFL"
10717           || anArg == "-ANGULARDEFL"
10718           || anArg == "-ANGULARDEFLECTION")
10719     {
10720       if (++anArgIter >= theArgsNb)
10721       {
10722         std::cout << "Error: wrong syntax at " << anArg << "\n";
10723         return 1;
10724       }
10725       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10726       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10727     }
10728     else if (anArg == "-AUTOTR"
10729           || anArg == "-AUTOTRIANG"
10730           || anArg == "-AUTOTRIANGULATION")
10731     {
10732       if (++anArgIter >= theArgsNb)
10733       {
10734         std::cout << "Error: wrong syntax at " << anArg << "\n";
10735         return 1;
10736       }
10737       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10738       aValue.LowerCase();
10739       if (aValue == "on"
10740        || aValue == "1")
10741       {
10742         aDefParams->SetAutoTriangulation (Standard_True);
10743       }
10744       else if (aValue == "off"
10745             || aValue == "0")
10746       {
10747         aDefParams->SetAutoTriangulation (Standard_False);
10748       }
10749     }
10750     else
10751     {
10752       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
10753     }
10754   }
10755
10756   return 0;
10757 }
10758
10759 //! Auxiliary method
10760 inline void addLight (const Handle(V3d_Light)& theLightNew,
10761                       const Graphic3d_ZLayerId theLayer,
10762                       const Standard_Boolean   theIsGlobal)
10763 {
10764   if (theLightNew.IsNull())
10765   {
10766     return;
10767   }
10768
10769   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10770   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10771   {
10772     aViewer->AddLight (theLightNew);
10773     if (theIsGlobal)
10774     {
10775       aViewer->SetLightOn (theLightNew);
10776     }
10777     else
10778     {
10779       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10780     }
10781   }
10782   else
10783   {
10784     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10785     if (aSettings.Lights().IsNull())
10786     {
10787       aSettings.SetLights (new Graphic3d_LightSet());
10788     }
10789     aSettings.Lights()->Add (theLightNew);
10790     aViewer->SetZLayerSettings (theLayer, aSettings);
10791   }
10792 }
10793
10794 //! Auxiliary method
10795 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10796 {
10797   TCollection_AsciiString anArgNextCase (theArgNext);
10798   anArgNextCase.UpperCase();
10799   if (anArgNextCase.Length() > 5
10800    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10801   {
10802     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10803   }
10804   else
10805   {
10806     return theArgNext.IntegerValue();
10807   }
10808 }
10809
10810 //===============================================================================================
10811 //function : VLight
10812 //purpose  :
10813 //===============================================================================================
10814 static int VLight (Draw_Interpretor& theDi,
10815                    Standard_Integer  theArgsNb,
10816                    const char**      theArgVec)
10817 {
10818   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10819   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10820   if (aView.IsNull()
10821    || aViewer.IsNull())
10822   {
10823     std::cerr << "No active viewer!\n";
10824     return 1;
10825   }
10826
10827   Standard_Real anXYZ[3]   = {};
10828   Standard_Real anAtten[2] = {};
10829   if (theArgsNb < 2)
10830   {
10831     // print lights info
10832     Standard_Integer aLightId = 0;
10833     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10834     {
10835       Handle(V3d_Light) aLight = aLightIter.Value();
10836       const Quantity_Color aColor = aLight->Color();
10837       theDi << "Light #" << aLightId
10838             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10839             << " [" << aLight->GetId() << "]" << "\n";
10840       switch (aLight->Type())
10841       {
10842         case V3d_AMBIENT:
10843         {
10844           theDi << "  Type:       Ambient\n";
10845           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10846           break;
10847         }
10848         case V3d_DIRECTIONAL:
10849         {
10850           theDi << "  Type:       Directional\n";
10851           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10852           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10853           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10854           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10855           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10856           break;
10857         }
10858         case V3d_POSITIONAL:
10859         {
10860           theDi << "  Type:       Positional\n";
10861           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10862           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10863           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10864           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10865           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10866           aLight->Attenuation (anAtten[0], anAtten[1]);
10867           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10868           break;
10869         }
10870         case V3d_SPOT:
10871         {
10872           theDi << "  Type:       Spot\n";
10873           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10874           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10875           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10876           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10877           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10878           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10879           aLight->Attenuation (anAtten[0], anAtten[1]);
10880           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10881           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
10882           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
10883           break;
10884         }
10885         default:
10886         {
10887           theDi << "  Type:       UNKNOWN\n";
10888           break;
10889         }
10890       }
10891       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10892     }
10893   }
10894
10895   Handle(V3d_Light) aLightNew;
10896   Handle(V3d_Light) aLightOld;
10897   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10898   Standard_Boolean  isGlobal = Standard_True;
10899   Standard_Boolean  toCreate = Standard_False;
10900   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10901   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10902   {
10903     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10904
10905     TCollection_AsciiString aName, aValue;
10906     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10907     TCollection_AsciiString anArgCase (anArg);
10908     anArgCase.UpperCase();
10909     if (anUpdateTool.parseRedrawMode (anArg))
10910     {
10911       continue;
10912     }
10913
10914     if (anArgCase.IsEqual ("NEW")
10915      || anArgCase.IsEqual ("ADD")
10916      || anArgCase.IsEqual ("CREATE")
10917      || anArgCase.IsEqual ("-NEW")
10918      || anArgCase.IsEqual ("-ADD")
10919      || anArgCase.IsEqual ("-CREATE"))
10920     {
10921       toCreate = Standard_True;
10922     }
10923     else if (anArgCase.IsEqual ("-LAYER")
10924           || anArgCase.IsEqual ("-ZLAYER"))
10925     {
10926       if (++anArgIt >= theArgsNb)
10927       {
10928         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10929         return 1;
10930       }
10931
10932       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10933       aValStr.LowerCase();
10934       if (aValStr == "default"
10935        || aValStr == "def")
10936       {
10937         aLayer = Graphic3d_ZLayerId_Default;
10938       }
10939       else if (aValStr == "top")
10940       {
10941         aLayer = Graphic3d_ZLayerId_Top;
10942       }
10943       else if (aValStr == "topmost")
10944       {
10945         aLayer = Graphic3d_ZLayerId_Topmost;
10946       }
10947       else if (aValStr == "toposd"
10948             || aValStr == "osd")
10949       {
10950         aLayer = Graphic3d_ZLayerId_TopOSD;
10951       }
10952       else if (aValStr == "botosd"
10953             || aValStr == "bottom")
10954       {
10955         aLayer = Graphic3d_ZLayerId_BotOSD;
10956       }
10957       else if (aValStr.IsIntegerValue())
10958       {
10959         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10960       }
10961       else
10962       {
10963         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10964         return 1;
10965       }
10966     }
10967     else if (anArgCase.IsEqual ("GLOB")
10968           || anArgCase.IsEqual ("GLOBAL")
10969           || anArgCase.IsEqual ("-GLOB")
10970           || anArgCase.IsEqual ("-GLOBAL"))
10971     {
10972       isGlobal = Standard_True;
10973     }
10974     else if (anArgCase.IsEqual ("LOC")
10975           || anArgCase.IsEqual ("LOCAL")
10976           || anArgCase.IsEqual ("-LOC")
10977           || anArgCase.IsEqual ("-LOCAL"))
10978     {
10979       isGlobal = Standard_False;
10980     }
10981     else if (anArgCase.IsEqual ("DEF")
10982           || anArgCase.IsEqual ("DEFAULTS")
10983           || anArgCase.IsEqual ("-DEF")
10984           || anArgCase.IsEqual ("-DEFAULTS"))
10985     {
10986       toCreate = Standard_False;
10987       aViewer->SetDefaultLights();
10988     }
10989     else if (anArgCase.IsEqual ("CLR")
10990           || anArgCase.IsEqual ("CLEAR")
10991           || anArgCase.IsEqual ("-CLR")
10992           || anArgCase.IsEqual ("-CLEAR"))
10993     {
10994       toCreate = Standard_False;
10995
10996       TColStd_SequenceOfInteger aLayers;
10997       aViewer->GetAllZLayers (aLayers);
10998       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10999       {
11000         if (aLayeriter.Value() == aLayer
11001          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
11002         {
11003           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
11004           aSettings.SetLights (Handle(Graphic3d_LightSet)());
11005           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
11006           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
11007           {
11008             break;
11009           }
11010         }
11011       }
11012
11013       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
11014       {
11015         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
11016         {
11017           Handle(V3d_Light) aLight = aLightIter.Value();
11018           aViewer->DelLight (aLight);
11019           aLightIter = aView->ActiveLightIterator();
11020         }
11021       }
11022     }
11023     else if (anArgCase.IsEqual ("AMB")
11024           || anArgCase.IsEqual ("AMBIENT")
11025           || anArgCase.IsEqual ("AMBLIGHT"))
11026     {
11027       if (!toCreate)
11028       {
11029         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11030         return 1;
11031       }
11032
11033       addLight (aLightNew, aLayer, isGlobal);
11034       toCreate  = Standard_False;
11035       aLightNew = new V3d_AmbientLight();
11036     }
11037     else if (anArgCase.IsEqual ("DIRECTIONAL")
11038           || anArgCase.IsEqual ("DIRLIGHT"))
11039     {
11040       if (!toCreate)
11041       {
11042         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11043         return 1;
11044       }
11045
11046       addLight (aLightNew, aLayer, isGlobal);
11047       toCreate  = Standard_False;
11048       aLightNew = new V3d_DirectionalLight();
11049     }
11050     else if (anArgCase.IsEqual ("SPOT")
11051           || anArgCase.IsEqual ("SPOTLIGHT"))
11052     {
11053       if (!toCreate)
11054       {
11055         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11056         return 1;
11057       }
11058
11059       addLight (aLightNew, aLayer, isGlobal);
11060       toCreate  = Standard_False;
11061       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
11062     }
11063     else if (anArgCase.IsEqual ("POSLIGHT")
11064           || anArgCase.IsEqual ("POSITIONAL"))
11065     {
11066       if (!toCreate)
11067       {
11068         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11069         return 1;
11070       }
11071
11072       addLight (aLightNew, aLayer, isGlobal);
11073       toCreate  = Standard_False;
11074       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
11075     }
11076     else if (anArgCase.IsEqual ("CHANGE")
11077           || anArgCase.IsEqual ("-CHANGE"))
11078     {
11079       if (++anArgIt >= theArgsNb)
11080       {
11081         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11082         return 1;
11083       }
11084
11085       addLight (aLightNew, aLayer, isGlobal);
11086       aLightNew.Nullify();
11087       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
11088       Standard_Integer aLightIt = 0;
11089       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
11090       {
11091         if (aLightIt == aLightId)
11092         {
11093           aLightOld = aLightIter.Value();
11094           break;
11095         }
11096       }
11097
11098       if (aLightOld.IsNull())
11099       {
11100         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
11101         return 1;
11102       }
11103     }
11104     else if (anArgCase.IsEqual ("DEL")
11105           || anArgCase.IsEqual ("DELETE")
11106           || anArgCase.IsEqual ("-DEL")
11107           || anArgCase.IsEqual ("-DELETE"))
11108     {
11109       Handle(V3d_Light) aLightDel;
11110       if (++anArgIt >= theArgsNb)
11111       {
11112         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11113         return 1;
11114       }
11115
11116       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
11117       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
11118       Standard_Integer aLightIt = 0;
11119       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
11120       {
11121         aLightDel = aLightIter.Value();
11122         if (aLightIt == aLightDelId)
11123         {
11124           break;
11125         }
11126       }
11127       if (aLightDel.IsNull())
11128       {
11129         continue;
11130       }
11131
11132       TColStd_SequenceOfInteger aLayers;
11133       aViewer->GetAllZLayers (aLayers);
11134       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
11135       {
11136         if (aLayeriter.Value() == aLayer
11137          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
11138         {
11139           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
11140           if (!aSettings.Lights().IsNull())
11141           {
11142             aSettings.Lights()->Remove (aLightDel);
11143             if (aSettings.Lights()->IsEmpty())
11144             {
11145               aSettings.SetLights (Handle(Graphic3d_LightSet)());
11146             }
11147           }
11148           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
11149           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
11150           {
11151             break;
11152           }
11153         }
11154       }
11155
11156       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
11157       {
11158         aViewer->DelLight (aLightDel);
11159       }
11160     }
11161     else if (anArgCase.IsEqual ("COLOR")
11162           || anArgCase.IsEqual ("COLOUR")
11163           || anArgCase.IsEqual ("-COLOR")
11164           || anArgCase.IsEqual ("-COLOUR"))
11165     {
11166       if (++anArgIt >= theArgsNb
11167        || aLightCurr.IsNull())
11168       {
11169         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11170         return 1;
11171       }
11172
11173       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
11174       anArgNext.UpperCase();
11175       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
11176       aLightCurr->SetColor (aColor);
11177     }
11178     else if (anArgCase.IsEqual ("POS")
11179           || anArgCase.IsEqual ("POSITION")
11180           || anArgCase.IsEqual ("-POS")
11181           || anArgCase.IsEqual ("-POSITION"))
11182     {
11183       if ((anArgIt + 3) >= theArgsNb
11184        || aLightCurr.IsNull()
11185        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11186         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11187       {
11188         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11189         return 1;
11190       }
11191
11192       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11193       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11194       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11195       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
11196     }
11197     else if (anArgCase.IsEqual ("DIR")
11198           || anArgCase.IsEqual ("DIRECTION")
11199           || anArgCase.IsEqual ("-DIR")
11200           || anArgCase.IsEqual ("-DIRECTION"))
11201     {
11202       if ((anArgIt + 3) >= theArgsNb
11203        || aLightCurr.IsNull()
11204        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
11205         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11206       {
11207         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11208         return 1;
11209       }
11210
11211       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11212       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11213       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11214       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
11215     }
11216     else if (anArgCase.IsEqual ("SM")
11217           || anArgCase.IsEqual ("SMOOTHNESS")
11218           || anArgCase.IsEqual ("-SM")
11219           || anArgCase.IsEqual ("-SMOOTHNESS"))
11220     {
11221       if (++anArgIt >= theArgsNb
11222        || aLightCurr.IsNull())
11223       {
11224         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11225         return 1;
11226       }
11227
11228       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11229       if (Abs (aSmoothness) <= ShortRealEpsilon())
11230       {
11231         aLightCurr->SetIntensity (1.f);
11232       }
11233       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
11234       {
11235         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
11236       }
11237       else
11238       {
11239         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
11240         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
11241       }
11242
11243       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
11244       {
11245         aLightCurr->SetSmoothRadius (aSmoothness);
11246       }
11247       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
11248       {
11249         aLightCurr->SetSmoothAngle (aSmoothness);
11250       }
11251     }
11252     else if (anArgCase.IsEqual ("INT")
11253           || anArgCase.IsEqual ("INTENSITY")
11254           || anArgCase.IsEqual ("-INT")
11255           || anArgCase.IsEqual ("-INTENSITY"))
11256     {
11257       if (++anArgIt >= theArgsNb
11258        || aLightCurr.IsNull())
11259       {
11260         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11261         return 1;
11262       }
11263
11264       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11265       aLightCurr->SetIntensity (aIntensity);
11266     }
11267     else if (anArgCase.IsEqual ("ANG")
11268           || anArgCase.IsEqual ("ANGLE")
11269           || anArgCase.IsEqual ("-ANG")
11270           || anArgCase.IsEqual ("-ANGLE"))
11271     {
11272       if (++anArgIt >= theArgsNb
11273        || aLightCurr.IsNull()
11274        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11275       {
11276         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11277         return 1;
11278       }
11279
11280       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11281       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
11282     }
11283     else if (anArgCase.IsEqual ("CONSTATTEN")
11284           || anArgCase.IsEqual ("CONSTATTENUATION")
11285           || anArgCase.IsEqual ("-CONSTATTEN")
11286           || anArgCase.IsEqual ("-CONSTATTENUATION"))
11287     {
11288       if (++anArgIt >= theArgsNb
11289        || aLightCurr.IsNull()
11290        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11291         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11292       {
11293         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11294         return 1;
11295       }
11296
11297       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11298       anAtten[0] = Atof (theArgVec[anArgIt]);
11299       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11300     }
11301     else if (anArgCase.IsEqual ("LINATTEN")
11302           || anArgCase.IsEqual ("LINEARATTEN")
11303           || anArgCase.IsEqual ("LINEARATTENUATION")
11304           || anArgCase.IsEqual ("-LINATTEN")
11305           || anArgCase.IsEqual ("-LINEARATTEN")
11306           || anArgCase.IsEqual ("-LINEARATTENUATION"))
11307     {
11308       if (++anArgIt >= theArgsNb
11309        || aLightCurr.IsNull()
11310        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11311         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11312       {
11313         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11314         return 1;
11315       }
11316
11317       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11318       anAtten[1] = Atof (theArgVec[anArgIt]);
11319       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11320     }
11321     else if (anArgCase.IsEqual ("EXP")
11322           || anArgCase.IsEqual ("EXPONENT")
11323           || anArgCase.IsEqual ("SPOTEXP")
11324           || anArgCase.IsEqual ("SPOTEXPONENT")
11325           || anArgCase.IsEqual ("-EXP")
11326           || anArgCase.IsEqual ("-EXPONENT")
11327           || anArgCase.IsEqual ("-SPOTEXP")
11328           || anArgCase.IsEqual ("-SPOTEXPONENT"))
11329     {
11330       if (++anArgIt >= theArgsNb
11331        || aLightCurr.IsNull()
11332        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11333       {
11334         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11335         return 1;
11336       }
11337
11338       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
11339     }
11340     else if (anArgCase.IsEqual ("HEAD")
11341           || anArgCase.IsEqual ("HEADLIGHT")
11342           || anArgCase.IsEqual ("-HEAD")
11343           || anArgCase.IsEqual ("-HEADLIGHT"))
11344     {
11345       if (aLightCurr.IsNull()
11346        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
11347       {
11348         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11349         return 1;
11350       }
11351
11352       Standard_Boolean isHeadLight = Standard_True;
11353       if (anArgIt + 1 < theArgsNb
11354        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
11355       {
11356         ++anArgIt;
11357       }
11358       aLightCurr->SetHeadlight (isHeadLight);
11359     }
11360     else
11361     {
11362       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
11363     }
11364   }
11365
11366   addLight (aLightNew, aLayer, isGlobal);
11367   return 0;
11368 }
11369
11370 //! Read Graphic3d_RenderingParams::PerfCounters flag.
11371 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
11372                                             Standard_Boolean& theToReset,
11373                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
11374                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
11375 {
11376   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
11377   TCollection_AsciiString aVal = theValue;
11378   Standard_Boolean toReverse = Standard_False;
11379   if (aVal == "none")
11380   {
11381     theToReset = Standard_True;
11382     return Standard_True;
11383   }
11384   else if (aVal.StartsWith ("-"))
11385   {
11386     toReverse = Standard_True;
11387     aVal = aVal.SubString (2, aVal.Length());
11388   }
11389   else if (aVal.StartsWith ("no"))
11390   {
11391     toReverse = Standard_True;
11392     aVal = aVal.SubString (3, aVal.Length());
11393   }
11394   else if (aVal.StartsWith ("+"))
11395   {
11396     aVal = aVal.SubString (2, aVal.Length());
11397   }
11398   else
11399   {
11400     theToReset = Standard_True;
11401   }
11402
11403   if (     aVal == "fps"
11404         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11405   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
11406   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
11407   else if (aVal == "structs"
11408         || aVal == "structures"
11409         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
11410   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
11411   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11412   else if (aVal == "tris"
11413         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
11414   else if (aVal == "pnts"
11415         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
11416   else if (aVal == "mem"
11417         || aVal == "gpumem"
11418         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11419   else if (aVal == "skipimmediate"
11420         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
11421   else if (aVal == "frametime"
11422         || aVal == "frametimers"
11423         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11424   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
11425   else if (aVal == "extended"
11426         || aVal == "verbose"
11427         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
11428   else if (aVal == "full"
11429         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
11430   else
11431   {
11432     return Standard_False;
11433   }
11434
11435   if (toReverse)
11436   {
11437     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11438   }
11439   else
11440   {
11441     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11442   }
11443   return Standard_True;
11444 }
11445
11446 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11447 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11448                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11449 {
11450   TCollection_AsciiString aValue = theValue;
11451   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11452   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11453   Standard_Boolean toReset = Standard_False;
11454   for (;;)
11455   {
11456     Standard_Integer aSplitPos = aValue.Search ("|");
11457     if (aSplitPos <= 0)
11458     {
11459       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11460       {
11461         return Standard_False;
11462       }
11463       if (toReset)
11464       {
11465         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11466       }
11467       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11468       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11469       return Standard_True;
11470     }
11471
11472     if (aSplitPos > 1)
11473     {
11474       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11475       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11476       {
11477         return Standard_False;
11478       }
11479     }
11480     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11481   }
11482 }
11483
11484 //=======================================================================
11485 //function : VRenderParams
11486 //purpose  : Enables/disables rendering features
11487 //=======================================================================
11488
11489 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11490                                        Standard_Integer  theArgNb,
11491                                        const char**      theArgVec)
11492 {
11493   Handle(V3d_View) aView = ViewerTest::CurrentView();
11494   if (aView.IsNull())
11495   {
11496     std::cerr << "Error: no active viewer!\n";
11497     return 1;
11498   }
11499
11500   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11501   TCollection_AsciiString aCmdName (theArgVec[0]);
11502   aCmdName.LowerCase();
11503   if (aCmdName == "vraytrace")
11504   {
11505     if (theArgNb == 1)
11506     {
11507       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11508       return 0;
11509     }
11510     else if (theArgNb == 2)
11511     {
11512       TCollection_AsciiString aValue (theArgVec[1]);
11513       aValue.LowerCase();
11514       if (aValue == "on"
11515        || aValue == "1")
11516       {
11517         aParams.Method = Graphic3d_RM_RAYTRACING;
11518         aView->Redraw();
11519         return 0;
11520       }
11521       else if (aValue == "off"
11522             || aValue == "0")
11523       {
11524         aParams.Method = Graphic3d_RM_RASTERIZATION;
11525         aView->Redraw();
11526         return 0;
11527       }
11528       else
11529       {
11530         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11531         return 1;
11532       }
11533     }
11534     else
11535     {
11536       std::cout << "Error: wrong number of arguments\n";
11537       return 1;
11538     }
11539   }
11540
11541   if (theArgNb < 2)
11542   {
11543     theDI << "renderMode:  ";
11544     switch (aParams.Method)
11545     {
11546       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11547       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11548     }
11549     theDI << "\n";
11550     theDI << "transparency:  ";
11551     switch (aParams.TransparencyMethod)
11552     {
11553       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11554       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11555                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11556     }
11557     theDI << "\n";
11558     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11559     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11560     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11561     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11562     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11563     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11564     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11565     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11566     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11567     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11568     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11569     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11570     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11571     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11572     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11573     theDI << "shadingModel: ";
11574     switch (aView->ShadingModel())
11575     {
11576       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
11577       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
11578       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
11579       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
11580       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
11581     }
11582     {
11583       theDI << "perfCounters:";
11584       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11585       {
11586         theDI << " fps";
11587       }
11588       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11589       {
11590         theDI << " cpu";
11591       }
11592       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11593       {
11594         theDI << " structs";
11595       }
11596       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11597       {
11598         theDI << " groups";
11599       }
11600       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11601       {
11602         theDI << " arrays";
11603       }
11604       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11605       {
11606         theDI << " tris";
11607       }
11608       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11609       {
11610         theDI << " pnts";
11611       }
11612       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11613       {
11614         theDI << " gpumem";
11615       }
11616       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11617       {
11618         theDI << " frameTime";
11619       }
11620       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11621       {
11622         theDI << " skipimmediate";
11623       }
11624       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11625       {
11626         theDI << " none";
11627       }
11628       theDI << "\n";
11629     }
11630     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11631     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11632     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11633                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11634                                                                                                                     "noUpdate") << "\n";
11635     theDI << "\n";
11636     return 0;
11637   }
11638
11639   Standard_Boolean toPrint = Standard_False;
11640   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11641   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11642   {
11643     Standard_CString        anArg (theArgVec[anArgIter]);
11644     TCollection_AsciiString aFlag (anArg);
11645     aFlag.LowerCase();
11646     if (anUpdateTool.parseRedrawMode (aFlag))
11647     {
11648       continue;
11649     }
11650     else if (aFlag == "-echo"
11651           || aFlag == "-print")
11652     {
11653       toPrint = Standard_True;
11654       anUpdateTool.Invalidate();
11655     }
11656     else if (aFlag == "-mode"
11657           || aFlag == "-rendermode"
11658           || aFlag == "-render_mode")
11659     {
11660       if (toPrint)
11661       {
11662         switch (aParams.Method)
11663         {
11664           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11665           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11666         }
11667         continue;
11668       }
11669       else
11670       {
11671         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11672         return 1;
11673       }
11674     }
11675     else if (aFlag == "-ray"
11676           || aFlag == "-raytrace")
11677     {
11678       if (toPrint)
11679       {
11680         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11681         continue;
11682       }
11683
11684       aParams.Method = Graphic3d_RM_RAYTRACING;
11685     }
11686     else if (aFlag == "-rast"
11687           || aFlag == "-raster"
11688           || aFlag == "-rasterization")
11689     {
11690       if (toPrint)
11691       {
11692         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11693         continue;
11694       }
11695
11696       aParams.Method = Graphic3d_RM_RASTERIZATION;
11697     }
11698     else if (aFlag == "-msaa")
11699     {
11700       if (toPrint)
11701       {
11702         theDI << aParams.NbMsaaSamples << " ";
11703         continue;
11704       }
11705       else if (++anArgIter >= theArgNb)
11706       {
11707         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11708         return 1;
11709       }
11710
11711       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11712       if (aNbSamples < 0)
11713       {
11714         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11715         return 1;
11716       }
11717       else
11718       {
11719         aParams.NbMsaaSamples = aNbSamples;
11720       }
11721     }
11722     else if (aFlag == "-linefeather"
11723           || aFlag == "-edgefeather"
11724           || aFlag == "-feather")
11725     {
11726       if (toPrint)
11727       {
11728         theDI << " " << aParams.LineFeather << " ";
11729         continue;
11730       }
11731       else if (++anArgIter >= theArgNb)
11732       {
11733         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11734         return 1;
11735       }
11736
11737       TCollection_AsciiString aParam = theArgVec[anArgIter];
11738       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11739       if (aFeather <= 0.0f)
11740       {
11741         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11742         return 1;
11743       }
11744       aParams.LineFeather = aFeather;
11745     }
11746     else if (aFlag == "-oit")
11747     {
11748       if (toPrint)
11749       {
11750         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11751         {
11752           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11753         }
11754         else
11755         {
11756           theDI << "off" << " ";
11757         }
11758         continue;
11759       }
11760       else if (++anArgIter >= theArgNb)
11761       {
11762         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11763         return 1;
11764       }
11765
11766       TCollection_AsciiString aParam = theArgVec[anArgIter];
11767       aParam.LowerCase();
11768       if (aParam.IsRealValue())
11769       {
11770         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11771         if (aWeight < 0.f || aWeight > 1.f)
11772         {
11773           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11774           return 1;
11775         }
11776
11777         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11778         aParams.OitDepthFactor     = aWeight;
11779       }
11780       else if (aParam == "off")
11781       {
11782         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11783       }
11784       else
11785       {
11786         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11787         return 1;
11788       }
11789     }
11790     else if (aFlag == "-depthprepass")
11791     {
11792       if (toPrint)
11793       {
11794         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11795         continue;
11796       }
11797       aParams.ToEnableDepthPrepass = Standard_True;
11798       if (anArgIter + 1 < theArgNb
11799        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11800       {
11801         ++anArgIter;
11802       }
11803     }
11804     else if (aFlag == "-samplealphatocoverage"
11805           || aFlag == "-alphatocoverage")
11806     {
11807       if (toPrint)
11808       {
11809         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11810         continue;
11811       }
11812       aParams.ToEnableAlphaToCoverage = Standard_True;
11813       if (anArgIter + 1 < theArgNb
11814        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11815       {
11816         ++anArgIter;
11817       }
11818     }
11819     else if (aFlag == "-rendscale"
11820           || aFlag == "-renderscale"
11821           || aFlag == "-renderresolutionscale")
11822     {
11823       if (toPrint)
11824       {
11825         theDI << aParams.RenderResolutionScale << " ";
11826         continue;
11827       }
11828       else if (++anArgIter >= theArgNb)
11829       {
11830         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11831         return 1;
11832       }
11833
11834       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11835       if (aScale < 0.01)
11836       {
11837         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11838         return 1;
11839       }
11840       else
11841       {
11842         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11843       }
11844     }
11845     else if (aFlag == "-raydepth"
11846           || aFlag == "-ray_depth")
11847     {
11848       if (toPrint)
11849       {
11850         theDI << aParams.RaytracingDepth << " ";
11851         continue;
11852       }
11853       else if (++anArgIter >= theArgNb)
11854       {
11855         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11856         return 1;
11857       }
11858
11859       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11860
11861       // We allow RaytracingDepth be more than 10 in case of GI enabled
11862       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11863       {
11864         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11865         return 1;
11866       }
11867       else
11868       {
11869         aParams.RaytracingDepth = aDepth;
11870       }
11871     }
11872     else if (aFlag == "-shad"
11873           || aFlag == "-shadows")
11874     {
11875       if (toPrint)
11876       {
11877         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11878         continue;
11879       }
11880
11881       Standard_Boolean toEnable = Standard_True;
11882       if (++anArgIter < theArgNb
11883       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11884       {
11885         --anArgIter;
11886       }
11887       aParams.IsShadowEnabled = toEnable;
11888     }
11889     else if (aFlag == "-refl"
11890           || aFlag == "-reflections")
11891     {
11892       if (toPrint)
11893       {
11894         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11895         continue;
11896       }
11897
11898       Standard_Boolean toEnable = Standard_True;
11899       if (++anArgIter < theArgNb
11900       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11901       {
11902         --anArgIter;
11903       }
11904       aParams.IsReflectionEnabled = toEnable;
11905     }
11906     else if (aFlag == "-fsaa")
11907     {
11908       if (toPrint)
11909       {
11910         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11911         continue;
11912       }
11913
11914       Standard_Boolean toEnable = Standard_True;
11915       if (++anArgIter < theArgNb
11916       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11917       {
11918         --anArgIter;
11919       }
11920       aParams.IsAntialiasingEnabled = toEnable;
11921     }
11922     else if (aFlag == "-gleam")
11923     {
11924       if (toPrint)
11925       {
11926         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11927         continue;
11928       }
11929
11930       Standard_Boolean toEnable = Standard_True;
11931       if (++anArgIter < theArgNb
11932       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11933       {
11934         --anArgIter;
11935       }
11936       aParams.IsTransparentShadowEnabled = toEnable;
11937     }
11938     else if (aFlag == "-gi")
11939     {
11940       if (toPrint)
11941       {
11942         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11943         continue;
11944       }
11945
11946       Standard_Boolean toEnable = Standard_True;
11947       if (++anArgIter < theArgNb
11948       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11949       {
11950         --anArgIter;
11951       }
11952       aParams.IsGlobalIlluminationEnabled = toEnable;
11953       if (!toEnable)
11954       {
11955         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11956       }
11957     }
11958     else if (aFlag == "-blockedrng"
11959           || aFlag == "-brng")
11960     {
11961       if (toPrint)
11962       {
11963         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11964         continue;
11965       }
11966
11967       Standard_Boolean toEnable = Standard_True;
11968       if (++anArgIter < theArgNb
11969         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11970       {
11971         --anArgIter;
11972       }
11973       aParams.CoherentPathTracingMode = toEnable;
11974     }
11975     else if (aFlag == "-maxrad")
11976     {
11977       if (toPrint)
11978       {
11979         theDI << aParams.RadianceClampingValue << " ";
11980         continue;
11981       }
11982       else if (++anArgIter >= theArgNb)
11983       {
11984         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11985         return 1;
11986       }
11987
11988       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11989       if (!aMaxRadStr.IsRealValue())
11990       {
11991         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11992         return 1;
11993       }
11994
11995       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11996       if (aMaxRadiance <= 0.0)
11997       {
11998         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11999         return 1;
12000       }
12001       else
12002       {
12003         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
12004       }
12005     }
12006     else if (aFlag == "-iss")
12007     {
12008       if (toPrint)
12009       {
12010         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
12011         continue;
12012       }
12013
12014       Standard_Boolean toEnable = Standard_True;
12015       if (++anArgIter < theArgNb
12016         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12017       {
12018         --anArgIter;
12019       }
12020       aParams.AdaptiveScreenSampling = toEnable;
12021     }
12022     else if (aFlag == "-issatomic")
12023     {
12024       if (toPrint)
12025       {
12026         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
12027         continue;
12028       }
12029
12030       Standard_Boolean toEnable = Standard_True;
12031       if (++anArgIter < theArgNb
12032       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12033       {
12034         --anArgIter;
12035       }
12036       aParams.AdaptiveScreenSamplingAtomic = toEnable;
12037     }
12038     else if (aFlag == "-issd")
12039     {
12040       if (toPrint)
12041       {
12042         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
12043         continue;
12044       }
12045
12046       Standard_Boolean toEnable = Standard_True;
12047       if (++anArgIter < theArgNb
12048         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12049       {
12050         --anArgIter;
12051       }
12052       aParams.ShowSamplingTiles = toEnable;
12053     }
12054     else if (aFlag == "-tilesize")
12055     {
12056       if (toPrint)
12057       {
12058         theDI << aParams.RayTracingTileSize << " ";
12059         continue;
12060       }
12061       else if (++anArgIter >= theArgNb)
12062       {
12063         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12064         return 1;
12065       }
12066
12067       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
12068       if (aTileSize < 1)
12069       {
12070         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
12071         return 1;
12072       }
12073       aParams.RayTracingTileSize = aTileSize;
12074     }
12075     else if (aFlag == "-nbtiles")
12076     {
12077       if (toPrint)
12078       {
12079         theDI << aParams.NbRayTracingTiles << " ";
12080         continue;
12081       }
12082       else if (++anArgIter >= theArgNb)
12083       {
12084         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12085         return 1;
12086       }
12087
12088       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
12089       if (aNbTiles < -1)
12090       {
12091         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
12092         return 1;
12093       }
12094       else if (aNbTiles > 0
12095             && (aNbTiles < 64
12096              || aNbTiles > 1024))
12097       {
12098         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
12099       }
12100       aParams.NbRayTracingTiles = aNbTiles;
12101     }
12102     else if (aFlag == "-env")
12103     {
12104       if (toPrint)
12105       {
12106         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
12107         continue;
12108       }
12109
12110       Standard_Boolean toEnable = Standard_True;
12111       if (++anArgIter < theArgNb
12112         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12113       {
12114         --anArgIter;
12115       }
12116       aParams.UseEnvironmentMapBackground = toEnable;
12117     }
12118     else if (aFlag == "-twoside")
12119     {
12120       if (toPrint)
12121       {
12122         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
12123         continue;
12124       }
12125
12126       Standard_Boolean toEnable = Standard_True;
12127       if (++anArgIter < theArgNb
12128         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12129       {
12130         --anArgIter;
12131       }
12132       aParams.TwoSidedBsdfModels = toEnable;
12133     }
12134     else if (aFlag == "-shademodel"
12135           || aFlag == "-shadingmodel"
12136           || aFlag == "-shading")
12137     {
12138       if (toPrint)
12139       {
12140         switch (aView->ShadingModel())
12141         {
12142           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
12143           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
12144           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
12145           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
12146           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
12147         }
12148         continue;
12149       }
12150
12151       if (++anArgIter >= theArgNb)
12152       {
12153         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12154       }
12155
12156       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
12157       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
12158        && aModel != Graphic3d_TOSM_DEFAULT)
12159       {
12160         aView->SetShadingModel (aModel);
12161       }
12162       else
12163       {
12164         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
12165         return 1;
12166       }
12167     }
12168     else if (aFlag == "-resolution")
12169     {
12170       if (++anArgIter >= theArgNb)
12171       {
12172         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12173         return 1;
12174       }
12175
12176       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
12177       if (aResolution.IsIntegerValue())
12178       {
12179         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
12180       }
12181       else
12182       {
12183         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12184         return 1;
12185       }
12186     }
12187     else if (aFlag == "-rebuildglsl"
12188           || aFlag == "-rebuild")
12189     {
12190       if (toPrint)
12191       {
12192         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
12193         continue;
12194       }
12195
12196       Standard_Boolean toEnable = Standard_True;
12197       if (++anArgIter < theArgNb
12198           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12199       {
12200         --anArgIter;
12201       }
12202       aParams.RebuildRayTracingShaders = toEnable;
12203     }
12204     else if (aFlag == "-focal")
12205     {
12206       if (++anArgIter >= theArgNb)
12207       {
12208         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12209         return 1;
12210       }
12211
12212       TCollection_AsciiString aParam (theArgVec[anArgIter]);
12213       if (aParam.IsRealValue())
12214       {
12215         float aFocalDist = static_cast<float> (aParam.RealValue());
12216         if (aFocalDist < 0)
12217         {
12218           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12219           return 1;
12220         }
12221         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
12222       }
12223       else
12224       {
12225         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12226         return 1;
12227       }
12228     }
12229     else if (aFlag == "-aperture")
12230     {
12231       if (++anArgIter >= theArgNb)
12232       {
12233         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12234         return 1;
12235       }
12236
12237       TCollection_AsciiString aParam(theArgVec[anArgIter]);
12238       if (aParam.IsRealValue())
12239       {
12240         float aApertureSize = static_cast<float> (aParam.RealValue());
12241         if (aApertureSize < 0)
12242         {
12243           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12244           return 1;
12245         }
12246         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
12247       }
12248       else
12249       {
12250         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12251         return 1;
12252       }
12253     }
12254     else if (aFlag == "-exposure")
12255     {
12256       if (++anArgIter >= theArgNb)
12257       {
12258         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12259         return 1;
12260       }
12261
12262       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
12263       if (anExposure.IsRealValue())
12264       {
12265         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
12266       }
12267       else
12268       {
12269         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12270         return 1;
12271       }
12272     }
12273     else if (aFlag == "-whitepoint")
12274     {
12275       if (++anArgIter >= theArgNb)
12276       {
12277         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12278         return 1;
12279       }
12280
12281       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
12282       if (aWhitePoint.IsRealValue())
12283       {
12284         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
12285       }
12286       else
12287       {
12288         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12289         return 1;
12290       }
12291     }
12292     else if (aFlag == "-tonemapping")
12293     {
12294       if (++anArgIter >= theArgNb)
12295       {
12296         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12297         return 1;
12298       }
12299
12300       TCollection_AsciiString aMode (theArgVec[anArgIter]);
12301       aMode.LowerCase();
12302
12303       if (aMode == "disabled")
12304       {
12305         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
12306       }
12307       else if (aMode == "filmic")
12308       {
12309         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
12310       }
12311       else
12312       {
12313         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12314         return 1;
12315       }
12316     }
12317     else if (aFlag == "-performancestats"
12318           || aFlag == "-performancecounters"
12319           || aFlag == "-perfstats"
12320           || aFlag == "-perfcounters"
12321           || aFlag == "-stats")
12322     {
12323       if (++anArgIter >= theArgNb)
12324       {
12325         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12326         return 1;
12327       }
12328
12329       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
12330       aFlagsStr.LowerCase();
12331       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
12332       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
12333       {
12334         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12335         return 1;
12336       }
12337       aView->ChangeRenderingParams().CollectedStats = aFlags;
12338       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
12339     }
12340     else if (aFlag == "-perfupdateinterval"
12341           || aFlag == "-statsupdateinterval")
12342     {
12343       if (++anArgIter >= theArgNb)
12344       {
12345         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12346         return 1;
12347       }
12348       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12349     }
12350     else if (aFlag == "-perfchart"
12351           || aFlag == "-statschart")
12352     {
12353       if (++anArgIter >= theArgNb)
12354       {
12355         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12356         return 1;
12357       }
12358       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
12359     }
12360     else if (aFlag == "-perfchartmax"
12361           || aFlag == "-statschartmax")
12362     {
12363       if (++anArgIter >= theArgNb)
12364       {
12365         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12366         return 1;
12367       }
12368       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12369     }
12370     else if (aFlag == "-frustumculling"
12371           || aFlag == "-culling")
12372     {
12373       if (toPrint)
12374       {
12375         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
12376                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
12377                                                                                                    "noUpdate") << " ";
12378         continue;
12379       }
12380
12381       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
12382       if (++anArgIter < theArgNb)
12383       {
12384         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
12385         aStateStr.LowerCase();
12386         bool toEnable = true;
12387         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
12388         {
12389           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
12390         }
12391         else if (aStateStr == "noupdate"
12392               || aStateStr == "freeze")
12393         {
12394           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
12395         }
12396         else
12397         {
12398           --anArgIter;
12399         }
12400       }
12401       aParams.FrustumCullingState = aState;
12402     }
12403     else
12404     {
12405       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
12406       return 1;
12407     }
12408   }
12409
12410   return 0;
12411 }
12412
12413 //=======================================================================
12414 //function : searchInfo
12415 //purpose  :
12416 //=======================================================================
12417 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12418                                            const TCollection_AsciiString&              theKey)
12419 {
12420   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12421   {
12422     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12423     {
12424       return anIter.Value();
12425     }
12426   }
12427   return TCollection_AsciiString();
12428 }
12429
12430 //=======================================================================
12431 //function : VStatProfiler
12432 //purpose  :
12433 //=======================================================================
12434 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12435                                        Standard_Integer  theArgNb,
12436                                        const char**      theArgVec)
12437 {
12438   Handle(V3d_View) aView = ViewerTest::CurrentView();
12439   if (aView.IsNull())
12440   {
12441     std::cerr << "Error: no active viewer!\n";
12442     return 1;
12443   }
12444
12445   Standard_Boolean toRedraw = Standard_True;
12446   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12447   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12448   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12449   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12450   {
12451     Standard_CString        anArg (theArgVec[anArgIter]);
12452     TCollection_AsciiString aFlag (anArg);
12453     aFlag.LowerCase();
12454     if (aFlag == "-noredraw")
12455     {
12456       toRedraw = Standard_False;
12457     }
12458     else
12459     {
12460       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12461       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12462       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12463       else if (aFlag == "alllayers"
12464             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12465       else if (aFlag == "allstructs"
12466             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12467       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12468       else if (aFlag == "allarrays"
12469             || aFlag == "fillarrays"
12470             || aFlag == "linearrays"
12471             || aFlag == "pointarrays"
12472             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12473       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12474       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12475       else if (aFlag == "geommem"
12476             || aFlag == "texturemem"
12477             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12478       else if (aFlag == "elapsedframe"
12479             || aFlag == "cpuframeaverage"
12480             || aFlag == "cpupickingaverage"
12481             || aFlag == "cpucullingaverage"
12482             || aFlag == "cpudynaverage"
12483             || aFlag == "cpuframemax"
12484             || aFlag == "cpupickingmax"
12485             || aFlag == "cpucullingmax"
12486             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12487       else
12488       {
12489         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12490         continue;
12491       }
12492
12493       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12494     }
12495   }
12496
12497   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12498   {
12499     aView->ChangeRenderingParams().CollectedStats =
12500       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12501
12502     if (toRedraw)
12503     {
12504       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12505       aView->Redraw();
12506       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12507     }
12508
12509     TColStd_IndexedDataMapOfStringString aDict;
12510     aView->StatisticInformation (aDict);
12511
12512     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12513
12514     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12515     {
12516       Standard_CString        anArg(theArgVec[anArgIter]);
12517       TCollection_AsciiString aFlag(anArg);
12518       aFlag.LowerCase();
12519       if (aFlag == "fps")
12520       {
12521         theDI << searchInfo (aDict, "FPS") << " ";
12522       }
12523       else if (aFlag == "cpu")
12524       {
12525         theDI << searchInfo (aDict, "CPU FPS") << " ";
12526       }
12527       else if (aFlag == "alllayers")
12528       {
12529         theDI << searchInfo (aDict, "Layers") << " ";
12530       }
12531       else if (aFlag == "layers")
12532       {
12533         theDI << searchInfo (aDict, "Rendered layers") << " ";
12534       }
12535       else if (aFlag == "allstructs")
12536       {
12537         theDI << searchInfo (aDict, "Structs") << " ";
12538       }
12539       else if (aFlag == "structs")
12540       {
12541         theDI << searchInfo (aDict, "Rendered structs") << " ";
12542       }
12543       else if (aFlag == "groups")
12544       {
12545         theDI << searchInfo (aDict, "Rendered groups") << " ";
12546       }
12547       else if (aFlag == "allarrays")
12548       {
12549         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12550       }
12551       else if (aFlag == "fillarrays")
12552       {
12553         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12554       }
12555       else if (aFlag == "linearrays")
12556       {
12557         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12558       }
12559       else if (aFlag == "pointarrays")
12560       {
12561         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12562       }
12563       else if (aFlag == "textarrays")
12564       {
12565         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12566       }
12567       else if (aFlag == "triangles")
12568       {
12569         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12570       }
12571       else if (aFlag == "points")
12572       {
12573         theDI << searchInfo (aDict, "Rendered points") << " ";
12574       }
12575       else if (aFlag == "geommem")
12576       {
12577         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12578       }
12579       else if (aFlag == "texturemem")
12580       {
12581         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12582       }
12583       else if (aFlag == "framemem")
12584       {
12585         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12586       }
12587       else if (aFlag == "elapsedframe")
12588       {
12589         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12590       }
12591       else if (aFlag == "cpuframe_average")
12592       {
12593         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12594       }
12595       else if (aFlag == "cpupicking_average")
12596       {
12597         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12598       }
12599       else if (aFlag == "cpuculling_average")
12600       {
12601         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12602       }
12603       else if (aFlag == "cpudyn_average")
12604       {
12605         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12606       }
12607       else if (aFlag == "cpuframe_max")
12608       {
12609         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12610       }
12611       else if (aFlag == "cpupicking_max")
12612       {
12613         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12614       }
12615       else if (aFlag == "cpuculling_max")
12616       {
12617         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12618       }
12619       else if (aFlag == "cpudyn_max")
12620       {
12621         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12622       }
12623     }
12624   }
12625   else
12626   {
12627     if (toRedraw)
12628     {
12629       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12630       aView->Redraw();
12631       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12632     }
12633     theDI << "Statistic info:\n" << aView->StatisticInformation();
12634   }
12635   return 0;
12636 }
12637
12638 //=======================================================================
12639 //function : VProgressiveMode
12640 //purpose  :
12641 //=======================================================================
12642 #if defined(_WIN32)
12643 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
12644                                           Standard_Integer  /*theNbArgs*/,
12645                                           const char**      /*theArgs*/)
12646 {
12647   Handle(V3d_View) aView = ViewerTest::CurrentView();
12648   if (aView.IsNull())
12649   {
12650     std::cerr << "Error: no active viewer!\n";
12651     return 1;
12652   }
12653
12654   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
12655
12656   for (;;)
12657   {
12658     aView->Redraw();
12659
12660     Standard_Boolean toExit = Standard_False;
12661
12662     MSG aMsg;
12663     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
12664     {
12665       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
12666       {
12667         toExit = Standard_True;
12668       }
12669
12670       TranslateMessage (&aMsg);
12671       DispatchMessageW (&aMsg);
12672     }
12673
12674     if (toExit)
12675     {
12676       break;
12677     }
12678   }
12679
12680   return 0;
12681 }
12682 #endif
12683
12684 //=======================================================================
12685 //function : VXRotate
12686 //purpose  :
12687 //=======================================================================
12688 static Standard_Integer VXRotate (Draw_Interpretor& di,
12689                                    Standard_Integer argc,
12690                                    const char ** argv)
12691 {
12692   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12693   if (aContext.IsNull())
12694   {
12695     di << argv[0] << "ERROR : use 'vinit' command before \n";
12696     return 1;
12697   }
12698
12699   if (argc != 3)
12700   {
12701     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12702     return 1;
12703   }
12704
12705   TCollection_AsciiString aName (argv[1]);
12706   Standard_Real anAngle = Draw::Atof (argv[2]);
12707
12708   // find object
12709   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12710   Handle(AIS_InteractiveObject) anIObj;
12711   if (!aMap.Find2 (aName, anIObj))
12712   {
12713     di << "Use 'vdisplay' before\n";
12714     return 1;
12715   }
12716
12717   gp_Trsf aTransform;
12718   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12719   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12720
12721   aContext->SetLocation (anIObj, aTransform);
12722   aContext->UpdateCurrentViewer();
12723   return 0;
12724 }
12725
12726 //===============================================================================================
12727 //class   : ViewerTest_AISManipulator
12728 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
12729 //===============================================================================================
12730 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12731
12732 class ViewerTest_AISManipulator : public AIS_Manipulator
12733 {
12734 public:
12735
12736   ViewerTest_AISManipulator() : AIS_Manipulator()
12737   {
12738     GetMapOfAISManipulators().Add (this);
12739   }
12740
12741   virtual ~ViewerTest_AISManipulator()
12742   {
12743     GetMapOfAISManipulators().Remove (this);
12744   }
12745
12746   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12747 };
12748
12749 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12750 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12751
12752 //===============================================================================================
12753 //function : VManipulator
12754 //purpose  :
12755 //===============================================================================================
12756 static int VManipulator (Draw_Interpretor& theDi,
12757                          Standard_Integer  theArgsNb,
12758                          const char**      theArgVec)
12759 {
12760   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
12761   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12762   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12763   if (aView.IsNull()
12764    || aViewer.IsNull())
12765   {
12766     std::cerr << "No active viewer!\n";
12767     return 1;
12768   }
12769
12770   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12771   Standard_Integer anArgIter = 1;
12772   for (; anArgIter < theArgsNb; ++anArgIter)
12773   {
12774     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12775   }
12776
12777   ViewerTest_CmdParser aCmd;
12778   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12779   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12780   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12781   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12782   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12783   aCmd.AddOption ("detach",         "...       - detach manipulator");
12784
12785   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12786   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12787   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12788
12789   aCmd.AddOption ("move",   "... x y z - move object");
12790   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
12791   aCmd.AddOption ("scale",  "... factor - scale object");
12792
12793   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12794   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12795   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12796   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12797   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12798   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12799   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
12800   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12801   aCmd.AddOption ("size",              "... size - set size of manipulator");
12802   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12803
12804   aCmd.Parse (theArgsNb, theArgVec);
12805
12806   if (aCmd.HasOption ("help"))
12807   {
12808     theDi.PrintHelp (theArgVec[0]);
12809     return 0;
12810   }
12811
12812   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12813
12814   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
12815
12816   if (aName.IsEmpty())
12817   {
12818     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12819     return 1;
12820   }
12821
12822   // ----------------------------------
12823   // detach existing manipulator object
12824   // ----------------------------------
12825
12826   if (aCmd.HasOption ("detach"))
12827   {
12828     if (!aMapAIS.IsBound2 (aName))
12829     {
12830       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12831       return 1;
12832     }
12833
12834     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12835     if (aManipulator.IsNull())
12836     {
12837       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12838       return 1;
12839     }
12840
12841     aManipulator->Detach();
12842     aMapAIS.UnBind2 (aName);
12843     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12844
12845     return 0;
12846   }
12847
12848   // -----------------------------------------------
12849   // find or create manipulator if it does not exist
12850   // -----------------------------------------------
12851
12852   Handle(AIS_Manipulator) aManipulator;
12853   if (!aMapAIS.IsBound2 (aName))
12854   {
12855     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12856
12857     aManipulator = new ViewerTest_AISManipulator();
12858     aMapAIS.Bind (aManipulator, aName);
12859   }
12860   else
12861   {
12862     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12863     if (aManipulator.IsNull())
12864     {
12865       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12866       return 1;
12867     }
12868   }
12869
12870   // -----------------------------------------
12871   // change properties of manipulator instance
12872   // -----------------------------------------
12873
12874   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12875   {
12876     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12877   }
12878   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12879   {
12880     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12881   }
12882   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12883   {
12884     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12885   }
12886   if (aCmd.HasOption("followDragging", 1, Standard_True))
12887   {
12888     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12889   }
12890   if (aCmd.HasOption ("gap", 1, Standard_True))
12891   {
12892     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12893   }
12894   if (aCmd.HasOption ("part", 3, Standard_True))
12895   {
12896     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12897     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12898     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12899     if (aMode < 1 || aMode > 4)
12900     {
12901       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12902       return 1;
12903     }
12904
12905     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12906   }
12907   if (aCmd.HasOption("parts", 2, Standard_True))
12908   {
12909     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
12910     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
12911     if (aMode < 1 || aMode > 4)
12912     {
12913       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12914       return 1;
12915     }
12916
12917     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
12918   }
12919   if (aCmd.HasOption ("pos", 3, Standard_True))
12920   {
12921     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12922     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12923     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12924
12925     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12926   }
12927   if (aCmd.HasOption ("size", 1, Standard_True))
12928   {
12929     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12930   }
12931   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12932   {
12933     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12934
12935     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12936     {
12937       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12938       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12939     }
12940   }
12941
12942   // ---------------------------------------------------
12943   // attach, detach or access manipulator from an object
12944   // ---------------------------------------------------
12945
12946   if (aCmd.HasOption ("attach"))
12947   {
12948     // Find an object and attach manipulator to it
12949     if (!aCmd.HasOption ("attach", 1, Standard_True))
12950     {
12951       return 1;
12952     }
12953
12954     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12955     Handle(AIS_InteractiveObject) anObject;
12956     if (!aMapAIS.Find2 (anObjName, anObject))
12957     {
12958       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12959       return 1;
12960     }
12961
12962     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
12963     {
12964       if (anIt.Value()->IsAttached()
12965        && anIt.Value()->Object() == anObject)
12966       {
12967         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12968         return 1;
12969       }
12970     }
12971
12972     AIS_Manipulator::OptionsForAttach anOptions;
12973     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12974     {
12975       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12976     }
12977     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12978     {
12979       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12980     }
12981     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12982     {
12983       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12984     }
12985
12986     aManipulator->Attach (anObject, anOptions);
12987   }
12988
12989   // --------------------------------------
12990   // apply transformation using manipulator
12991   // --------------------------------------
12992
12993   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12994   {
12995     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12996   }
12997   if (aCmd.HasOption ("transform", 2, Standard_True))
12998   {
12999     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
13000   }
13001   if (aCmd.HasOption ("stopTransform"))
13002   {
13003     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
13004
13005     aManipulator->StopTransform (toApply);
13006   }
13007
13008   gp_Trsf aT;
13009   if (aCmd.HasOption ("move", 3, Standard_True))
13010   {
13011     aT.SetTranslationPart (aCmd.ArgVec ("move"));
13012   }
13013   if (aCmd.HasOption ("rotate", 7, Standard_True))
13014   {
13015     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
13016   }
13017   if (aCmd.HasOption ("scale", 1))
13018   {
13019     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
13020   }
13021
13022   if (aT.Form() != gp_Identity)
13023   {
13024     aManipulator->Transform (aT);
13025   }
13026
13027   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
13028
13029   return 0;
13030 }
13031
13032 //===============================================================================================
13033 //function : VSelectionProperties
13034 //purpose  :
13035 //===============================================================================================
13036 static int VSelectionProperties (Draw_Interpretor& theDi,
13037                                  Standard_Integer  theArgsNb,
13038                                  const char**      theArgVec)
13039 {
13040   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
13041   if (aCtx.IsNull())
13042   {
13043     std::cerr << "No active viewer!\n";
13044     return 1;
13045   }
13046
13047   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
13048   {
13049     // handle obsolete alias
13050     bool toEnable = true;
13051     if (theArgsNb < 2)
13052     {
13053       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
13054       return 0;
13055     }
13056     else if (theArgsNb != 2
13057          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
13058     {
13059       std::cout << "Syntax error: wrong number of parameters.";
13060       return 1;
13061     }
13062     if (toEnable != aCtx->ToHilightSelected())
13063     {
13064       aCtx->ClearDetected();
13065       aCtx->SetToHilightSelected (toEnable);
13066     }
13067     return 0;
13068   }
13069
13070   Standard_Boolean toPrint  = theArgsNb == 1;
13071   Standard_Boolean toRedraw = Standard_False;
13072   Standard_Integer anArgIter = 1;
13073   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
13074   if (anArgIter < theArgsNb)
13075   {
13076     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
13077     anArgFirst.LowerCase();
13078     ++anArgIter;
13079     if (anArgFirst == "dynhighlight"
13080      || anArgFirst == "dynhilight"
13081      || anArgFirst == "dynamichighlight"
13082      || anArgFirst == "dynamichilight")
13083     {
13084       aType = Prs3d_TypeOfHighlight_Dynamic;
13085     }
13086     else if (anArgFirst == "localdynhighlight"
13087           || anArgFirst == "localdynhilight"
13088           || anArgFirst == "localdynamichighlight"
13089           || anArgFirst == "localdynamichilight")
13090     {
13091       aType = Prs3d_TypeOfHighlight_LocalDynamic;
13092     }
13093     else if (anArgFirst == "selhighlight"
13094           || anArgFirst == "selhilight"
13095           || anArgFirst == "selectedhighlight"
13096           || anArgFirst == "selectedhilight")
13097     {
13098       aType = Prs3d_TypeOfHighlight_Selected;
13099     }
13100     else if (anArgFirst == "localselhighlight"
13101           || anArgFirst == "localselhilight"
13102           || anArgFirst == "localselectedhighlight"
13103           || anArgFirst == "localselectedhilight")
13104     {
13105       aType = Prs3d_TypeOfHighlight_LocalSelected;
13106     }
13107     else
13108     {
13109       --anArgIter;
13110     }
13111   }
13112   for (; anArgIter < theArgsNb; ++anArgIter)
13113   {
13114     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13115     anArg.LowerCase();
13116     if (anArg == "-help")
13117     {
13118       theDi.PrintHelp (theArgVec[0]);
13119       return 0;
13120     }
13121     else if (anArg == "-print")
13122     {
13123       toPrint = Standard_True;
13124     }
13125     else if (anArg == "-autoactivate")
13126     {
13127       Standard_Boolean toEnable = Standard_True;
13128       if (anArgIter + 1 < theArgsNb
13129        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13130       {
13131         ++anArgIter;
13132       }
13133       aCtx->SetAutoActivateSelection (toEnable);
13134     }
13135     else if (anArg == "-automatichighlight"
13136           || anArg == "-automatichilight"
13137           || anArg == "-autohighlight"
13138           || anArg == "-autohilight")
13139     {
13140       Standard_Boolean toEnable = Standard_True;
13141       if (anArgIter + 1 < theArgsNb
13142        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13143       {
13144         ++anArgIter;
13145       }
13146       aCtx->ClearSelected (false);
13147       aCtx->ClearDetected();
13148       aCtx->SetAutomaticHilight (toEnable);
13149       toRedraw = true;
13150     }
13151     else if (anArg == "-highlightselected"
13152           || anArg == "-hilightselected")
13153     {
13154       Standard_Boolean toEnable = Standard_True;
13155       if (anArgIter + 1 < theArgsNb
13156        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13157       {
13158         ++anArgIter;
13159       }
13160       aCtx->ClearDetected();
13161       aCtx->SetToHilightSelected (toEnable);
13162       toRedraw = true;
13163     }
13164     else if (anArg == "-pickstrategy"
13165           || anArg == "-pickingstrategy")
13166     {
13167       if (++anArgIter >= theArgsNb)
13168       {
13169         std::cout << "Syntax error: type of highlighting is undefined\n";
13170         return 1;
13171       }
13172
13173       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13174       TCollection_AsciiString aVal (theArgVec[anArgIter]);
13175       aVal.LowerCase();
13176       if (aVal == "first"
13177        || aVal == "firstaccepted"
13178        || aVal == "firstacceptable")
13179       {
13180         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13181       }
13182       else if (aVal == "topmost"
13183             || aVal == "onlyTopmost")
13184       {
13185         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
13186       }
13187       else
13188       {
13189         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
13190         return 1;
13191       }
13192
13193       aCtx->SetPickingStrategy (aStrategy);
13194     }
13195     else if (anArg == "-pixtol"
13196           && anArgIter + 1 < theArgsNb)
13197     {
13198       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
13199     }
13200     else if ((anArg == "-mode"
13201            || anArg == "-dispmode")
13202           && anArgIter + 1 < theArgsNb)
13203     {
13204       if (aType == Prs3d_TypeOfHighlight_None)
13205       {
13206         std::cout << "Syntax error: type of highlighting is undefined\n";
13207         return 1;
13208       }
13209
13210       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
13211       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13212       aStyle->SetDisplayMode (aDispMode);
13213       toRedraw = Standard_True;
13214     }
13215     else if (anArg == "-layer"
13216           && anArgIter + 1 < theArgsNb)
13217     {
13218       if (aType == Prs3d_TypeOfHighlight_None)
13219       {
13220         std::cout << "Syntax error: type of highlighting is undefined\n";
13221         return 1;
13222       }
13223
13224       ++anArgIter;
13225       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
13226       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
13227       {
13228         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
13229         return 1;
13230       }
13231
13232       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13233       aStyle->SetZLayer (aNewLayer);
13234       toRedraw = Standard_True;
13235     }
13236     else if (anArg == "-hicolor"
13237           || anArg == "-selcolor"
13238           || anArg == "-color")
13239     {
13240       if (anArg.StartsWith ("-hi"))
13241       {
13242         aType = Prs3d_TypeOfHighlight_Dynamic;
13243       }
13244       else if (anArg.StartsWith ("-sel"))
13245       {
13246         aType = Prs3d_TypeOfHighlight_Selected;
13247       }
13248       else if (aType == Prs3d_TypeOfHighlight_None)
13249       {
13250         std::cout << "Syntax error: type of highlighting is undefined\n";
13251         return 1;
13252       }
13253
13254       Quantity_Color aColor;
13255       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
13256                                                            theArgVec + anArgIter + 1,
13257                                                            aColor);
13258       if (aNbParsed == 0)
13259       {
13260         std::cout << "Syntax error: need more arguments.\n";
13261         return 1;
13262       }
13263       anArgIter += aNbParsed;
13264
13265       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13266       aStyle->SetColor (aColor);
13267       toRedraw = Standard_True;
13268     }
13269     else if ((anArg == "-transp"
13270            || anArg == "-transparency"
13271            || anArg == "-hitransp"
13272            || anArg == "-seltransp"
13273            || anArg == "-hitransplocal"
13274            || anArg == "-seltransplocal")
13275           && anArgIter + 1 < theArgsNb)
13276     {
13277       if (anArg.StartsWith ("-hi"))
13278       {
13279         aType = Prs3d_TypeOfHighlight_Dynamic;
13280       }
13281       else if (anArg.StartsWith ("-sel"))
13282       {
13283         aType = Prs3d_TypeOfHighlight_Selected;
13284       }
13285       else if (aType == Prs3d_TypeOfHighlight_None)
13286       {
13287         std::cout << "Syntax error: type of highlighting is undefined\n";
13288         return 1;
13289       }
13290
13291       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
13292       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13293       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
13294       toRedraw = Standard_True;
13295     }
13296     else if ((anArg == "-mat"
13297            || anArg == "-material")
13298           && anArgIter + 1 < theArgsNb)
13299     {
13300       if (aType == Prs3d_TypeOfHighlight_None)
13301       {
13302         std::cout << "Syntax error: type of highlighting is undefined\n";
13303         return 1;
13304       }
13305
13306       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13307       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
13308       if (aMatName != Graphic3d_NOM_DEFAULT)
13309       {
13310         ++anArgIter;
13311         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
13312         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
13313         Graphic3d_MaterialAspect aMat (aMatName);
13314         aMat.SetColor (aStyle->Color());
13315         aMat.SetTransparency (aStyle->Transparency());
13316         anAspect->SetFrontMaterial (aMat);
13317         anAspect->SetInteriorColor (aStyle->Color());
13318         aStyle->SetBasicFillAreaAspect (anAspect);
13319       }
13320       else
13321       {
13322         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
13323       }
13324       toRedraw = Standard_True;
13325     }
13326     else
13327     {
13328       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
13329     }
13330   }
13331
13332   if (toPrint)
13333   {
13334     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
13335     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
13336     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
13337     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
13338     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
13339     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
13340     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
13341     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
13342     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
13343     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
13344     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
13345     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
13346     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
13347     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
13348   }
13349
13350   if (aCtx->NbSelected() != 0 && toRedraw)
13351   {
13352     aCtx->HilightSelected (Standard_True);
13353   }
13354
13355   return 0;
13356 }
13357
13358 //===============================================================================================
13359 //function : VDumpSelectionImage
13360 //purpose  :
13361 //===============================================================================================
13362 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
13363                                 Standard_Integer  theArgsNb,
13364                                 const char**      theArgVec)
13365 {
13366   if (theArgsNb < 2)
13367   {
13368     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
13369     return 1;
13370   }
13371
13372   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13373   if (aContext.IsNull())
13374   {
13375     std::cout << "Error: no active view.\n";
13376     return 1;
13377   }
13378
13379   TCollection_AsciiString aFile;
13380   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13381   Image_Format anImgFormat = Image_Format_BGR;
13382   Standard_Integer aPickedIndex = 1;
13383   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13384   {
13385     TCollection_AsciiString aParam (theArgVec[anArgIter]);
13386     aParam.LowerCase();
13387     if (aParam == "-type")
13388     {
13389       if (++anArgIter >= theArgsNb)
13390       {
13391         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
13392         return 1;
13393       }
13394
13395       TCollection_AsciiString aValue (theArgVec[anArgIter]);
13396       aValue.LowerCase();
13397       if (aValue == "depth"
13398        || aValue == "normdepth"
13399        || aValue == "normalizeddepth")
13400       {
13401         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13402         anImgFormat = Image_Format_GrayF;
13403       }
13404       if (aValue == "depthinverted"
13405        || aValue == "normdepthinverted"
13406        || aValue == "normalizeddepthinverted"
13407        || aValue == "inverted")
13408       {
13409         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
13410         anImgFormat = Image_Format_GrayF;
13411       }
13412       else if (aValue == "unnormdepth"
13413             || aValue == "unnormalizeddepth")
13414       {
13415         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
13416         anImgFormat = Image_Format_GrayF;
13417       }
13418       else if (aValue == "objectcolor"
13419             || aValue == "object"
13420             || aValue == "color")
13421       {
13422         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13423       }
13424       else if (aValue == "entitycolor"
13425             || aValue == "entity")
13426       {
13427         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13428       }
13429       else if (aValue == "ownercolor"
13430             || aValue == "owner")
13431       {
13432         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13433       }
13434       else if (aValue == "selectionmodecolor"
13435             || aValue == "selectionmode"
13436             || aValue == "selmodecolor"
13437             || aValue == "selmode")
13438       {
13439         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13440       }
13441     }
13442     else if (aParam == "-picked"
13443           || aParam == "-pickeddepth"
13444           || aParam == "-pickedindex")
13445     {
13446       if (++anArgIter >= theArgsNb)
13447       {
13448         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13449         return 1;
13450       }
13451
13452       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13453     }
13454     else if (aFile.IsEmpty())
13455     {
13456       aFile = theArgVec[anArgIter];
13457     }
13458     else
13459     {
13460       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13461       return 1;
13462     }
13463   }
13464   if (aFile.IsEmpty())
13465   {
13466     std::cout << "Syntax error: image file name is missing.\n";
13467     return 1;
13468   }
13469
13470   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13471   Standard_Integer aWidth = 0, aHeight = 0;
13472   aView->Window()->Size (aWidth, aHeight);
13473
13474   Image_AlienPixMap aPixMap;
13475   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13476   {
13477     std::cout << "Error: can't allocate image.\n";
13478     return 1;
13479   }
13480   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13481   {
13482     std::cout << "Error: can't generate selection image.\n";
13483     return 1;
13484   }
13485   if (!aPixMap.Save (aFile))
13486   {
13487     std::cout << "Error: can't save selection image.\n";
13488     return 0;
13489   }
13490   return 0;
13491 }
13492
13493 //=======================================================================
13494 //function : ViewerCommands
13495 //purpose  :
13496 //=======================================================================
13497
13498 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13499 {
13500
13501   const char *group = "ZeViewer";
13502   theCommands.Add("vinit",
13503           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13504     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13505   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13506     "\n\t\t:     [-display displayName]"
13507   #endif
13508     "\n\t\t: Creates new View window with specified name viewName."
13509     "\n\t\t: By default the new view is created in the viewer and in"
13510     "\n\t\t: graphic driver shared with active view."
13511     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13512     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13513     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13514 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13515     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13516     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13517 #endif
13518     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13519     "\n\t\t:  -width, -height width and heigth of window respectively."
13520     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13521     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13522     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13523     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13524     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13525     __FILE__,VInit,group);
13526   theCommands.Add("vclose" ,
13527     "[view_id [keep_context=0|1]]\n"
13528     "or vclose ALL - to remove all created views\n"
13529     " - removes view(viewer window) defined by its view_id.\n"
13530     " - keep_context: by default 0; if 1 and the last view is deleted"
13531     " the current context is not removed.",
13532     __FILE__,VClose,group);
13533   theCommands.Add("vactivate" ,
13534     "vactivate view_id [-noUpdate]"
13535     " - activates view(viewer window) defined by its view_id",
13536     __FILE__,VActivate,group);
13537   theCommands.Add("vviewlist",
13538     "vviewlist [format={tree, long}]"
13539     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13540     " - format: format of result output, if tree the output is a tree view;"
13541     "otherwise it's a list of full view names. By default format = tree",
13542     __FILE__,VViewList,group);
13543   theCommands.Add("vhelp" ,
13544     "vhelp            : display help on the viewer commands",
13545     __FILE__,VHelp,group);
13546   theCommands.Add("vtop" ,
13547     "vtop or <T>      : Top view. Orientation +X+Y" ,
13548     __FILE__,VTop,group);
13549   theCommands.Add("vbottom" ,
13550     "vbottom          : Bottom view. Orientation +X-Y" ,
13551     __FILE__,VBottom,group);
13552   theCommands.Add("vleft" ,
13553     "vleft            : Left view. Orientation -Y+Z" ,
13554     __FILE__,VLeft,group);
13555   theCommands.Add("vright" ,
13556     "vright           : Right view. Orientation +Y+Z" ,
13557     __FILE__,VRight,group);
13558   theCommands.Add("vaxo" ,
13559     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13560     __FILE__,VAxo,group);
13561   theCommands.Add("vfront" ,
13562     "vfront           : Front view. Orientation +X+Z" ,
13563     __FILE__,VFront,group);
13564   theCommands.Add("vback" ,
13565     "vback            : Back view. Orientation -X+Z" ,
13566     __FILE__,VBack,group);
13567   theCommands.Add("vpick" ,
13568     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13569     VPick,group);
13570   theCommands.Add("vfit",
13571     "vfit or <F> [-selected] [-noupdate]"
13572     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13573     __FILE__,VFit,group);
13574   theCommands.Add ("vfitarea",
13575     "vfitarea x1 y1 x2 y2"
13576     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13577     "\n\t\t: Fit view to show area located between two points"
13578     "\n\t\t: given in world 2D or 3D corrdinates.",
13579     __FILE__, VFitArea, group);
13580   theCommands.Add ("vzfit", "vzfit [scale]\n"
13581     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13582     "   \"scale\" - specifies factor to scale computed z range.\n",
13583     __FILE__, VZFit, group);
13584   theCommands.Add("vrepaint",
13585             "vrepaint [-immediate] [-continuous FPS]"
13586     "\n\t\t: force redraw of active View"
13587     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13588     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13589     "\n\t\t:                0 means no continuous rendering,"
13590     "\n\t\t:               -1 means non-stop redraws,"
13591     "\n\t\t:               >0 specifies target framerate,",
13592     __FILE__,VRepaint,group);
13593   theCommands.Add("vclear",
13594     "vclear          : vclear"
13595     "\n\t\t: remove all the object from the viewer",
13596     __FILE__,VClear,group);
13597   theCommands.Add (
13598     "vbackground",
13599     "Changes background or some background settings.\n"
13600     "\n"
13601     "Usage:\n"
13602     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13603     "  vbackground -imageMode FillType\n"
13604     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13605     "  vbackground -gradientMode FillMethod\n"
13606     "  vbackground -color Color\n"
13607     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13608     "  vbackground -default -color Color\n"
13609     "  vbackground -help\n"
13610     "\n"
13611     "Options:\n"
13612     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13613     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13614     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13615     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13616     "  -color        (-col):                               sets background color\n"
13617     "  -default      (-def):                               sets background default gradient or color\n"
13618     "  -help         (-h):                                 outputs short help message\n"
13619     "\n"
13620     "Arguments:\n"
13621     "  Color:      Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13622     "                                  or reals within the range [0.0, 1.0]\n"
13623     "              ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13624     "              #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13625     "  FillMethod: one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13626     "CORNER4\n"
13627     "  FillType:   one of CENTERED, TILED, STRETCH, NONE\n"
13628     "  ImageFile:  a name of the file with the image used as a background\n",
13629     __FILE__,
13630     vbackground,
13631     group);
13632   theCommands.Add ("vsetbg",
13633                    "Loads image as background."
13634                    "\n\t\t: vsetbg ImageFile [FillType]"
13635                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13636                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13637                    __FILE__,
13638                    vbackground,
13639                    group);
13640   theCommands.Add ("vsetbgmode",
13641                    "Changes background image fill type."
13642                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13643                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13644                    __FILE__,
13645                    vbackground,
13646                    group);
13647   theCommands.Add ("vsetgradientbg",
13648                    "Mounts gradient background."
13649                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13650                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13651                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13652                    __FILE__,
13653                    vbackground,
13654                    group);
13655   theCommands.Add ("vsetgrbgmode",
13656                    "Changes gradient background fill method."
13657                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13658                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13659                    __FILE__,
13660                    vbackground,
13661                    group);
13662   theCommands.Add ("vsetcolorbg",
13663                    "Sets background color."
13664                    "\n\t\t: vsetcolorbg [-color] Color."
13665                    "\n\t\t: Alias for 'vbackground -color Color'.",
13666                    __FILE__,
13667                    vbackground,
13668                    group);
13669   theCommands.Add ("vsetdefaultbg",
13670                    "Sets default viewer background fill color (flat/gradient)."
13671                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13672                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13673                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13674                    "\n\t\t: vsetdefaultbg [-color] Color"
13675                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13676                    __FILE__,
13677                    vbackground,
13678                    group);
13679   theCommands.Add("vscale",
13680     "vscale          : vscale X Y Z",
13681     __FILE__,VScale,group);
13682   theCommands.Add("vzbufftrihedron",
13683             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13684     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13685     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13686     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13687     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13688     "\n\t\t: Displays a trihedron",
13689     __FILE__,VZBuffTrihedron,group);
13690   theCommands.Add("vrotate",
13691     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13692     "\n                : Option -mouseStart starts rotation according to the mouse position"
13693     "\n                : Option -mouseMove continues rotation with angle computed"
13694     "\n                : from last and new mouse position."
13695     "\n                : vrotate AX AY AZ [X Y Z]",
13696     __FILE__,VRotate,group);
13697   theCommands.Add("vzoom",
13698     "vzoom           : vzoom coef",
13699     __FILE__,VZoom,group);
13700   theCommands.Add("vpan",
13701     "vpan            : vpan dx dy",
13702     __FILE__,VPan,group);
13703   theCommands.Add("vcolorscale",
13704     "vcolorscale name [-noupdate|-update] [-demo]"
13705     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13706     "\n\t\t:       [-font HeightFont=20]"
13707     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13708     "\n\t\t:       [-smoothTransition {on|off}=off]"
13709     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13710     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13711     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13712     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13713     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13714     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13715     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13716     "\n\t\t:       [-xy Left=0 Bottom=0]"
13717     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13718     "\n\t\t:  -colors   - set colors for all intervals"
13719     "\n\t\t:  -color    - set color for specific interval"
13720     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
13721     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
13722     "\n\t\t:              at border means the value inbetween neighbor intervals,"
13723     "\n\t\t:              at center means the center value within current interval"
13724     "\n\t\t:  -labels   - set labels for all intervals"
13725     "\n\t\t:  -freeLabels - same as -labels but does not require"
13726     "\n\t\t:              matching the number of intervals"
13727     "\n\t\t:  -label    - set label for specific interval"
13728     "\n\t\t:  -title    - set title"
13729     "\n\t\t:  -reversed - setup smooth color transition between intervals"
13730     "\n\t\t:  -smoothTransition - swap colorscale direction"
13731     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
13732     __FILE__, VColorScale, group);
13733   theCommands.Add("vgraduatedtrihedron",
13734     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
13735     "\t[-namefont Name] [-valuesfont Name]\n"
13736     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
13737     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
13738     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
13739     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
13740     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
13741     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
13742     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
13743     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
13744     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
13745     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
13746     " - Displays or erases graduated trihedron"
13747     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
13748     " - namefont - font of axes names. Default: Arial\n"
13749     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
13750     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
13751     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
13752     " - valuesfont - font of axes values. Default: Arial\n"
13753     " - xcolor, ycolor, zcolor - color of axis and values\n"
13754     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
13755     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
13756     __FILE__,VGraduatedTrihedron,group);
13757   theCommands.Add("vtile" ,
13758             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
13759     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
13760     "\n\t\t:  -totalSize the size of virtual bigger viewport"
13761     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
13762     "\n\t\t:  -lowerLeft tile offset as lower left corner"
13763     "\n\t\t:  -upperLeft tile offset as upper left corner",
13764     __FILE__, VTile, group);
13765   theCommands.Add("vzlayer",
13766               "vzlayer [layerId]"
13767       "\n\t\t:         [-add|-delete|-get|-settings]"
13768       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
13769       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
13770       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
13771       "\n\t\t: ZLayer list management:"
13772       "\n\t\t:   -add      add new z layer to viewer and print its id"
13773       "\n\t\t:   -delete   delete z layer"
13774       "\n\t\t:   -get      print sequence of z layers"
13775       "\n\t\t:   -settings print status of z layer settings"
13776       "\n\t\t:   -disable  disables given setting"
13777       "\n\t\t:   -enable   enables  given setting",
13778     __FILE__,VZLayer,group);
13779   theCommands.Add("vlayerline",
13780     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
13781     __FILE__,VLayerLine,group);
13782   theCommands.Add("vgrid",
13783               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
13784       "\n\t\t:       [-step X Y] [-size DX DY]"
13785       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
13786     __FILE__, VGrid, group);
13787   theCommands.Add ("vpriviledgedplane",
13788     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
13789     "\n\t\t:   Ox, Oy, Oz - plane origin"
13790     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
13791     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
13792     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
13793     __FILE__, VPriviledgedPlane, group);
13794   theCommands.Add ("vconvert",
13795     "vconvert v [Mode={window|view}]"
13796     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
13797     "\n\t\t: vconvert x y z [Mode={window|grid}]"
13798     "\n\t\t:   window - convert to window coordinates, pixels"
13799     "\n\t\t:   view   - convert to view projection plane"
13800     "\n\t\t:   grid   - convert to model coordinates, given on grid"
13801     "\n\t\t:   ray    - convert projection ray to model coordiantes"
13802     "\n\t\t: - vconvert v window : convert view to window;"
13803     "\n\t\t: - vconvert v view   : convert window to view;"
13804     "\n\t\t: - vconvert x y window : convert view to window;"
13805     "\n\t\t: - vconvert x y view : convert window to view;"
13806     "\n\t\t: - vconvert x y : convert window to model;"
13807     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
13808     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
13809     "\n\t\t: - vconvert x y z window : convert model to window;"
13810     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
13811     "\n\t\t: Converts the given coordinates to window/view/model space.",
13812     __FILE__, VConvert, group);
13813   theCommands.Add ("vfps",
13814     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
13815     __FILE__, VFps, group);
13816   theCommands.Add ("vgldebug",
13817             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
13818     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
13819     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
13820     "\n\t\t: Debug context can be requested only on Windows"
13821     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
13822     "\n\t\t:  -sync     - request synchronized debug GL context"
13823     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
13824     "\n\t\t:              which are suppressed by default,"
13825     "\n\t\t:  -glslCode - log GLSL program source code,"
13826     "\n\t\t:              which are suppressed by default,"
13827     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
13828     "\n\t\t:              which are suppressed by default",
13829     __FILE__, VGlDebug, group);
13830   theCommands.Add ("vvbo",
13831     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
13832     __FILE__, VVbo, group);
13833   theCommands.Add ("vstereo",
13834             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
13835     "\n\t\t:         [-anaglyph Filter]"
13836     "\n\t\t: Control stereo output mode. Available modes for -mode:"
13837     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
13838     "\n\t\t:                     requires driver support."
13839     "\n\t\t:                     Should be called BEFORE vinit!"
13840     "\n\t\t:  anaglyph         - Anaglyph glasses"
13841     "\n\t\t:  rowInterlaced    - row-interlaced display"
13842     "\n\t\t:  columnInterlaced - column-interlaced display"
13843     "\n\t\t:  chessBoard       - chess-board output"
13844     "\n\t\t:  sideBySide       - horizontal pair"
13845     "\n\t\t:  overUnder        - vertical   pair"
13846     "\n\t\t: Available Anaglyph filters for -anaglyph:"
13847     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
13848     "\n\t\t:  greenMagentaSimple",
13849     __FILE__, VStereo, group);
13850   theCommands.Add ("vcaps",
13851             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
13852     "\n\t\t:       [-compatibleProfile {0|1}]"
13853     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
13854     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
13855     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
13856     "\n\t\t: Modify particular graphic driver options:"
13857     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
13858     "\n\t\t:             built-in GLSL programs"
13859     "\n\t\t:            (requires compatible profile)"
13860     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
13861     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
13862     "\n\t\t:             arrays to GPU memory)"
13863     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
13864     "\n\t\t:  vsync    - switch VSync on or off"
13865     "\n\t\t:  winBuffer - allow using window buffer for rendering"
13866     "\n\t\t: Context creation options:"
13867     "\n\t\t:  softMode          - software OpenGL implementation"
13868     "\n\t\t:  compatibleProfile - backward-compatible profile"
13869     "\n\t\t:  quadbuffer        - QuadBuffer"
13870     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
13871     "\n\t\t: rendering paths producing the same visual result when"
13872     "\n\t\t: possible."
13873     "\n\t\t: Command is intended for testing old hardware compatibility.",
13874     __FILE__, VCaps, group);
13875   theCommands.Add ("vmemgpu",
13876     "vmemgpu [f]: print system-dependent GPU memory information if available;"
13877     " with f option returns free memory in bytes",
13878     __FILE__, VMemGpu, group);
13879   theCommands.Add ("vreadpixel",
13880     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
13881     " : Read pixel value for active view",
13882     __FILE__, VReadPixel, group);
13883   theCommands.Add("diffimage",
13884             "diffimage imageFile1 imageFile2 [diffImageFile]"
13885     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
13886     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
13887     "\n\t\t: Compare two images by content and generate difference image."
13888     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
13889     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
13890     __FILE__, VDiffImage, group);
13891   theCommands.Add ("vselect",
13892     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
13893     "- emulates different types of selection:\n"
13894     "- 1) single click selection\n"
13895     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
13896     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
13897     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
13898     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
13899     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
13900     " (partial inclusion - overlap - is not allowed by default)\n"
13901     "- 5) any of these selections with shift button pressed",
13902     __FILE__, VSelect, group);
13903   theCommands.Add ("vmoveto",
13904     "vmoveto [x y] [-reset]"
13905     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
13906     "\n\t\t:   -reset resets current highlighting",
13907     __FILE__, VMoveTo, group);
13908   theCommands.Add ("vviewparams",
13909               "vviewparams [-args] [-scale [s]]"
13910       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
13911       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
13912       "\n\t\t: Manage current view parameters or prints all"
13913       "\n\t\t: current values when called without argument."
13914       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
13915       "\n\t\t:   -eye  [x y z] prints or sets eye location"
13916       "\n\t\t:   -at   [x y z] prints or sets center of look"
13917       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
13918       "\n\t\t:   -proj [x y z] prints or sets direction of look"
13919       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
13920       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
13921       "\n\t\t:                 or changes the size of its maximum dimension"
13922       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
13923     __FILE__, VViewParams, group);
13924
13925   theCommands.Add("v2dmode",
13926     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
13927     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
13928     "\n\t\t:   mode   - switches On/Off rotation mode"
13929     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
13930     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
13931     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
13932     "\n\t\t: View camera position might be changed only by commands.",
13933     __FILE__, V2DMode, group);
13934
13935   theCommands.Add("vanimation", "Alias for vanim",
13936     __FILE__, VAnimation, group);
13937
13938   theCommands.Add("vanim",
13939             "List existing animations:"
13940     "\n\t\t:  vanim"
13941     "\n\t\t: Animation playback:"
13942     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
13943     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
13944     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
13945     "\n\t\t:   -freeLook skip camera animations"
13946     "\n\t\t:   -lockLoop disable any interactions"
13947     "\n\t\t:"
13948     "\n\t\t: Animation definition:"
13949     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
13950     "\n\t\t:        [start TimeSec] [duration TimeSec]"
13951     "\n\t\t:"
13952     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
13953     "\n\t\t: specifies nested animations."
13954     "\n\t\t: There is no syntax to explicitly add new animation,"
13955     "\n\t\t: and all non-existing animations within the name will be"
13956     "\n\t\t: implicitly created on first use (including parents)."
13957     "\n\t\t:"
13958     "\n\t\t: Each animation might define the SINGLE action (see below),"
13959     "\n\t\t: like camera transition, object transformation or custom callback."
13960     "\n\t\t: Child animations can be used for defining concurrent actions."
13961     "\n\t\t:"
13962     "\n\t\t: Camera animation:"
13963     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
13964     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
13965     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
13966     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
13967     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
13968     "\n\t\t:   -atX    camera Center positions pair"
13969     "\n\t\t:   -upX    camera Up directions pair"
13970     "\n\t\t:   -scaleX camera Scale factors pair"
13971     "\n\t\t: Object animation:"
13972     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
13973     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
13974     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
13975     "\n\t\t:   -locX   object Location points pair (translation)"
13976     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
13977     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
13978     "\n\t\t: Custom callback:"
13979     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
13980     "\n\t\t:   %Pts        overall animation presentation timestamp"
13981     "\n\t\t:   %LocalPts   local animation timestamp"
13982     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
13983     "\n\t\t:"
13984     "\n\t\t: Video recording:"
13985     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
13986     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
13987     "\n\t\t:             [-crf Value] [-preset Preset]"
13988     "\n\t\t:   -fps     video framerate"
13989     "\n\t\t:   -format  file format, container (matroska, etc.)"
13990     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
13991     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
13992     "\n\t\t:   -crf     constant rate factor (specific to codec)"
13993     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
13994     __FILE__, VAnimation, group);
13995
13996   theCommands.Add("vchangeselected",
13997     "vchangeselected shape"
13998     "- adds to shape to selection or remove one from it",
13999                 __FILE__, VChangeSelected, group);
14000   theCommands.Add ("vnbselected",
14001     "vnbselected"
14002     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
14003   theCommands.Add ("vcamera",
14004               "vcamera [PrsName] [-ortho] [-projtype]"
14005       "\n\t\t:         [-persp]"
14006       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
14007       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
14008       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
14009       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
14010       "\n\t\t: Manages camera parameters."
14011       "\n\t\t: Displays frustum when presntation name PrsName is specified."
14012       "\n\t\t: Prints current value when option called without argument."
14013       "\n\t\t: Orthographic camera:"
14014       "\n\t\t:   -ortho      activate orthographic projection"
14015       "\n\t\t: Perspective camera:"
14016       "\n\t\t:   -persp      activate perspective  projection (mono)"
14017       "\n\t\t:   -fovy       field of view in y axis, in degrees"
14018       "\n\t\t:   -distance   distance of eye from camera center"
14019       "\n\t\t: Stereoscopic camera:"
14020       "\n\t\t:   -stereo     perspective  projection (stereo)"
14021       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
14022       "\n\t\t:   -rightEye   perspective  projection (right eye)"
14023       "\n\t\t:   -iod        intraocular distance value"
14024       "\n\t\t:   -iodType    distance type, absolute or relative"
14025       "\n\t\t:   -zfocus     stereographic focus value"
14026       "\n\t\t:   -zfocusType focus type, absolute or relative",
14027     __FILE__, VCamera, group);
14028   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
14029     "- vautozfit [on={1|0}] [scale]\n"
14030     "    Prints or changes parameters of automatic z-fit mode:\n"
14031     "   \"on\" - turns automatic z-fit on or off\n"
14032     "   \"scale\" - specifies factor to scale computed z range.\n",
14033     __FILE__, VAutoZFit, group);
14034   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
14035     "   vzrange                - without parameters shows current values\n"
14036     "   vzrange [znear] [zfar] - applies provided values to view",
14037     __FILE__,VZRange, group);
14038   theCommands.Add ("vpurgedisplay",
14039     "vpurgedisplay"
14040     "- removes structures which don't belong to objects displayed in neutral point",
14041     __FILE__, VPurgeDisplay, group);
14042   theCommands.Add("vsetviewsize",
14043     "vsetviewsize size",
14044     __FILE__,VSetViewSize,group);
14045   theCommands.Add("vmoveview",
14046     "vmoveview Dx Dy Dz [Start = 1|0]",
14047     __FILE__,VMoveView,group);
14048   theCommands.Add("vtranslateview",
14049     "vtranslateview Dx Dy Dz [Start = 1|0)]",
14050     __FILE__,VTranslateView,group);
14051   theCommands.Add("vturnview",
14052     "vturnview Ax Ay Az [Start = 1|0]",
14053     __FILE__,VTurnView,group);
14054   theCommands.Add("vtextureenv",
14055     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
14056     "or user-defined file and optionally applying texture mapping parameters\n"
14057     "                  Usage:\n"
14058     "                  vtextureenv off - disables environment mapping\n"
14059     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
14060     "                              std_texture = (0..7)\n"
14061     "                              rep         = {clamp|repeat}\n"
14062     "                              mod         = {decal|modulate}\n"
14063     "                              flt         = {nearest|bilinear|trilinear}\n"
14064     "                              ss, st      - scale factors for s and t texture coordinates\n"
14065     "                              ts, tt      - translation for s and t texture coordinates\n"
14066     "                              rot         - texture rotation angle in degrees",
14067     __FILE__, VTextureEnv, group);
14068   theCommands.Add("vhlr",
14069             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
14070       "\n\t\t: Hidden Line Removal algorithm."
14071       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
14072       "\n\t\t:   -algoType   type of HLR algorithm.\n",
14073     __FILE__,VHLR,group);
14074   theCommands.Add("vhlrtype",
14075               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
14076       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
14077       "\n\t\t:   'algo' - exact HLR algorithm is applied"
14078       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
14079       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
14080     __FILE__,VHLRType,group);
14081   theCommands.Add("vclipplane",
14082               "vclipplane planeName [{0|1}]"
14083       "\n\t\t:   [-equation1 A B C D]"
14084       "\n\t\t:   [-equation2 A B C D]"
14085       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
14086       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
14087       "\n\t\t:   [-maxPlanes]"
14088       "\n\t\t:   [-capping {0|1}]"
14089       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
14090       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
14091       "\n\t\t:       [-texRotate Angle]"
14092       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
14093       "\n\t\t:       [-useObjShader {0|1}]"
14094       "\n\t\t: Clipping planes management:"
14095       "\n\t\t:   -maxPlanes   print plane limit for view"
14096       "\n\t\t:   -delete      delete plane with given name"
14097       "\n\t\t:   {off|on|0|1} turn clipping on/off"
14098       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
14099       "\n\t\t:                applied to active View when list is omitted"
14100       "\n\t\t:   -equation A B C D change plane equation"
14101       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
14102       "\n\t\t: Capping options:"
14103       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
14104       "\n\t\t:   -color R G B          set capping color"
14105       "\n\t\t:   -transparency Value   set capping transparency 0..1"
14106       "\n\t\t:   -texName Texture      set capping texture"
14107       "\n\t\t:   -texScale SX SY       set capping tex scale"
14108       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
14109       "\n\t\t:   -texRotate Angle      set capping tex rotation"
14110       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
14111       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
14112       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
14113       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
14114       __FILE__, VClipPlane, group);
14115   theCommands.Add("vdefaults",
14116                "vdefaults [-absDefl value]"
14117        "\n\t\t:           [-devCoeff value]"
14118        "\n\t\t:           [-angDefl value]"
14119        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
14120     , __FILE__, VDefaults, group);
14121   theCommands.Add("vlight",
14122     "tool to manage light sources, without arguments shows list of lights."
14123     "\n    Main commands: "
14124     "\n      '-clear' to clear lights"
14125     "\n      '-{def}aults' to load deafault lights"
14126     "\n      '-add' <type> to add any light source"
14127     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
14128     "\n      'change' <lightId> to edit light source with specified lightId"
14129     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
14130     "\n        -layer Id"
14131     "\n        -{pos}ition X Y Z"
14132     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
14133     "\n        -color colorName"
14134     "\n        -{head}light 0|1"
14135     "\n        -{sm}oothness value"
14136     "\n        -{int}ensity value"
14137     "\n        -{constAtten}uation value"
14138     "\n        -{linearAtten}uation value"
14139     "\n        -angle angleDeg"
14140     "\n        -{spotexp}onent value"
14141     "\n        -local|-global"
14142     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
14143     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
14144     __FILE__, VLight, group);
14145   theCommands.Add("vraytrace",
14146             "vraytrace [0|1]"
14147     "\n\t\t: Turns on/off ray-tracing renderer."
14148     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
14149     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
14150     __FILE__, VRenderParams, group);
14151   theCommands.Add("vrenderparams",
14152     "\n    Manages rendering parameters: "
14153     "\n      '-raster'                   Disables GPU ray-tracing"
14154     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
14155     "\n      '-lineFeather  > 0'         Sets line feather factor"
14156     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
14157     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
14158     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
14159     "\n      '-rendScale    value        Rendering resolution scale factor"
14160     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
14161     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
14162     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
14163     "\n      '-reflections  on|off'      Enables/disables specular reflections"
14164     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
14165     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
14166     "\n      '-gi           on|off'      Enables/disables global illumination effects"
14167     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
14168     "\n      '-env          on|off'      Enables/disables environment map background"
14169     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
14170     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
14171     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
14172     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
14173     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
14174     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
14175     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
14176     "\n      '-shadingModel model'       Controls shading model from enumeration"
14177     "\n                                  color, flat, gouraud, phong"
14178     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
14179     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
14180     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
14181     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
14182     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
14183     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
14184     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
14185     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
14186     "\n                                  Show/hide performance counters (flags can be combined)"
14187     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
14188     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
14189     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
14190     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
14191     "\n                                        set state to check structures culled previously."
14192     "\n    Unlike vcaps, these parameters dramatically change visual properties."
14193     "\n    Command is intended to control presentation quality depending on"
14194     "\n    hardware capabilities and performance.",
14195     __FILE__, VRenderParams, group);
14196   theCommands.Add("vstatprofiler",
14197     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
14198     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
14199     "\n                |triagles|points|geomMem|textureMem|frameMem"
14200     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
14201     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
14202     "\n                [-noredraw]"
14203     "\n\t\t: Prints rendering statistics."
14204     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
14205     "\n\t\t:   else - print all performance counters set previously."
14206     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
14207     __FILE__, VStatProfiler, group);
14208   theCommands.Add ("vplace",
14209             "vplace dx dy"
14210     "\n\t\t: Places the point (in pixels) at the center of the window",
14211     __FILE__, VPlace, group);
14212   theCommands.Add("vxrotate",
14213     "vxrotate",
14214     __FILE__,VXRotate,group);
14215
14216     theCommands.Add("vmanipulator",
14217       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
14218       "\n    tool to create and manage AIS manipulators."
14219       "\n    Options: "
14220       "\n      '-attach AISObject'                 attach manipulator to AISObject"
14221       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
14222       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
14223       "\n      '-enableModes    {0|1}'             enable modes when attaching"
14224       "\n      '-detach'                           detach manipulator"
14225       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
14226       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
14227       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
14228       "\n      '-move x y z'                     - move attached object"
14229       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
14230       "\n      '-scale factor'                   - scale attached object"
14231       "\n      '-autoActivate      {0|1}'        - set activation on detection"
14232       "\n      '-followTranslation {0|1}'        - set following translation transform"
14233       "\n      '-followRotation    {0|1}'        - set following rotation transform"
14234       "\n      '-followDragging    {0|1}'        - set following dragging transform"
14235       "\n      '-gap value'                      - set gap between sub-parts"
14236       "\n      '-part axis mode    {0|1}'        - set visual part"
14237       "\n      '-parts axis mode   {0|1}'        - set visual part"
14238       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
14239       "\n      '-size value'                     - set size of manipulator"
14240       "\n      '-zoomable {0|1}'                 - set zoom persistence",
14241     __FILE__, VManipulator, group);
14242
14243   theCommands.Add("vselprops",
14244     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
14245     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
14246     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
14247     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
14248     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
14249     "\n    -pickStrategy {first|topmost} : defines picking strategy"
14250     "\n                            'first'   to pick first acceptable (default)"
14251     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
14252     "\n    -pixTol    value        : sets up pixel tolerance"
14253     "\n    -dispMode  dispMode     : sets display mode for highlighting"
14254     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
14255     "\n    -color     {name|r g b} : sets highlight color"
14256     "\n    -transp    value        : sets transparency coefficient for highlight"
14257     "\n    -material  material     : sets highlight material"
14258     "\n    -print                  : prints current state of all mentioned parameters",
14259     __FILE__, VSelectionProperties, group);
14260   theCommands.Add ("vhighlightselected",
14261                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
14262                    __FILE__, VSelectionProperties, group);
14263
14264   theCommands.Add ("vseldump",
14265                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
14266                    "\n\t\t: Generate an image based on detection results:"
14267                    "\n\t\t:   depth       normalized depth values"
14268                    "\n\t\t:   unnormDepth unnormalized depth values"
14269                    "\n\t\t:   object      color of detected object"
14270                    "\n\t\t:   owner       color of detected owner"
14271                    "\n\t\t:   selMode     color of selection mode"
14272                    "\n\t\t:   entity      color of etected entity",
14273                    __FILE__, VDumpSelectionImage, group);
14274
14275 #if defined(_WIN32)
14276   theCommands.Add("vprogressive",
14277     "vprogressive",
14278     __FILE__, VProgressiveMode, group);
14279 #endif
14280 }
14281