0029367: Visualization - simplify interface of V3d_View and V3d_Viewer
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18 #include <ViewerTest.hxx>
19
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_CameraFrustum.hxx>
23 #include <AIS_ColorScale.hxx>
24 #include <AIS_InteractiveContext.hxx>
25 #include <AIS_ListOfInteractive.hxx>
26 #include <AIS_ListIteratorOfListOfInteractive.hxx>
27 #include <AIS_Manipulator.hxx>
28 #include <AIS_ViewCube.hxx>
29 #include <AIS_Shape.hxx>
30 #include <Aspect_DisplayConnection.hxx>
31 #include <Aspect_Grid.hxx>
32 #include <Aspect_TypeOfLine.hxx>
33 #include <Draw.hxx>
34 #include <Draw_Appli.hxx>
35 #include <Draw_Interpretor.hxx>
36 #include <Draw_ProgressIndicator.hxx>
37 #include <gp_Dir.hxx>
38 #include <gp_Pln.hxx>
39 #include <gp_Pnt.hxx>
40 #include <Graphic3d_ArrayOfPolylines.hxx>
41 #include <Graphic3d_AspectFillArea3d.hxx>
42 #include <Graphic3d_AspectMarker3d.hxx>
43 #include <Graphic3d_ClipPlane.hxx>
44 #include <Graphic3d_CubeMapPacked.hxx>
45 #include <Graphic3d_CubeMapSeparate.hxx>
46 #include <Graphic3d_GraduatedTrihedron.hxx>
47 #include <Graphic3d_NameOfTextureEnv.hxx>
48 #include <Graphic3d_Texture2Dmanual.hxx>
49 #include <Graphic3d_TextureEnv.hxx>
50 #include <Graphic3d_TextureParams.hxx>
51 #include <Graphic3d_TypeOfTextureFilter.hxx>
52 #include <Image_AlienPixMap.hxx>
53 #include <Image_Diff.hxx>
54 #include <Image_VideoRecorder.hxx>
55 #include <Message_ProgressSentry.hxx>
56 #include <NCollection_DataMap.hxx>
57 #include <NCollection_List.hxx>
58 #include <NCollection_Vector.hxx>
59 #include <OSD.hxx>
60 #include <OSD_Timer.hxx>
61 #include <OpenGl_GraphicDriver.hxx>
62 #include <Prs3d_ShadingAspect.hxx>
63 #include <Prs3d_Drawer.hxx>
64 #include <Prs3d_LineAspect.hxx>
65 #include <Prs3d_Root.hxx>
66 #include <Prs3d_Text.hxx>
67 #include <Select3D_SensitivePrimitiveArray.hxx>
68 #include <TColStd_HSequenceOfAsciiString.hxx>
69 #include <TColStd_SequenceOfInteger.hxx>
70 #include <TColStd_HSequenceOfReal.hxx>
71 #include <TColgp_Array1OfPnt2d.hxx>
72 #include <TColStd_MapOfAsciiString.hxx>
73 #include <ViewerTest_AutoUpdater.hxx>
74 #include <ViewerTest_EventManager.hxx>
75 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
76 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
77 #include <ViewerTest_CmdParser.hxx>
78 #include <ViewerTest_V3dView.hxx>
79 #include <V3d_AmbientLight.hxx>
80 #include <V3d_DirectionalLight.hxx>
81 #include <V3d_PositionalLight.hxx>
82 #include <V3d_SpotLight.hxx>
83
84 #include <tcl.h>
85
86 #include <cstdlib>
87
88 #if defined(_WIN32)
89   #include <WNT_WClass.hxx>
90   #include <WNT_Window.hxx>
91 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
92   #include <Cocoa_Window.hxx>
93 #else
94   #include <Xw_Window.hxx>
95   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
96   #include <X11/Xutil.h>
97   #include <tk.h>
98 #endif
99
100 //==============================================================================
101 //  VIEWER GLOBAL VARIABLES
102 //==============================================================================
103
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
106
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
109
110 #if defined(_WIN32)
111 static Handle(WNT_Window)& VT_GetWindow() {
112   static Handle(WNT_Window) WNTWin;
113   return WNTWin;
114 }
115 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
116 static Handle(Cocoa_Window)& VT_GetWindow()
117 {
118   static Handle(Cocoa_Window) aWindow;
119   return aWindow;
120 }
121 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
122 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
123
124 #else
125 static Handle(Xw_Window)& VT_GetWindow(){
126   static Handle(Xw_Window) XWWin;
127   return XWWin;
128 }
129
130 static void VProcessEvents(ClientData,int);
131 #endif
132
133 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
134 {
135   static Handle(Aspect_DisplayConnection) aDisplayConnection;
136   return aDisplayConnection;
137 }
138
139 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
140 {
141   GetDisplayConnection() = theDisplayConnection;
142 }
143
144 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
145 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
146 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
147 static OpenGl_Caps ViewerTest_myDefaultCaps;
148
149 static void OSWindowSetup();
150
151 static struct
152 {
153   Quantity_Color FlatColor;
154   Quantity_Color GradientColor1;
155   Quantity_Color GradientColor2;
156   Aspect_GradientFillMethod FillMethod;
157 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
158
159 //==============================================================================
160 //  EVENT GLOBAL VARIABLES
161 //==============================================================================
162
163 Standard_Boolean TheIsAnimating = Standard_False;
164
165 namespace
166 {
167
168   //! Checks if some set is a subset of other set
169   //! @tparam TheSuperSet the type of the superset
170   //! @tparam TheSubSet the type of the subset
171   //! @param theSuperSet the superset
172   //! @param theSubSet the subset to be checked
173   //! @return true if the superset includes subset, or false otherwise
174   template <typename TheSuperSet, typename TheSubSet>
175   static bool includes (const TheSuperSet& theSuperSet, const TheSubSet& theSubSet)
176   {
177     return std::includes (theSuperSet.begin(), theSuperSet.end(), theSubSet.begin(), theSubSet.end());
178   }
179
180   //! A variable set of keys for command-line options.
181   //! It includes a set of mandatory keys and a set of all possible keys.
182   class CommandOptionKeyVariableSet
183   {
184   public:
185     //! Default constructor
186     CommandOptionKeyVariableSet()
187     {
188     }
189
190     //! Constructor
191     //! @param theMandatoryKeySet the set of the mandatory option keys
192     //! @param theAdditionalKeySet the set of additional options that could be omitted
193     CommandOptionKeyVariableSet (
194       const ViewerTest_CommandOptionKeySet& theMandatoryKeySet,
195       const ViewerTest_CommandOptionKeySet& theAdditionalKeySet = ViewerTest_CommandOptionKeySet())
196     : myMandatoryKeySet (theMandatoryKeySet)
197     {
198       std::set_union (theMandatoryKeySet.begin(),
199                       theMandatoryKeySet.end(),
200                       theAdditionalKeySet.begin(),
201                       theAdditionalKeySet.end(),
202                       std::inserter (myFullKeySet, myFullKeySet.begin()));
203     }
204
205     //! Checks if the set of option keys fits to the current variable set (it must contain all mandatory keys
206     //! and be contained in the full key set)
207     //! @param theCheckedKeySet the set of option keys to be checked
208     bool IsInSet (const ViewerTest_CommandOptionKeySet& theCheckedKeySet) const
209     {
210       return includes (theCheckedKeySet, myMandatoryKeySet) && includes (myFullKeySet, theCheckedKeySet);
211     }
212
213   private:
214     //! A set of mandatory command-line option keys
215     ViewerTest_CommandOptionKeySet myMandatoryKeySet;
216
217     //! A full set of command-line option keys (includes mandatory and additional option keys)
218     ViewerTest_CommandOptionKeySet myFullKeySet;
219   };
220
221   //! Gets some code by its name
222   //! @tparam TheCode the type of a code to be found
223   //! @param theCodeNameMap the map from code names to codes
224   //! @param theCodeName the name of a code to be found
225   //! @param theCode the code to be found
226   //! @return true if a code is found, or false otherwise
227   template <typename TheCode>
228   static bool getSomeCodeByName (const std::map<TCollection_AsciiString, TheCode>& theCodeNameMap,
229                                  TCollection_AsciiString                           theCodeName,
230                                  TheCode&                                          theCode)
231   {
232     theCodeName.LowerCase();
233     const typename std::map<TCollection_AsciiString, TheCode>::const_iterator aCodeIterator = theCodeNameMap.find (
234       theCodeName);
235     if (aCodeIterator == theCodeNameMap.end())
236     {
237       return false;
238     }
239     theCode = aCodeIterator->second;
240     return true;
241   }
242
243   // Defines possible commands related to background changing
244   enum BackgroundCommand
245   {
246     BackgroundCommand_Main,              //!< The main command that manages other commands through options
247     BackgroundCommand_Image,             //!< Sets an image as a background
248     BackgroundCommand_ImageMode,         //!< Changes a background image mode
249     BackgroundCommand_Gradient,          //!< Sets a gradient as a background
250     BackgroundCommand_GradientMode,      //!< Changes a background gradient mode
251     BackgroundCommand_Color,             //!< Fills background with a specified color
252     BackgroundCommand_Default            //!< Sets the background default color or gradient
253   };
254
255   //! Map from background command names to its codes
256   typedef std::map<TCollection_AsciiString, BackgroundCommand> BackgroundCommandNameMap;
257
258   //! Creates a map from background command names to its codes
259   //! @return a map from background command names to its codes
260   static BackgroundCommandNameMap createBackgroundCommandNameMap()
261   {
262     BackgroundCommandNameMap aBackgroundCommandNameMap;
263     aBackgroundCommandNameMap["vbackground"]      = BackgroundCommand_Main;
264     aBackgroundCommandNameMap["vsetbg"]           = BackgroundCommand_Image;
265     aBackgroundCommandNameMap["vsetbgmode"]       = BackgroundCommand_ImageMode;
266     aBackgroundCommandNameMap["vsetgradientbg"]   = BackgroundCommand_Gradient;
267     aBackgroundCommandNameMap["vsetgrbgmode"]     = BackgroundCommand_GradientMode;
268     aBackgroundCommandNameMap["vsetcolorbg"]      = BackgroundCommand_Color;
269     aBackgroundCommandNameMap["vsetdefaultbg"]    = BackgroundCommand_Default;
270     return aBackgroundCommandNameMap;
271   }
272
273   //! Gets a background command by its name
274   //! @param theBackgroundCommandName the name of the background command
275   //! @param theBackgroundCommand the background command to be found
276   //! @return true if a background command is found, or false otherwise
277   static bool getBackgroundCommandByName (const TCollection_AsciiString& theBackgroundCommandName,
278                                           BackgroundCommand&             theBackgroundCommand)
279   {
280     static const BackgroundCommandNameMap THE_BACKGROUND_COMMAND_NAME_MAP = createBackgroundCommandNameMap();
281     return getSomeCodeByName (THE_BACKGROUND_COMMAND_NAME_MAP, theBackgroundCommandName, theBackgroundCommand);
282   }
283
284   //! Map from background image fill method names to its codes
285   typedef std::map<TCollection_AsciiString, Aspect_FillMethod> BackgroundImageFillMethodNameMap;
286
287   //! Creates a map from background image fill method names to its codes
288   //! @return a map from background image fill method names to its codes
289   static BackgroundImageFillMethodNameMap createBackgroundImageFillMethodNameMap()
290   {
291     BackgroundImageFillMethodNameMap aBackgroundImageFillMethodNameMap;
292     aBackgroundImageFillMethodNameMap["none"]     = Aspect_FM_NONE;
293     aBackgroundImageFillMethodNameMap["centered"] = Aspect_FM_CENTERED;
294     aBackgroundImageFillMethodNameMap["tiled"]    = Aspect_FM_TILED;
295     aBackgroundImageFillMethodNameMap["stretch"]  = Aspect_FM_STRETCH;
296     return aBackgroundImageFillMethodNameMap;
297   }
298
299   //! Gets a background image fill method by its name
300   //! @param theBackgroundImageFillMethodName the name of the background image fill method
301   //! @param theBackgroundImageFillMethod the background image fill method to be found
302   //! @return true if a background image fill method is found, or false otherwise
303   static bool getBackgroundImageFillMethodByName (const TCollection_AsciiString& theBackgroundImageFillMethodName,
304                                                   Aspect_FillMethod&             theBackgroundImageFillMethod)
305   {
306     static const BackgroundImageFillMethodNameMap THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP =
307       createBackgroundImageFillMethodNameMap();
308     return getSomeCodeByName (THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP,
309                               theBackgroundImageFillMethodName,
310                               theBackgroundImageFillMethod);
311   }
312
313   //! Map from background gradient fill method names to its codes
314   typedef std::map<TCollection_AsciiString, Aspect_GradientFillMethod> BackgroundGradientFillMethodNameMap;
315
316   //! Creates a map from background gradient fill method names to its codes
317   //! @return a map from background gradient fill method names to its codes
318   static BackgroundGradientFillMethodNameMap createBackgroundGradientFillMethodNameMap()
319   {
320     BackgroundGradientFillMethodNameMap aBackgroundGradientFillMethodNameMap;
321     aBackgroundGradientFillMethodNameMap["none"]       = Aspect_GFM_NONE;
322     aBackgroundGradientFillMethodNameMap["hor"]        = Aspect_GFM_HOR;
323     aBackgroundGradientFillMethodNameMap["horizontal"] = Aspect_GFM_HOR;
324     aBackgroundGradientFillMethodNameMap["ver"]        = Aspect_GFM_VER;
325     aBackgroundGradientFillMethodNameMap["vertical"]   = Aspect_GFM_VER;
326     aBackgroundGradientFillMethodNameMap["diag1"]      = Aspect_GFM_DIAG1;
327     aBackgroundGradientFillMethodNameMap["diagonal1"]  = Aspect_GFM_DIAG1;
328     aBackgroundGradientFillMethodNameMap["diag2"]      = Aspect_GFM_DIAG2;
329     aBackgroundGradientFillMethodNameMap["diagonal2"]  = Aspect_GFM_DIAG2;
330     aBackgroundGradientFillMethodNameMap["corner1"]    = Aspect_GFM_CORNER1;
331     aBackgroundGradientFillMethodNameMap["corner2"]    = Aspect_GFM_CORNER2;
332     aBackgroundGradientFillMethodNameMap["corner3"]    = Aspect_GFM_CORNER3;
333     aBackgroundGradientFillMethodNameMap["corner4"]    = Aspect_GFM_CORNER4;
334     return aBackgroundGradientFillMethodNameMap;
335   }
336
337   //! Gets a gradient fill method by its name
338   //! @param theBackgroundGradientFillMethodName the name of the gradient fill method
339   //! @param theBackgroundGradientFillMethod the gradient fill method to be found
340   //! @return true if a gradient fill method is found, or false otherwise
341   static bool getBackgroundGradientFillMethodByName (const TCollection_AsciiString& theBackgroundGradientFillMethodName,
342                                                      Aspect_GradientFillMethod&     theBackgroundGradientFillMethod)
343   {
344     static const BackgroundGradientFillMethodNameMap THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP =
345       createBackgroundGradientFillMethodNameMap();
346     return getSomeCodeByName (THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP,
347                               theBackgroundGradientFillMethodName,
348                               theBackgroundGradientFillMethod);
349   }
350
351   //! Changes the background in accordance with passed command line options
352   class BackgroundChanger
353   {
354   public:
355     //! Constructor. Prepares the command parser
356     BackgroundChanger()
357     {
358       prepareCommandParser();
359     }
360
361     //! Processes the command line and changes the background
362     //! @param theDrawInterpretor the interpreter of the Draw Harness application
363     //! @param theNumberOfCommandLineArguments the number of passed command line arguments
364     //! @param theCommandLineArguments the array of command line arguments
365     bool ProcessCommandLine (Draw_Interpretor&        theDrawInterpretor,
366                              const Standard_Integer   theNumberOfCommandLineArguments,
367                              const char* const* const theCommandLineArguments)
368     {
369       const char* const aBackgroundCommandName = theCommandLineArguments[0];
370       BackgroundCommand aBackgroundCommand = BackgroundCommand_Main;
371       if (!getBackgroundCommandByName (aBackgroundCommandName, aBackgroundCommand))
372       {
373         return false;
374       }
375       addCommandDescription (aBackgroundCommand);
376       myCommandParser.Parse (theNumberOfCommandLineArguments, theCommandLineArguments);
377       return processCommandOptions (aBackgroundCommandName, aBackgroundCommand, theDrawInterpretor);
378     }
379
380   private:
381     //! The type of functions that are able to set gradient background filling
382     typedef void SetGradientFunction (const Quantity_Color& /* theColor1 */,
383                                       const Quantity_Color& /* theColor2 */,
384                                       const Aspect_GradientFillMethod /* theGradientMode */);
385
386     //! The type of functions that are able to fill a background with a specific color
387     typedef void SetColorFunction (const Quantity_Color& /* theColor */);
388
389     //! the command parser used to parse command line options and its arguments
390     ViewerTest_CmdParser myCommandParser;
391
392     //! the option key for the command that sets an image as a background
393     ViewerTest_CommandOptionKey myImageOptionKey;
394
395     //! the option key for the command that sets a background image fill type
396     ViewerTest_CommandOptionKey myImageModeOptionKey;
397
398     //! the option key for the command that sets a gradient filling for the background
399     ViewerTest_CommandOptionKey myGradientOptionKey;
400
401     //! the option key for the command that sets a background gradient filling method
402     ViewerTest_CommandOptionKey myGradientModeOptionKey;
403
404     //! the option key for the command that fills background with a specific color
405     ViewerTest_CommandOptionKey myColorOptionKey;
406
407     //! the option key for the command that sets default background gradient or color
408     ViewerTest_CommandOptionKey myDefaultOptionKey;
409
410     //! the option key for the command that sets an environment cubemap as a background
411     ViewerTest_CommandOptionKey myCubeMapOptionKey;
412
413     //! the option key for the command that defines order of tiles in one image packed cubemap
414     ViewerTest_CommandOptionKey myCubeMapOrderOptionKey;
415
416     //! the option key for the command that sets inversion of Z axis for background cubemap
417     ViewerTest_CommandOptionKey myCubeMapInvertedZOptionKey;
418
419     //! the option key for the command that allows skip IBL map generation
420     ViewerTest_CommandOptionKey myCubeMapDoNotGenPBREnvOptionKey;
421
422     //! the variable set of options that are allowed for the old scenario (without any option passed)
423     CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
424
425     //! the variable set of options that are allowed for setting an environment cubemap as background
426     CommandOptionKeyVariableSet myCubeMapOptionVariableSet;
427
428     //! the variable set of options that are allowed for setting an image as a background
429     CommandOptionKeyVariableSet myImageOptionVariableSet;
430
431     //! the variable set of options that are allowed for setting a background image fill type
432     CommandOptionKeyVariableSet myImageModeOptionVariableSet;
433
434     //! the variable set of options that are allowed for setting a gradient filling for the background
435     CommandOptionKeyVariableSet myGradientOptionVariableSet;
436
437     //! the variable set of options that are allowed for setting a background gradient filling method
438     CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
439
440     //! the variable set of options that are allowed for filling a background with a specific color
441     CommandOptionKeyVariableSet myColorOptionVariableSet;
442
443     //! the variable set of options that are allowed for setting a default background gradient
444     CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
445
446     //! the variable set of options that are allowed for setting a default background color
447     CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
448
449     //! the variable set of options that are allowed for printing help
450     CommandOptionKeyVariableSet myHelpOptionVariableSet;
451
452     //! Adds options to command parser
453     void addOptionsToCommandParser()
454     {
455       myImageOptionKey     = myCommandParser.AddOption ("imageFile|image|imgFile|img",
456                                                     "filename of image used as background");
457       myImageModeOptionKey = myCommandParser.AddOption (
458         "imageMode|imgMode", "image fill type, should be one of CENTERED, TILED, STRETCH, NONE");
459       myGradientOptionKey = myCommandParser.AddOption ("gradient|grad|gr",
460                                                        "sets background gradient starting and ending colors");
461       myGradientModeOptionKey =
462         myCommandParser.AddOption ("gradientMode|gradMode|gradMd|grMode|grMd",
463                                    "gradient fill method, should be one of NONE, HOR[IZONTAL], VER[TICAL], "
464                                    "DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, CORNER4");
465       myColorOptionKey   = myCommandParser.AddOption ("color|col", "background color");
466       myDefaultOptionKey = myCommandParser.AddOption ("default|def", "sets background default gradient or color");
467
468       myCubeMapOptionKey           = myCommandParser.AddOption ("cubemap|cmap|cm", "background cubemap");
469       myCubeMapOrderOptionKey      = myCommandParser.AddOption ("order|o", "order of sides in one image packed cubemap");
470       myCubeMapInvertedZOptionKey = myCommandParser.AddOption (
471         "invertedz|invz|iz", "whether Z axis is inverted or not during background cubemap rendering");
472       myCubeMapDoNotGenPBREnvOptionKey = myCommandParser.AddOption ("nopbrenv", "whether IBL map generation should be skipped");
473     }
474
475     //! Creates option sets used to determine if a passed option set is valid or not
476     void createOptionSets()
477     {
478       ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
479       anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
480       myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
481
482       ViewerTest_CommandOptionKeySet aCubeMapOptionSet;
483       aCubeMapOptionSet.insert (myCubeMapOptionKey);
484       ViewerTest_CommandOptionKeySet aCubeMapAdditionalOptionKeySet;
485       aCubeMapAdditionalOptionKeySet.insert (myCubeMapInvertedZOptionKey);
486       aCubeMapAdditionalOptionKeySet.insert (myCubeMapDoNotGenPBREnvOptionKey);
487       aCubeMapAdditionalOptionKeySet.insert (myCubeMapOrderOptionKey);
488       myCubeMapOptionVariableSet     = CommandOptionKeyVariableSet (aCubeMapOptionSet, aCubeMapAdditionalOptionKeySet);
489
490       ViewerTest_CommandOptionKeySet anImageOptionSet;
491       anImageOptionSet.insert (myImageOptionKey);
492       ViewerTest_CommandOptionKeySet anImageModeOptionSet;
493       anImageModeOptionSet.insert (myImageModeOptionKey);
494       myImageOptionVariableSet     = CommandOptionKeyVariableSet (anImageOptionSet, anImageModeOptionSet);
495       myImageModeOptionVariableSet = CommandOptionKeyVariableSet (anImageModeOptionSet);
496
497       ViewerTest_CommandOptionKeySet aGradientOptionSet;
498       aGradientOptionSet.insert (myGradientOptionKey);
499       ViewerTest_CommandOptionKeySet aGradientModeOptionSet;
500       aGradientModeOptionSet.insert (myGradientModeOptionKey);
501       myGradientOptionVariableSet     = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
502       myGradientModeOptionVariableSet = CommandOptionKeyVariableSet (aGradientModeOptionSet);
503
504       ViewerTest_CommandOptionKeySet aColorOptionSet;
505       aColorOptionSet.insert (myColorOptionKey);
506       myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
507
508       aGradientOptionSet.insert (myDefaultOptionKey);
509       myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
510       aColorOptionSet.insert (myDefaultOptionKey);
511       myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
512
513       ViewerTest_CommandOptionKeySet aHelpOptionSet;
514       aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
515       myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
516     }
517
518     //! Prepares the command parser. Adds options and creates option sets used to determine
519     //! if a passed option set is valid or not
520     void prepareCommandParser()
521     {
522       addOptionsToCommandParser();
523       createOptionSets();
524     }
525
526     //! Adds a command description to the command parser
527     //! @param theBackgroundCommand the key of the command which description is added to the command parser
528     void addCommandDescription (const BackgroundCommand theBackgroundCommand)
529     {
530       std::string aDescription;
531       bool        isMainCommand = false;
532       switch (theBackgroundCommand)
533       {
534         case BackgroundCommand_Main:
535           aDescription  = "Command: vbackground (changes background or some background settings)";
536           isMainCommand = true;
537           break;
538         case BackgroundCommand_Image:
539           aDescription = "Command: vsetbg (loads image as a background)";
540           break;
541         case BackgroundCommand_ImageMode:
542           aDescription = "Command: vsetbgmode (changes background fill type)";
543           break;
544         case BackgroundCommand_Gradient:
545           aDescription = "Command: vsetgradientbg (mounts gradient background)";
546           break;
547         case BackgroundCommand_GradientMode:
548           aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
549           break;
550         case BackgroundCommand_Color:
551           aDescription = "Command: vsetcolorbg (sets color background)";
552           break;
553         case BackgroundCommand_Default:
554           aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
555           break;
556         default:
557           return;
558       }
559       if (!isMainCommand)
560       {
561         aDescription += "\nThis command is obsolete. Use vbackground instead.";
562       }
563       myCommandParser.SetDescription (aDescription);
564     }
565
566     //! Check if a viewer is needed to be initialized
567     //! @param theBackgroundCommand the key of the command that changes the background
568     //! @return true if processing was successful, or false otherwise
569     bool checkViewerIsNeeded (const BackgroundCommand theBackgroundCommand) const
570     {
571       const bool                           isMain             = (theBackgroundCommand == BackgroundCommand_Main);
572       const ViewerTest_CommandOptionKeySet aUsedOptions       = myCommandParser.GetUsedOptions();
573       const bool                           aViewerIsNotNeeded =
574         (theBackgroundCommand == BackgroundCommand_Default)
575         || (myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
576         || (myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
577         || myHelpOptionVariableSet.IsInSet (aUsedOptions);
578       return !aViewerIsNotNeeded;
579     }
580
581     //! Check if a viewer is initialized
582     //! @param theBackgroundCommandName the name of the command that changes the background
583     //! @param theDrawInterpretor the interpreter of the Draw Harness application
584     //! @return true if a viewer is initialized, or false otherwise
585     static bool checkViewerIsInitialized (const char* const theBackgroundCommandName,
586                                           Draw_Interpretor& theDrawInterpretor)
587     {
588       const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
589       if (anAISContext.IsNull())
590       {
591         theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
592         return false;
593       }
594       return true;
595     }
596
597     //! Processes command options
598     //! @param theBackgroundCommandName the name of the command that changes the background
599     //! @param theBackgroundCommand the key of the command that changes the background
600     //! @param theDrawInterpretor the interpreter of the Draw Harness application
601     //! @return true if processing was successful, or false otherwise
602     bool processCommandOptions (const char* const       theBackgroundCommandName,
603                                 const BackgroundCommand theBackgroundCommand,
604                                 Draw_Interpretor&       theDrawInterpretor) const
605     {
606       if (myCommandParser.HasNoOption())
607       {
608         return printHelp (theBackgroundCommandName, theDrawInterpretor);
609       }
610       if (checkViewerIsNeeded (theBackgroundCommand)
611           && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
612       {
613         return false;
614       }
615       if (myCommandParser.HasOnlyUnnamedOption())
616       {
617         return processUnnamedOption (theBackgroundCommand);
618       }
619       return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
620     }
621
622     //! Processes the unnamed option
623     //! @param theBackgroundCommand the key of the command that changes the background
624     //! @return true if processing was successful, or false otherwise
625     bool processUnnamedOption (const BackgroundCommand theBackgroundCommand) const
626     {
627       switch (theBackgroundCommand)
628       {
629         case BackgroundCommand_Main:
630           return false;
631         case BackgroundCommand_Image:
632           return processImageUnnamedOption();
633         case BackgroundCommand_ImageMode:
634           return processImageModeUnnamedOption();
635         case BackgroundCommand_Gradient:
636           return processGradientUnnamedOption();
637         case BackgroundCommand_GradientMode:
638           return processGradientModeUnnamedOption();
639         case BackgroundCommand_Color:
640           return processColorUnnamedOption();
641         case BackgroundCommand_Default:
642           return processDefaultUnnamedOption();
643         default:
644           return false;
645       }
646     }
647
648     //! Processes the image unnamed option
649     //! @return true if processing was successful, or false otherwise
650     bool processImageUnnamedOption() const
651     {
652       const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
653         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
654       if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
655       {
656         return false;
657       }
658       std::string anImageFileName;
659       if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
660       {
661         return false;
662       }
663       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
664       if (aNumberOfImageUnnamedOptionArguments == 2)
665       {
666         std::string anImageModeString;
667         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
668         {
669           return false;
670         }
671         if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
672         {
673           return false;
674         }
675       }
676       setImage (anImageFileName.c_str(), anImageMode);
677       return true;
678     }
679
680     //! Processes the image mode unnamed option
681     //! @return true if processing was successful, or false otherwise
682     bool processImageModeUnnamedOption() const
683     {
684       return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
685     }
686
687     //! Processes the gradient unnamed option
688     //! @param theSetGradient the function used to set a background gradient filling
689     //! @return true if processing was successful, or false otherwise
690     bool processGradientUnnamedOption (SetGradientFunction* const theSetGradient = setGradient) const
691     {
692       const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
693         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
694       if (aNumberOfGradientUnnamedOptionArguments < 2)
695       {
696         return false;
697       }
698
699       Standard_Integer anArgumentIndex = 0;
700       Quantity_Color   aColor1;
701       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
702       {
703         return false;
704       }
705       if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
706       {
707         return false;
708       }
709
710       Quantity_Color aColor2;
711       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
712       {
713         return false;
714       }
715       if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
716       {
717         return false;
718       }
719
720       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
721       if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
722       {
723         std::string anGradientModeString;
724
725         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
726                                   anArgumentIndex,
727                                   anGradientModeString))
728         {
729           return false;
730         }
731         if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
732         {
733           return false;
734         }
735         ++anArgumentIndex;
736       }
737       if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
738       {
739         return false;
740       }
741       theSetGradient (aColor1, aColor2, aGradientMode);
742       return true;
743     }
744
745     //! Processes the gradient mode unnamed option
746     //! @return true if processing was successful, or false otherwise
747     bool processGradientModeUnnamedOption() const
748     {
749       return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
750     }
751
752     //! Processes the color unnamed option
753     //! @param theSetColor the function used to set a background color
754     //! @return true if processing was successful, or false otherwise
755     bool processColorUnnamedOption (SetColorFunction* const theSetColor = setColor) const
756     {
757       return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
758     }
759
760     //! Processes the default back unnamed option
761     //! @return true if processing was successful, or false otherwise
762     bool processDefaultUnnamedOption() const
763     {
764       if (processGradientUnnamedOption (setDefaultGradient))
765       {
766         return true;
767       }
768       return processColorUnnamedOption (setDefaultColor);
769     }
770
771     //! Processes named options
772     //! @param theBackgroundCommandName the name of the command that changes the background
773     //! @param theBackgroundCommand the key of the command that changes the background
774     //! @param theDrawInterpretor the interpreter of the Draw Harness application
775     //! @return true if processing was successful, or false otherwise
776     bool processNamedOptions (const char* const       theBackgroundCommandName,
777                               const BackgroundCommand theBackgroundCommand,
778                               Draw_Interpretor&       theDrawInterpretor) const
779     {
780       const bool                           isMain       = (theBackgroundCommand == BackgroundCommand_Main);
781       const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
782       if (myCubeMapOptionVariableSet.IsInSet (aUsedOptions) && isMain)
783       {
784         return processCubeMapOptionSet();
785       }
786       if (myImageOptionVariableSet.IsInSet (aUsedOptions)
787           && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
788       {
789         return processImageOptionSet();
790       }
791       if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
792           && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
793       {
794         return processImageModeOptionSet();
795       }
796       if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
797           && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
798       {
799         return processGradientOptionSet();
800       }
801       if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
802           && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
803       {
804         return processGradientModeOptionSet();
805       }
806       if (myColorOptionVariableSet.IsInSet (aUsedOptions)
807           && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
808       {
809         return processColorOptionSet();
810       }
811       if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
812           || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
813               && (theBackgroundCommand == BackgroundCommand_Default)))
814       {
815         return processDefaultGradientOptionSet();
816       }
817       if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
818           || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
819       {
820         return processDefaultColorOptionSet();
821       }
822       if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
823       {
824         return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
825       }
826       return false;
827     }
828
829     //! Process the cubemap option set in named and unnamed case.
830     //! @return true if processing was successful, or false otherwise
831     bool processCubeMapOptionSet() const
832     {
833       NCollection_Array1<TCollection_AsciiString> aFilePaths;
834
835       if (!processCubeMapOptions (aFilePaths))
836       {
837         return false;
838       }
839
840       Graphic3d_CubeMapOrder anOrder = Graphic3d_CubeMapOrder::Default();
841
842       if (myCommandParser.HasOption (myCubeMapOrderOptionKey))
843       {
844         if (!processCubeMapOrderOptions (anOrder))
845         {
846           return false;
847         }
848       }
849
850       bool aZIsInverted = false;
851       if (myCommandParser.HasOption (myCubeMapInvertedZOptionKey))
852       {
853         if (!processCubeMapInvertedZOptionSet())
854         {
855           return false;
856         }
857         aZIsInverted = true;
858       }
859
860       bool aToGenPBREnv = true;
861       if (myCommandParser.HasOption (myCubeMapDoNotGenPBREnvOptionKey))
862       {
863         if (!processCubeMapDoNotGenPBREnvOptionSet())
864         {
865           return false;
866         }
867         aToGenPBREnv = false;
868       }
869
870       setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted, aToGenPBREnv);
871       return true;
872     }
873
874     //! Processes the image option set
875     //! @return true if processing was successful, or false otherwise
876     bool processImageOptionSet() const
877     {
878       std::string anImageFileName;
879       if (!processImageOption (anImageFileName))
880       {
881         return false;
882       }
883       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
884       if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
885       {
886         return false;
887       }
888       setImage (anImageFileName.c_str(), anImageMode);
889       return true;
890     }
891
892     //! Processes the image mode option set
893     //! @return true if processing was successful, or false otherwise
894     bool processImageModeOptionSet() const
895     {
896       return processImageModeOptionSet (myImageModeOptionKey);
897     }
898
899     //! Processes the image mode option set
900     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
901     //! @return true if processing was successful, or false otherwise
902     bool processImageModeOptionSet (const ViewerTest_CommandOptionKey theImageModeOptionKey) const
903     {
904       Aspect_FillMethod anImageMode = Aspect_FM_NONE;
905       if (!processImageModeOption (theImageModeOptionKey, anImageMode))
906       {
907         return false;
908       }
909       setImageMode (anImageMode);
910       return true;
911     }
912
913     //! Processes the gradient option set
914     //! @param theSetGradient the function used to set a background gradient filling
915     //! @return true if processing was successful, or false otherwise
916     bool processGradientOptionSet (SetGradientFunction* const theSetGradient = setGradient) const
917     {
918       Quantity_Color aColor1;
919       Quantity_Color aColor2;
920       if (!processGradientOption (aColor1, aColor2))
921       {
922         return false;
923       }
924       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
925       if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
926       {
927         return false;
928       }
929       theSetGradient (aColor1, aColor2, aGradientMode);
930       return true;
931     }
932
933     //! Processes the gradient mode option set
934     //! @return true if processing was successful, or false otherwise
935     bool processGradientModeOptionSet() const
936     {
937       return processGradientModeOptionSet (myGradientModeOptionKey);
938     }
939
940     //! Processes the gradient mode option set
941     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
942     //! @return true if processing was successful, or false otherwise
943     bool processGradientModeOptionSet (const ViewerTest_CommandOptionKey theGradientModeOptionKey) const
944     {
945       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
946       if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
947       {
948         return false;
949       }
950       setGradientMode (aGradientMode);
951       return true;
952     }
953
954     //! Processes the color option set
955     //! @param theSetColor the function used to set a background color
956     //! @return true if processing was successful, or false otherwise
957     bool processColorOptionSet (SetColorFunction* const theSetColor = setColor) const
958     {
959       return processColorOptionSet (myColorOptionKey, theSetColor);
960     }
961
962     //! Processes the default color option set
963     //! @return true if processing was successful, or false otherwise
964     bool processDefaultGradientOptionSet() const
965     {
966       return processGradientOptionSet (setDefaultGradient);
967     }
968
969     //! Processes the default gradient option set
970     //! @return true if processing was successful, or false otherwise
971     bool processDefaultColorOptionSet() const
972     {
973       return processColorOptionSet (setDefaultColor);
974     }
975
976     //! Processes the color option set
977     //! @param theColorOptionKey the key of the option that is interpreted as a color option
978     //! @param theSetColor the function used to set a background color
979     //! @return true if processing was successful, or false otherwise
980     bool processColorOptionSet (const ViewerTest_CommandOptionKey theColorOptionKey,
981                                 SetColorFunction* const           theSetColor = setColor) const
982     {
983       Quantity_Color aColor;
984       if (!processColorOption (theColorOptionKey, aColor))
985       {
986         return false;
987       }
988       theSetColor (aColor);
989       return true;
990     }
991
992     //! Processes the help option set
993     //! @param theBackgroundCommandName the name of the command that changes the background
994     //! @param theDrawInterpretor the interpreter of the Draw Harness application
995     //! @return true if processing was successful, or false otherwise
996     bool processHelpOptionSet (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor) const
997     {
998       const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
999         ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
1000       if (aNumberOfHelpOptionArguments != 0)
1001       {
1002         return false;
1003       }
1004       return printHelp (theBackgroundCommandName, theDrawInterpretor);
1005     }
1006
1007     //! Processes the cubemap option
1008     //! @param theFilePaths the array of filenames of cubemap sides
1009     //! @return true if processing was successful, or false otherwise
1010     bool processCubeMapOptions (NCollection_Array1<TCollection_AsciiString> &theFilePaths) const
1011     {
1012       const Standard_Integer aNumberOfCubeMapOptionArguments = myCommandParser.GetNumberOfOptionArguments (myCubeMapOptionKey);
1013
1014       if (aNumberOfCubeMapOptionArguments != 1
1015        && aNumberOfCubeMapOptionArguments != 6)
1016       {
1017         return false;
1018       }
1019
1020       theFilePaths.Resize(0, aNumberOfCubeMapOptionArguments - 1, Standard_False);
1021
1022       for (int i = 0; i < aNumberOfCubeMapOptionArguments; ++i)
1023       {
1024         std::string aCubeMapFileName;
1025         if (!myCommandParser.Arg (myCubeMapOptionKey, i, aCubeMapFileName))
1026         {
1027           return false;
1028         }
1029         theFilePaths[i] = aCubeMapFileName.c_str();
1030       }
1031
1032       return true;
1033     }
1034
1035     //! Processes the inverted z cubemap option
1036     //! @return true if processing was successful, or false otherwise
1037     bool processCubeMapInvertedZOptionSet () const
1038     {
1039       const Standard_Integer aNumberOfCubeMapZInversionOptionArguments =
1040         myCommandParser.GetNumberOfOptionArguments (myCubeMapInvertedZOptionKey);
1041
1042       if (aNumberOfCubeMapZInversionOptionArguments != 0)
1043       {
1044         return false;
1045       }
1046
1047       return true;
1048     }
1049
1050     //! Processes the option allowing to skip IBM maps generation
1051     //! @return true if processing was successful, or false otherwise
1052     bool processCubeMapDoNotGenPBREnvOptionSet() const
1053     {
1054       const Standard_Integer aNumberOfCubeMapDoNotGenPBREnvOptionArguments =
1055         myCommandParser.GetNumberOfOptionArguments(myCubeMapDoNotGenPBREnvOptionKey);
1056
1057       if (aNumberOfCubeMapDoNotGenPBREnvOptionArguments != 0)
1058       {
1059         return false;
1060       }
1061
1062       return true;
1063     }
1064
1065     //! Processes the tiles order option
1066     //! @param theOrder the array of indexes if cubemap sides in tile grid
1067     //! @return true if processing was successful, or false otherwise
1068     bool processCubeMapOrderOptions (Graphic3d_CubeMapOrder& theOrder) const
1069     {
1070       const Standard_Integer aNumberOfCubeMapOrderOptionArguments = myCommandParser.GetNumberOfOptionArguments(
1071         myCubeMapOrderOptionKey);
1072
1073       if (aNumberOfCubeMapOrderOptionArguments != 6)
1074       {
1075         return false;
1076       }
1077
1078
1079       for (unsigned int i = 0; i < 6; ++i)
1080       {
1081         std::string anOrderItem;
1082         if (!myCommandParser.Arg (myCubeMapOrderOptionKey, i, anOrderItem)) 
1083         {
1084           return false;
1085         }
1086
1087         theOrder.Set (Graphic3d_CubeMapSide (i),
1088                       static_cast<unsigned char> (Draw::Atoi (anOrderItem.c_str())));
1089       }
1090
1091       return theOrder.IsValid();
1092     }
1093
1094     //! Processes the image option
1095     //! @param theImageFileName the filename of the image to be used as a background
1096     //! @return true if processing was successful, or false otherwise
1097     bool processImageOption (std::string& theImageFileName) const
1098     {
1099       const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1100         myImageOptionKey);
1101       if (aNumberOfImageOptionArguments != 1)
1102       {
1103         return false;
1104       }
1105       std::string anImageFileName;
1106       if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
1107       {
1108         return false;
1109       }
1110       theImageFileName = anImageFileName;
1111       return true;
1112     }
1113
1114     //! Processes the image mode option
1115     //! @param theImageMode the fill type used for a background image
1116     //! @return true if processing was successful, or false otherwise
1117     bool processImageModeOption (Aspect_FillMethod& theImageMode) const
1118     {
1119       return processImageModeOption (myImageModeOptionKey, theImageMode);
1120     }
1121
1122     //! Processes the image mode option
1123     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
1124     //! @param theImageMode the fill type used for a background image
1125     //! @return true if processing was successful, or false otherwise
1126     bool processImageModeOption (const ViewerTest_CommandOptionKey theImageModeOptionKey,
1127                                  Aspect_FillMethod&                theImageMode) const
1128     {
1129       return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
1130     }
1131
1132     //! Processes the gradient option
1133     //! @param theColor1 the gradient starting color
1134     //! @param theColor2 the gradient ending color
1135     //! @return true if processing was successful, or false otherwise
1136     bool processGradientOption (Quantity_Color& theColor1, Quantity_Color& theColor2) const
1137     {
1138       Standard_Integer anArgumentIndex = 0;
1139       Quantity_Color   aColor1;
1140       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
1141       {
1142         return false;
1143       }
1144       Quantity_Color aColor2;
1145       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
1146       {
1147         return false;
1148       }
1149       const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1150         myGradientOptionKey);
1151       if (anArgumentIndex != aNumberOfGradientOptionArguments)
1152       {
1153         return false;
1154       }
1155       theColor1 = aColor1;
1156       theColor2 = aColor2;
1157       return true;
1158     }
1159
1160     //! Processes the gradient mode option
1161     //! @param theGradientMode the fill method used for a background gradient filling
1162     //! @return true if processing was successful, or false otherwise
1163     bool processGradientModeOption (Aspect_GradientFillMethod& theGradientMode) const
1164     {
1165       return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
1166     }
1167
1168     //! Processes the gradient mode option
1169     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
1170     //! @param theGradientMode the fill method used for a background gradient filling
1171     //! @return true if processing was successful, or false otherwise
1172     bool processGradientModeOption (const ViewerTest_CommandOptionKey theGradientModeOptionKey,
1173                                     Aspect_GradientFillMethod&        theGradientMode) const
1174     {
1175       return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1176     }
1177
1178     //! Processes some mode option
1179     //! @tparam TheMode the type of a mode to be processed
1180     //! @param theModeOptionKey the key of the option that is interpreted as a mode option
1181     //! @param theMode a mode to be processed
1182     //! @return true if processing was successful, or false otherwise
1183     template <typename TheMode>
1184     bool processModeOption (const ViewerTest_CommandOptionKey theModeOptionKey,
1185                             bool (*const theGetModeByName) (const TCollection_AsciiString& /* theModeName */,
1186                                                             TheMode& /* theMode */),
1187                             TheMode& theMode) const
1188     {
1189       const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1190         theModeOptionKey);
1191       if (aNumberOfModeOptionArguments != 1)
1192       {
1193         return false;
1194       }
1195       std::string aModeString;
1196       if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1197       {
1198         return false;
1199       }
1200       TheMode aMode = TheMode();
1201       if (!theGetModeByName (aModeString.c_str(), aMode))
1202       {
1203         return false;
1204       }
1205       theMode = aMode;
1206       return true;
1207     }
1208
1209     //! Processes the color option
1210     //! @param theColor a color used for filling a background
1211     //! @return true if processing was successful, or false otherwise
1212     bool processColorOption (Quantity_Color& theColor) const
1213     {
1214       return processColorOption (myColorOptionKey, theColor);
1215     }
1216
1217     //! Processes the color option
1218     //! @param theColorOptionKey the key of the option that is interpreted as a color option
1219     //! @param theColor a color used for filling a background
1220     //! @return true if processing was successful, or false otherwise
1221     bool processColorOption (const ViewerTest_CommandOptionKey theColorOptionKey, Quantity_Color& theColor) const
1222     {
1223       Standard_Integer anArgumentIndex = 0;
1224       Quantity_Color   aColor;
1225       if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1226       {
1227         return false;
1228       }
1229       const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1230         theColorOptionKey);
1231       if (anArgumentIndex != aNumberOfColorOptionArguments)
1232       {
1233         return false;
1234       }
1235       theColor = aColor;
1236       return true;
1237     }
1238
1239     //! Prints helping message
1240     //! @param theBackgroundCommandName the name of the command that changes the background
1241     //! @param theDrawInterpretor the interpreter of the Draw Harness application
1242     //! @return true if printing was successful, or false otherwise
1243     static bool printHelp (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor)
1244     {
1245       return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1246     }
1247
1248     //! Sets the cubemap as a background
1249     //! @param theFileNames the array of filenames of packed or multifile cubemap
1250     //! @param theOrder array of cubemap sides indexes mapping them from tiles in packed cubemap
1251     static void setCubeMap (const NCollection_Array1<TCollection_AsciiString>& theFileNames,
1252                             const Graphic3d_ValidatedCubeMapOrder              theOrder = Graphic3d_CubeMapOrder::Default(),
1253                             bool                                               theZIsInverted = false,
1254                             bool                                               theToGenPBREnv = true)
1255     {
1256       const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
1257       Handle(Graphic3d_CubeMap) aCubeMap;
1258
1259       if (theFileNames.Size() == 1)
1260         aCubeMap = new Graphic3d_CubeMapPacked(theFileNames[0], theOrder);
1261       else
1262         aCubeMap = new Graphic3d_CubeMapSeparate(theFileNames);
1263
1264       aCubeMap->SetZInversion (theZIsInverted);
1265
1266       aCubeMap->GetParams()->SetFilter(Graphic3d_TOTF_BILINEAR);
1267       aCubeMap->GetParams()->SetRepeat(Standard_False);
1268       aCubeMap->GetParams()->SetTextureUnit(Graphic3d_TextureUnit_EnvMap);
1269
1270       aCurrentView->SetBackgroundCubeMap (aCubeMap, theToGenPBREnv, Standard_True);
1271     }
1272
1273     //! Sets the image as a background
1274     //! @param theImageFileName the filename of the image to be used as a background
1275     //! @param theImageMode the fill type used for a background image
1276     static void setImage (const Standard_CString theImageFileName, const Aspect_FillMethod theImageMode)
1277     {
1278       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1279       aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1280     }
1281
1282     //! Sets the fill type used for a background image
1283     //! @param theImageMode the fill type used for a background image
1284     static void setImageMode (const Aspect_FillMethod theImageMode)
1285     {
1286       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1287       aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1288     }
1289
1290     //! Sets the gradient filling for a background
1291     //! @param theColor1 the gradient starting color
1292     //! @param theColor2 the gradient ending color
1293     //! @param theGradientMode the fill method used for a background gradient filling
1294     static void setGradient (const Quantity_Color&           theColor1,
1295                              const Quantity_Color&           theColor2,
1296                              const Aspect_GradientFillMethod theGradientMode)
1297     {
1298       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1299       aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1300     }
1301
1302     //! Sets the fill method used for a background gradient filling
1303     //! @param theGradientMode the fill method used for a background gradient filling
1304     static void setGradientMode (const Aspect_GradientFillMethod theGradientMode)
1305     {
1306       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1307       aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1308     }
1309
1310     //! Sets the color used for filling a background
1311     //! @param theColor the color used for filling a background
1312     static void setColor (const Quantity_Color& theColor)
1313     {
1314       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1315       aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1316       aCurrentView->SetBackgroundColor (theColor);
1317       aCurrentView->Update();
1318     }
1319
1320     //! Sets the gradient filling for a background in a default viewer
1321     //! @param theColor1 the gradient starting color
1322     //! @param theColor2 the gradient ending color
1323     //! @param theGradientMode the fill method used for a background gradient filling
1324     static void setDefaultGradient (const Quantity_Color&           theColor1,
1325                                     const Quantity_Color&           theColor2,
1326                                     const Aspect_GradientFillMethod theGradientMode)
1327     {
1328       ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1329       ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1330       ViewerTest_DefaultBackground.FillMethod     = theGradientMode;
1331       setDefaultGradient();
1332     }
1333
1334     //! Sets the color used for filling a background in a default viewer
1335     //! @param theColor the color used for filling a background
1336     static void setDefaultColor (const Quantity_Color& theColor)
1337     {
1338       ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
1339       ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
1340       ViewerTest_DefaultBackground.FillMethod     = Aspect_GFM_NONE;
1341       ViewerTest_DefaultBackground.FlatColor      = theColor;
1342       setDefaultGradient();
1343       setDefaultColor();
1344     }
1345
1346     //! Sets the gradient filling for a background in a default viewer.
1347     //! Gradient settings are taken from ViewerTest_DefaultBackground structure
1348     static void setDefaultGradient()
1349     {
1350       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1351              anInteractiveContextIterator (ViewerTest_myContexts);
1352            anInteractiveContextIterator.More();
1353            anInteractiveContextIterator.Next())
1354       {
1355         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1356         aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1357                                              ViewerTest_DefaultBackground.GradientColor2,
1358                                              ViewerTest_DefaultBackground.FillMethod);
1359       }
1360     }
1361
1362     //! Sets the color used for filling a background in a default viewer.
1363     //! The color value is taken from ViewerTest_DefaultBackground structure
1364     static void setDefaultColor()
1365     {
1366       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1367              anInteractiveContextIterator (ViewerTest_myContexts);
1368            anInteractiveContextIterator.More();
1369            anInteractiveContextIterator.Next())
1370       {
1371         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1372         aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1373       }
1374     }
1375   };
1376
1377 } // namespace
1378
1379 //==============================================================================
1380
1381 #ifdef _WIN32
1382 static LRESULT WINAPI ViewerWindowProc(
1383                                        HWND hwnd,
1384                                        UINT uMsg,
1385                                        WPARAM wParam,
1386                                        LPARAM lParam );
1387 static LRESULT WINAPI AdvViewerWindowProc(
1388   HWND hwnd,
1389   UINT uMsg,
1390   WPARAM wParam,
1391   LPARAM lParam );
1392 #endif
1393
1394
1395 //==============================================================================
1396 //function : WClass
1397 //purpose  :
1398 //==============================================================================
1399
1400 const Handle(Standard_Transient)& ViewerTest::WClass()
1401 {
1402   static Handle(Standard_Transient) theWClass;
1403 #if defined(_WIN32)
1404   if (theWClass.IsNull())
1405   {
1406     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
1407                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
1408                                 ::LoadCursor (NULL, IDC_ARROW));
1409   }
1410 #endif
1411   return theWClass;
1412 }
1413
1414 //==============================================================================
1415 //function : CreateName
1416 //purpose  : Create numerical name for new object in theMap
1417 //==============================================================================
1418 template <typename ObjectType>
1419 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1420                                     const TCollection_AsciiString& theDefaultString)
1421 {
1422   if (theObjectMap.IsEmpty())
1423     return theDefaultString + TCollection_AsciiString(1);
1424
1425   Standard_Integer aNextKey = 1;
1426   Standard_Boolean isFound = Standard_False;
1427   while (!isFound)
1428   {
1429     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1430     // Look for objects with default names
1431     if (theObjectMap.IsBound1(aStringKey))
1432     {
1433       aNextKey++;
1434     }
1435     else
1436       isFound = Standard_True;
1437   }
1438
1439   return theDefaultString + TCollection_AsciiString(aNextKey);
1440 }
1441
1442 //==============================================================================
1443 //structure : ViewerTest_Names
1444 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
1445 //==============================================================================
1446 struct ViewerTest_Names
1447 {
1448 private:
1449   TCollection_AsciiString myDriverName;
1450   TCollection_AsciiString myViewerName;
1451   TCollection_AsciiString myViewName;
1452
1453 public:
1454
1455   const TCollection_AsciiString& GetDriverName () const
1456   {
1457     return myDriverName;
1458   }
1459   void SetDriverName (const TCollection_AsciiString& theDriverName)
1460   {
1461     myDriverName = theDriverName;
1462   }
1463   const TCollection_AsciiString& GetViewerName () const
1464   {
1465     return myViewerName;
1466   }
1467   void SetViewerName (const TCollection_AsciiString& theViewerName)
1468   {
1469     myViewerName = theViewerName;
1470   }
1471   const TCollection_AsciiString& GetViewName () const
1472   {
1473     return myViewName;
1474   }
1475   void SetViewName (const TCollection_AsciiString& theViewName)
1476   {
1477     myViewName = theViewName;
1478   }
1479
1480   //===========================================================================
1481   //function : Constructor for ViewerTest_Names
1482   //purpose  : Get view, viewer, driver names from custom string
1483   //===========================================================================
1484
1485   ViewerTest_Names (const TCollection_AsciiString& theInputString)
1486   {
1487     TCollection_AsciiString aName(theInputString);
1488     if (theInputString.IsEmpty())
1489     {
1490       // Get current configuration
1491       if (ViewerTest_myDrivers.IsEmpty())
1492         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1493           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1494       else
1495         myDriverName = ViewerTest_myDrivers.Find2
1496         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1497
1498       if(ViewerTest_myContexts.IsEmpty())
1499       {
1500         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1501           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1502       }
1503       else
1504       {
1505         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
1506       }
1507
1508       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
1509     }
1510     else
1511     {
1512       // There is at least view name
1513       Standard_Integer aParserNumber = 0;
1514       for (Standard_Integer i = 0; i < 3; ++i)
1515       {
1516         Standard_Integer aParserPos = aName.SearchFromEnd("/");
1517         if(aParserPos != -1)
1518         {
1519           aParserNumber++;
1520           aName.Split(aParserPos-1);
1521         }
1522         else
1523           break;
1524       }
1525       if (aParserNumber == 0)
1526       {
1527         // Only view name
1528         if (!ViewerTest::GetAISContext().IsNull())
1529         {
1530           myDriverName = ViewerTest_myDrivers.Find2
1531           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1532           myViewerName = ViewerTest_myContexts.Find2
1533           (ViewerTest::GetAISContext());
1534         }
1535         else
1536         {
1537           // There is no opened contexts here, need to create names for viewer and driver
1538           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1539             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1540
1541           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1542             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1543         }
1544         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1545       }
1546       else if (aParserNumber == 1)
1547       {
1548         // Here is viewerName/viewName
1549         if (!ViewerTest::GetAISContext().IsNull())
1550           myDriverName = ViewerTest_myDrivers.Find2
1551           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1552         else
1553         {
1554           // There is no opened contexts here, need to create name for driver
1555           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1556             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1557         }
1558         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1559
1560         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1561       }
1562       else
1563       {
1564         //Here is driverName/viewerName/viewName
1565         myDriverName = TCollection_AsciiString(aName);
1566
1567         TCollection_AsciiString aViewerName(theInputString);
1568         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1569         myViewerName = TCollection_AsciiString(aViewerName);
1570
1571         myViewName = TCollection_AsciiString(theInputString);
1572       }
1573     }
1574   }
1575 };
1576
1577 //==============================================================================
1578 //function : FindContextByView
1579 //purpose  : Find AIS_InteractiveContext by View
1580 //==============================================================================
1581
1582 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1583 {
1584   Handle(AIS_InteractiveContext) anAISContext;
1585
1586   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1587        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1588   {
1589     if (anIter.Value()->CurrentViewer() == theView->Viewer())
1590        return anIter.Key2();
1591   }
1592   return anAISContext;
1593 }
1594
1595 //==============================================================================
1596 //function : IsWindowOverlapped
1597 //purpose  : Check if theWindow overlapp another view
1598 //==============================================================================
1599
1600 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
1601                                      const Standard_Integer thePxTop,
1602                                      const Standard_Integer thePxRight,
1603                                      const Standard_Integer thePxBottom,
1604                                      TCollection_AsciiString& theViewId)
1605 {
1606   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1607       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1608   {
1609     Standard_Integer aTop = 0,
1610       aLeft = 0,
1611       aRight = 0,
1612       aBottom = 0;
1613     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
1614     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1615         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
1616         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1617         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
1618     {
1619       theViewId = anIter.Key1();
1620       return Standard_True;
1621     }
1622   }
1623   return Standard_False;
1624 }
1625
1626 // Workaround: to create and delete non-orthographic views outside ViewerTest
1627 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1628 {
1629   ViewerTest_myViews.UnBind1 (theName);
1630 }
1631
1632 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1633                                const Handle(V3d_View)& theView)
1634 {
1635   ViewerTest_myViews.Bind (theName, theView);
1636 }
1637
1638 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1639 {
1640   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1641 }
1642
1643 //! Auxiliary tool performing continuous redraws of specified window.
1644 class ViewerTest_ContinuousRedrawer
1645 {
1646 public:
1647   //! Return global instance.
1648   static ViewerTest_ContinuousRedrawer& Instance()
1649   {
1650     static ViewerTest_ContinuousRedrawer aRedrawer;
1651     return aRedrawer;
1652   }
1653 public:
1654
1655   //! Destructor.
1656   ~ViewerTest_ContinuousRedrawer()
1657   {
1658     Stop();
1659   }
1660
1661   //! Start thread.
1662   void Start (const Handle(Aspect_Window)& theWindow,
1663               Standard_Real theTargetFps)
1664   {
1665     if (myWindow != theWindow
1666      || myTargetFps != theTargetFps)
1667     {
1668       Stop();
1669       myWindow = theWindow;
1670       myTargetFps = theTargetFps;
1671     }
1672     if (myThread.GetId() == 0)
1673     {
1674       myToStop = false;
1675       myThread.Run (this);
1676     }
1677   }
1678
1679   //! Stop thread.
1680   void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1681   {
1682     if (!theWindow.IsNull()
1683       && myWindow != theWindow)
1684     {
1685       return;
1686     }
1687
1688     {
1689       Standard_Mutex::Sentry aLock (myMutex);
1690       myToStop = true;
1691     }
1692     myThread.Wait();
1693     myToStop = false;
1694     myWindow.Nullify();
1695   }
1696
1697 private:
1698
1699   //! Thread loop.
1700   void doThreadLoop()
1701   {
1702     Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1703     OSD_Timer aTimer;
1704     aTimer.Start();
1705     Standard_Real aTimeOld = 0.0;
1706     const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1707     for (;;)
1708     {
1709       {
1710         Standard_Mutex::Sentry aLock (myMutex);
1711         if (myToStop)
1712         {
1713           return;
1714         }
1715       }
1716       if (myTargetFps > 0.0)
1717       {
1718         const Standard_Real aTimeNew  = aTimer.ElapsedTime();
1719         const Standard_Real aDuration = aTimeNew - aTimeOld;
1720         if (aDuration >= aTargetDur)
1721         {
1722           myWindow->InvalidateContent (aDisp);
1723           aTimeOld = aTimeNew;
1724         }
1725       }
1726       else
1727       {
1728         myWindow->InvalidateContent (aDisp);
1729       }
1730
1731       OSD::MilliSecSleep (1);
1732     }
1733   }
1734
1735   //! Thread creation callback.
1736   static Standard_Address doThreadWrapper (Standard_Address theData)
1737   {
1738     ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1739     aThis->doThreadLoop();
1740     return 0;
1741   }
1742
1743   //! Empty constructor.
1744   ViewerTest_ContinuousRedrawer()
1745   : myThread (doThreadWrapper),
1746     myTargetFps (0.0),
1747     myToStop (false) {}
1748
1749 private:
1750   Handle(Aspect_Window) myWindow;
1751   OSD_Thread      myThread;
1752   Standard_Mutex  myMutex;
1753   Standard_Real   myTargetFps;
1754   volatile bool   myToStop;
1755 };
1756
1757 //==============================================================================
1758 //function : ViewerInit
1759 //purpose  : Create the window viewer and initialize all the global variable
1760 //==============================================================================
1761
1762 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1763                                                 const Standard_Integer thePxTop,
1764                                                 const Standard_Integer thePxWidth,
1765                                                 const Standard_Integer thePxHeight,
1766                                                 const TCollection_AsciiString& theViewName,
1767                                                 const TCollection_AsciiString& theDisplayName,
1768                                                 const Handle(V3d_View)& theViewToClone)
1769 {
1770   // Default position and dimension of the viewer window.
1771   // Note that left top corner is set to be sufficiently small to have
1772   // window fit in the small screens (actual for remote desktops, see #23003).
1773   // The position corresponds to the window's client area, thus some
1774   // gap is added for window frame to be visible.
1775   Standard_Integer aPxLeft   = 20;
1776   Standard_Integer aPxTop    = 40;
1777   Standard_Integer aPxWidth  = 409;
1778   Standard_Integer aPxHeight = 409;
1779   Standard_Boolean toCreateViewer = Standard_False;
1780   if (!theViewToClone.IsNull())
1781   {
1782     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1783   }
1784
1785   Handle(OpenGl_GraphicDriver) aGraphicDriver;
1786   ViewerTest_Names aViewNames(theViewName);
1787   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1788     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1789
1790   if (thePxLeft != 0)
1791     aPxLeft = thePxLeft;
1792   if (thePxTop != 0)
1793     aPxTop = thePxTop;
1794   if (thePxWidth != 0)
1795     aPxWidth = thePxWidth;
1796   if (thePxHeight != 0)
1797     aPxHeight = thePxHeight;
1798
1799   // Get graphic driver (create it or get from another view)
1800   const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1801   if (isNewDriver)
1802   {
1803     // Get connection string
1804   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1805     if (!theDisplayName.IsEmpty())
1806     {
1807       SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1808     }
1809     else
1810     {
1811       ::Display* aDispX = NULL;
1812       // create dedicated display connection instead of reusing Tk connection
1813       // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
1814       /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
1815       Tcl_Interp* aTclInterp = aCommands.Interp();
1816       Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
1817       aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
1818       SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
1819     }
1820   #else
1821     (void)theDisplayName; // avoid warning on unused argument
1822     SetDisplayConnection (new Aspect_DisplayConnection ());
1823   #endif
1824
1825     if (Draw_VirtualWindows)
1826     {
1827       // don't waste the time waiting for VSync when window is not displayed on the screen
1828       ViewerTest_myDefaultCaps.swapInterval = 0;
1829       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
1830       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
1831     }
1832     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection(), false);
1833     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
1834     aGraphicDriver->InitContext();
1835
1836     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1837     toCreateViewer = Standard_True;
1838   }
1839   else
1840   {
1841     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
1842   }
1843
1844   //Dispose the window if input parameters are default
1845   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
1846   {
1847     Standard_Integer aTop = 0,
1848                      aLeft = 0,
1849                      aRight = 0,
1850                      aBottom = 0,
1851                      aScreenWidth = 0,
1852                      aScreenHeight = 0;
1853
1854     // Get screen resolution
1855 #if defined(_WIN32) || defined(__WIN32__)
1856     RECT aWindowSize;
1857     GetClientRect(GetDesktopWindow(), &aWindowSize);
1858     aScreenHeight = aWindowSize.bottom;
1859     aScreenWidth = aWindowSize.right;
1860 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1861     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1862 #else
1863     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1864     aScreenWidth = WidthOfScreen(aScreen);
1865     aScreenHeight = HeightOfScreen(aScreen);
1866 #endif
1867
1868     TCollection_AsciiString anOverlappedViewId("");
1869
1870     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
1871     {
1872       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1873
1874       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1875         && aRight + 2*aPxWidth + 40 > aScreenWidth)
1876       {
1877         if (aBottom + aPxHeight + 40 > aScreenHeight)
1878         {
1879           aPxLeft = 20;
1880           aPxTop = 40;
1881           break;
1882         }
1883         aPxLeft = 20;
1884         aPxTop = aBottom + 40;
1885       }
1886       else
1887         aPxLeft = aRight + 20;
1888     }
1889   }
1890
1891   // Get viewer name
1892   TCollection_AsciiString aTitle("3D View - ");
1893   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1894
1895   // Change name of current active window
1896   if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
1897   {
1898     aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
1899   }
1900
1901   // Create viewer
1902   Handle(V3d_Viewer) a3DViewer;
1903   // If it's the single view, we first look for empty context
1904   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1905   {
1906     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1907       anIter(ViewerTest_myContexts);
1908     if (anIter.More())
1909       ViewerTest::SetAISContext (anIter.Value());
1910     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1911   }
1912   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1913   {
1914     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1915     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1916   }
1917   else if (a3DViewer.IsNull())
1918   {
1919     toCreateViewer = Standard_True;
1920     a3DViewer = new V3d_Viewer(aGraphicDriver);
1921     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1922     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1923                                            ViewerTest_DefaultBackground.GradientColor2,
1924                                            ViewerTest_DefaultBackground.FillMethod);
1925   }
1926
1927   // AIS context setup
1928   if (ViewerTest::GetAISContext().IsNull() ||
1929       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1930   {
1931     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
1932     ViewerTest::SetAISContext (aContext);
1933     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1934   }
1935   else
1936   {
1937     ViewerTest::ResetEventManager();
1938   }
1939
1940   // Create window
1941 #if defined(_WIN32)
1942   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
1943                                     Handle(WNT_WClass)::DownCast (WClass()),
1944                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
1945                                     aPxLeft, aPxTop,
1946                                     aPxWidth, aPxHeight,
1947                                     Quantity_NOC_BLACK);
1948 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1949   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1950                                      aPxLeft, aPxTop,
1951                                      aPxWidth, aPxHeight);
1952   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
1953 #else
1954   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1955                                   aTitle.ToCString(),
1956                                   aPxLeft, aPxTop,
1957                                   aPxWidth, aPxHeight);
1958 #endif
1959   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
1960
1961   // View setup
1962   Handle(V3d_View) aView;
1963   if (!theViewToClone.IsNull())
1964   {
1965     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
1966   }
1967   else
1968   {
1969     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
1970   }
1971
1972   aView->SetWindow (VT_GetWindow());
1973   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
1974
1975   ViewerTest::CurrentView(aView);
1976   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
1977
1978   // Setup for X11 or NT
1979   OSWindowSetup();
1980
1981   // Set parameters for V3d_View and V3d_Viewer
1982   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1983   aV3dView->SetComputedMode(Standard_False);
1984
1985   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1986   if (toCreateViewer)
1987   {
1988     a3DViewer->SetDefaultLights();
1989     a3DViewer->SetLightOn();
1990   }
1991
1992 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1993   if (isNewDriver)
1994   {
1995     ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1996     Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1997   }
1998 #endif
1999
2000   VT_GetWindow()->Map();
2001
2002   // Set the handle of created view in the event manager
2003   ViewerTest::ResetEventManager();
2004
2005   ViewerTest::CurrentView()->Redraw();
2006
2007   aView.Nullify();
2008   a3DViewer.Nullify();
2009
2010   return aViewNames.GetViewName();
2011 }
2012
2013 //==============================================================================
2014 //function : RedrawAllViews
2015 //purpose  : Redraw all created views
2016 //==============================================================================
2017 void ViewerTest::RedrawAllViews()
2018 {
2019   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
2020   for (; aViewIt.More(); aViewIt.Next())
2021   {
2022     const Handle(V3d_View)& aView = aViewIt.Key2();
2023     aView->Redraw();
2024   }
2025 }
2026
2027 //==============================================================================
2028 //function : Vinit
2029 //purpose  : Create the window viewer and initialize all the global variable
2030 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
2031 //==============================================================================
2032
2033 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2034 {
2035   TCollection_AsciiString aViewName, aDisplayName;
2036   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
2037   Handle(V3d_View) aCopyFrom;
2038   TCollection_AsciiString aName, aValue;
2039   int is2dMode = -1;
2040   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
2041   {
2042     const TCollection_AsciiString anArg = theArgVec[anArgIt];
2043     TCollection_AsciiString anArgCase = anArg;
2044     anArgCase.LowerCase();
2045     if (anArgIt + 1 < theArgsNb
2046      && anArgCase == "-name")
2047     {
2048       aViewName = theArgVec[++anArgIt];
2049     }
2050     else if (anArgIt + 1 < theArgsNb
2051           && (anArgCase == "-left"
2052            || anArgCase == "-l"))
2053     {
2054       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2055     }
2056     else if (anArgIt + 1 < theArgsNb
2057           && (anArgCase == "-top"
2058            || anArgCase == "-t"))
2059     {
2060       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2061     }
2062     else if (anArgIt + 1 < theArgsNb
2063           && (anArgCase == "-width"
2064            || anArgCase == "-w"))
2065     {
2066       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2067     }
2068     else if (anArgIt + 1 < theArgsNb
2069           && (anArgCase == "-height"
2070            || anArgCase == "-h"))
2071     {
2072       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2073     }
2074     else if (anArgCase == "-exitonclose")
2075     {
2076       ViewerTest_EventManager::ToExitOnCloseView() = true;
2077       if (anArgIt + 1 < theArgsNb
2078        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
2079       {
2080         ++anArgIt;
2081       }
2082     }
2083     else if (anArgCase == "-closeonescape"
2084           || anArgCase == "-closeonesc")
2085     {
2086       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
2087       if (anArgIt + 1 < theArgsNb
2088        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
2089       {
2090         ++anArgIt;
2091       }
2092     }
2093     else if (anArgCase == "-2d_mode"
2094           || anArgCase == "-2dmode"
2095           || anArgCase == "-2d")
2096     {
2097       bool toEnable = true;
2098       if (anArgIt + 1 < theArgsNb
2099        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2100       {
2101         ++anArgIt;
2102       }
2103       is2dMode = toEnable ? 1 : 0;
2104     }
2105     else if (anArgIt + 1 < theArgsNb
2106           && (anArgCase == "-disp"
2107            || anArgCase == "-display"))
2108     {
2109       aDisplayName = theArgVec[++anArgIt];
2110     }
2111     else if (!ViewerTest::CurrentView().IsNull()
2112           &&  aCopyFrom.IsNull()
2113           && (anArgCase == "-copy"
2114            || anArgCase == "-clone"
2115            || anArgCase == "-cloneactive"
2116            || anArgCase == "-cloneactiveview"))
2117     {
2118       aCopyFrom = ViewerTest::CurrentView();
2119     }
2120     // old syntax
2121     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2122     {
2123       aName.LowerCase();
2124       if (aName == "name")
2125       {
2126         aViewName = aValue;
2127       }
2128       else if (aName == "l"
2129             || aName == "left")
2130       {
2131         aPxLeft = aValue.IntegerValue();
2132       }
2133       else if (aName == "t"
2134             || aName == "top")
2135       {
2136         aPxTop = aValue.IntegerValue();
2137       }
2138       else if (aName == "disp"
2139             || aName == "display")
2140       {
2141         aDisplayName = aValue;
2142       }
2143       else if (aName == "w"
2144             || aName == "width")
2145       {
2146         aPxWidth = aValue.IntegerValue();
2147       }
2148       else if (aName == "h"
2149             || aName == "height")
2150       {
2151         aPxHeight = aValue.IntegerValue();
2152       }
2153       else
2154       {
2155         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2156         return 1;
2157       }
2158     }
2159     else if (aViewName.IsEmpty())
2160     {
2161       aViewName = anArg;
2162     }
2163     else
2164     {
2165       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2166       return 1;
2167     }
2168   }
2169
2170 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2171   if (!aDisplayName.IsEmpty())
2172   {
2173     aDisplayName.Clear();
2174     std::cout << "Warning: display parameter will be ignored.\n";
2175   }
2176 #endif
2177
2178   ViewerTest_Names aViewNames (aViewName);
2179   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
2180   {
2181     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2182     theDi.Eval (aCommand.ToCString());
2183     if (is2dMode != -1)
2184     {
2185       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2186     }
2187     return 0;
2188   }
2189
2190   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
2191                                                             aViewName, aDisplayName, aCopyFrom);
2192   if (is2dMode != -1)
2193   {
2194     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2195   }
2196   theDi << aViewId;
2197   return 0;
2198 }
2199
2200 //! Parse HLR algo type.
2201 static Standard_Boolean parseHlrAlgoType (const char* theName,
2202                                           Prs3d_TypeOfHLR& theType)
2203 {
2204   TCollection_AsciiString aName (theName);
2205   aName.LowerCase();
2206   if (aName == "polyalgo")
2207   {
2208     theType = Prs3d_TOH_PolyAlgo;
2209   }
2210   else if (aName == "algo")
2211   {
2212     theType = Prs3d_TOH_Algo;
2213   }
2214   else
2215   {
2216     return Standard_False;
2217   }
2218   return Standard_True;
2219 }
2220
2221 //==============================================================================
2222 //function : VHLR
2223 //purpose  : hidden lines removal algorithm
2224 //==============================================================================
2225
2226 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2227 {
2228   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2229   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2230   if (aView.IsNull())
2231   {
2232     std::cerr << "Error: No opened viewer!\n";
2233     return 1;
2234   }
2235
2236   Standard_Boolean hasHlrOnArg = Standard_False;
2237   Standard_Boolean hasShowHiddenArg = Standard_False;
2238   Standard_Boolean isHLROn = Standard_False;
2239   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2240   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
2241   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2242   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2243   {
2244     TCollection_AsciiString anArg (argv[anArgIter]);
2245     anArg.LowerCase();
2246     if (anUpdateTool.parseRedrawMode (anArg))
2247     {
2248       continue;
2249     }
2250     else if (anArg == "-showhidden"
2251           && anArgIter + 1 < argc
2252           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2253     {
2254       ++anArgIter;
2255       hasShowHiddenArg = Standard_True;
2256       continue;
2257     }
2258     else if ((anArg == "-type"
2259            || anArg == "-algo"
2260            || anArg == "-algotype")
2261           && anArgIter + 1 < argc
2262           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2263     {
2264       ++anArgIter;
2265       continue;
2266     }
2267     else if (!hasHlrOnArg
2268           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2269     {
2270       hasHlrOnArg = Standard_True;
2271       continue;
2272     }
2273     // old syntax
2274     else if (!hasShowHiddenArg
2275           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2276     {
2277       hasShowHiddenArg = Standard_True;
2278       continue;
2279     }
2280     else
2281     {
2282       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2283       return 1;
2284     }
2285   }
2286   if (!hasHlrOnArg)
2287   {
2288     di << "HLR:        " << aView->ComputedMode() << "\n";
2289     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2290     di << "HlrAlgo:    ";
2291     switch (aCtx->DefaultDrawer()->TypeOfHLR())
2292     {
2293       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
2294       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2295       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
2296     }
2297     anUpdateTool.Invalidate();
2298     return 0;
2299   }
2300
2301   Standard_Boolean toRecompute = Standard_False;
2302   if (aTypeOfHLR != Prs3d_TOH_NotSet
2303    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
2304   {
2305     toRecompute = Standard_True;
2306     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2307   }
2308   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2309   {
2310     toRecompute = Standard_True;
2311     if (toShowHidden)
2312     {
2313       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
2314     }
2315     else
2316     {
2317       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
2318     }
2319   }
2320
2321   // redisplay shapes
2322   if (aView->ComputedMode() && isHLROn && toRecompute)
2323   {
2324     AIS_ListOfInteractive aListOfShapes;
2325     aCtx->DisplayedObjects (aListOfShapes);
2326     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
2327     {
2328       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
2329       {
2330         aCtx->Redisplay (aShape, Standard_False);
2331       }
2332     }
2333   }
2334
2335   aView->SetComputedMode (isHLROn);
2336   return 0;
2337 }
2338
2339 //==============================================================================
2340 //function : VHLRType
2341 //purpose  : change type of using HLR algorithm
2342 //==============================================================================
2343
2344 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
2345 {
2346   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2347   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2348   if (aView.IsNull())
2349   {
2350     std::cerr << "Error: No opened viewer!\n";
2351     return 1;
2352   }
2353
2354   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2355   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2356   AIS_ListOfInteractive aListOfShapes;
2357   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2358   {
2359     TCollection_AsciiString anArg (argv[anArgIter]);
2360     anArg.LowerCase();
2361     if (anUpdateTool.parseRedrawMode (anArg))
2362     {
2363       continue;
2364     }
2365     else if ((anArg == "-type"
2366            || anArg == "-algo"
2367            || anArg == "-algotype")
2368           && anArgIter + 1 < argc
2369           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2370     {
2371       ++anArgIter;
2372       continue;
2373     }
2374     // old syntax
2375     else if (aTypeOfHLR == Prs3d_TOH_NotSet
2376           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2377     {
2378       continue;
2379     }
2380     else
2381     {
2382       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
2383       TCollection_AsciiString aName (argv[anArgIter]);
2384       if (!aMap.IsBound2 (aName))
2385       {
2386         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2387         return 1;
2388       }
2389
2390       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2391       if (aShape.IsNull())
2392       {
2393         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2394         return 1;
2395       }
2396       aListOfShapes.Append (aShape);
2397       continue;
2398     }
2399   }
2400   if (aTypeOfHLR == Prs3d_TOH_NotSet)
2401   {
2402     std::cout << "Syntax error: wrong number of arguments!\n";
2403     return 1;
2404   }
2405
2406   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2407   if (isGlobal)
2408   {
2409     aCtx->DisplayedObjects (aListOfShapes);
2410     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2411   }
2412
2413   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2414   {
2415     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2416     if (aShape.IsNull())
2417     {
2418       continue;
2419     }
2420
2421     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2422                             && aView->ComputedMode();
2423     if (!isGlobal
2424      || aShape->TypeOfHLR() != aTypeOfHLR)
2425     {
2426       aShape->SetTypeOfHLR (aTypeOfHLR);
2427     }
2428     if (toUpdateShape)
2429     {
2430       aCtx->Redisplay (aShape, Standard_False);
2431     }
2432   }
2433   return 0;
2434 }
2435
2436 //==============================================================================
2437 //function : FindViewIdByWindowHandle
2438 //purpose  : Find theView Id in the map of views by window handle
2439 //==============================================================================
2440 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2441 TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
2442 {
2443   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2444        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2445   {
2446     Aspect_Drawable aWindowHandle = anIter.Value()->Window()->NativeHandle();
2447     if (aWindowHandle == theWindowHandle)
2448       return anIter.Key1();
2449   }
2450   return TCollection_AsciiString("");
2451 }
2452 #endif
2453
2454 //! Make the view active
2455 void ActivateView (const TCollection_AsciiString& theViewName,
2456                    Standard_Boolean theToUpdate = Standard_True)
2457 {
2458   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2459   if (aView.IsNull())
2460   {
2461     return;
2462   }
2463
2464   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2465   if (!anAISContext.IsNull())
2466   {
2467     if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
2468     {
2469       aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
2470     }
2471
2472     ViewerTest::CurrentView (aView);
2473     ViewerTest::SetAISContext (anAISContext);
2474     aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
2475 #if defined(_WIN32)
2476     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
2477 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
2478     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
2479 #else
2480     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
2481 #endif
2482     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2483     if (theToUpdate)
2484     {
2485       ViewerTest::CurrentView()->Redraw();
2486     }
2487   }
2488 }
2489
2490 //==============================================================================
2491 //function : RemoveView
2492 //purpose  :
2493 //==============================================================================
2494 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2495                              const Standard_Boolean  theToRemoveContext)
2496 {
2497   if (!ViewerTest_myViews.IsBound2 (theView))
2498   {
2499     return;
2500   }
2501
2502   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2503   RemoveView (aViewName, theToRemoveContext);
2504 }
2505
2506 //==============================================================================
2507 //function : RemoveView
2508 //purpose  : Close and remove view from display, clear maps if neccessary
2509 //==============================================================================
2510 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2511 {
2512   if (!ViewerTest_myViews.IsBound1(theViewName))
2513   {
2514     std::cout << "Wrong view name\n";
2515     return;
2516   }
2517
2518   // Activate another view if it's active now
2519   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2520   {
2521     if (ViewerTest_myViews.Extent() > 1)
2522     {
2523       TCollection_AsciiString aNewViewName;
2524       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2525            anIter.More(); anIter.Next())
2526       {
2527         if (anIter.Key1() != theViewName)
2528         {
2529           aNewViewName = anIter.Key1();
2530           break;
2531         }
2532       }
2533       ActivateView (aNewViewName);
2534     }
2535     else
2536     {
2537       VT_GetWindow().Nullify();
2538       ViewerTest::CurrentView (Handle(V3d_View)());
2539       if (isContextRemoved)
2540       {
2541         Handle(AIS_InteractiveContext) anEmptyContext;
2542         ViewerTest::SetAISContext(anEmptyContext);
2543       }
2544     }
2545   }
2546
2547   // Delete view
2548   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2549   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
2550   ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2551   aRedrawer.Stop (aView->Window());
2552
2553   // Remove view resources
2554   ViewerTest_myViews.UnBind1(theViewName);
2555   aView->Window()->Unmap();
2556   aView->Remove();
2557
2558 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2559   XFlush (GetDisplayConnection()->GetDisplay());
2560 #endif
2561
2562   // Keep context opened only if the closed view is last to avoid
2563   // unused empty contexts
2564   if (!aCurrentContext.IsNull())
2565   {
2566     // Check if there are more difined views in the viewer
2567     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1)
2568      && aCurrentContext->CurrentViewer()->DefinedViews().IsEmpty())
2569     {
2570       // Remove driver if there is no viewers that use it
2571       Standard_Boolean isRemoveDriver = Standard_True;
2572       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2573           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2574       {
2575         if (aCurrentContext != anIter.Key2() &&
2576           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2577         {
2578           isRemoveDriver = Standard_False;
2579           break;
2580         }
2581       }
2582
2583       aCurrentContext->RemoveAll (Standard_False);
2584       if(isRemoveDriver)
2585       {
2586         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2587       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2588         Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
2589       #endif
2590       }
2591
2592       ViewerTest_myContexts.UnBind2(aCurrentContext);
2593     }
2594   }
2595   std::cout << "3D View - " << theViewName << " was deleted.\n";
2596   if (ViewerTest_EventManager::ToExitOnCloseView())
2597   {
2598     Draw_Interprete ("exit");
2599   }
2600 }
2601
2602 //==============================================================================
2603 //function : VClose
2604 //purpose  : Remove the view defined by its name
2605 //==============================================================================
2606
2607 static int VClose (Draw_Interpretor& /*theDi*/,
2608                    Standard_Integer  theArgsNb,
2609                    const char**      theArgVec)
2610 {
2611   NCollection_List<TCollection_AsciiString> aViewList;
2612   if (theArgsNb > 1)
2613   {
2614     TCollection_AsciiString anArg (theArgVec[1]);
2615     anArg.UpperCase();
2616     if (anArg.IsEqual ("ALL")
2617      || anArg.IsEqual ("*"))
2618     {
2619       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2620            anIter.More(); anIter.Next())
2621       {
2622         aViewList.Append (anIter.Key1());
2623       }
2624       if (aViewList.IsEmpty())
2625       {
2626         std::cout << "No view to close\n";
2627         return 0;
2628       }
2629     }
2630     else
2631     {
2632       ViewerTest_Names aViewName (theArgVec[1]);
2633       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2634       {
2635         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2636         return 1;
2637       }
2638       aViewList.Append (aViewName.GetViewName());
2639     }
2640   }
2641   else
2642   {
2643     // close active view
2644     if (ViewerTest::CurrentView().IsNull())
2645     {
2646       std::cerr << "No active view!\n";
2647       return 1;
2648     }
2649     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2650   }
2651
2652   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
2653   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2654        anIter.More(); anIter.Next())
2655   {
2656     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
2657   }
2658
2659   return 0;
2660 }
2661
2662 //==============================================================================
2663 //function : VActivate
2664 //purpose  : Activate the view defined by its ID
2665 //==============================================================================
2666
2667 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2668 {
2669   if (theArgsNb == 1)
2670   {
2671     theDi.Eval("vviewlist");
2672     return 0;
2673   }
2674
2675   TCollection_AsciiString aNameString;
2676   Standard_Boolean toUpdate = Standard_True;
2677   Standard_Boolean toActivate = Standard_True;
2678   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
2679   {
2680     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2681     anArg.LowerCase();
2682     if (toUpdate
2683      && anArg == "-noupdate")
2684     {
2685       toUpdate = Standard_False;
2686     }
2687     else if (toActivate
2688           && aNameString.IsEmpty()
2689           && anArg == "none")
2690     {
2691       ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2692       VT_GetWindow().Nullify();
2693       ViewerTest::CurrentView (Handle(V3d_View)());
2694       ViewerTest::ResetEventManager();
2695       theDi << theArgVec[0] << ": all views are inactive\n";
2696       toActivate = Standard_False;
2697     }
2698     else if (toActivate
2699           && aNameString.IsEmpty())
2700     {
2701       aNameString = theArgVec[anArgIter];
2702     }
2703     else
2704     {
2705       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2706       return 1;
2707     }
2708   }
2709
2710   if (!toActivate)
2711   {
2712     return 0;
2713   }
2714   else if (aNameString.IsEmpty())
2715   {
2716     std::cout << "Syntax error: wrong number of arguments\n";
2717     return 1;
2718   }
2719
2720   // Check if this view exists in the viewer with the driver
2721   ViewerTest_Names aViewNames (aNameString);
2722   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2723   {
2724     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
2725     return 1;
2726   }
2727
2728   // Check if it is active already
2729   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2730   {
2731     theDi << theArgVec[0] << ": the view is active already\n";
2732     return 0;
2733   }
2734
2735   ActivateView (aViewNames.GetViewName(), toUpdate);
2736   return 0;
2737 }
2738
2739 //==============================================================================
2740 //function : VViewList
2741 //purpose  : Print current list of views per viewer and graphic driver ID
2742 //           shared between viewers
2743 //==============================================================================
2744
2745 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2746 {
2747   if (theArgsNb > 2)
2748   {
2749     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
2750           << "Usage: " << theArgVec[0] << " name";
2751     return 1;
2752   }
2753   if (ViewerTest_myContexts.Size() < 1)
2754     return 0;
2755
2756   Standard_Boolean isTreeView =
2757     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
2758
2759   if (isTreeView)
2760   {
2761     theDi << theArgVec[0] <<":\n";
2762   }
2763
2764   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2765        aDriverIter.More(); aDriverIter.Next())
2766   {
2767     if (isTreeView)
2768       theDi << aDriverIter.Key1() << ":\n";
2769
2770     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2771       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2772     {
2773       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
2774       {
2775         if (isTreeView)
2776         {
2777           TCollection_AsciiString aContextName(aContextIter.Key1());
2778           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2779         }
2780
2781         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2782              aViewIter.More(); aViewIter.Next())
2783         {
2784           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
2785           {
2786             TCollection_AsciiString aViewName(aViewIter.Key1());
2787             if (isTreeView)
2788             {
2789               if (aViewIter.Value() == ViewerTest::CurrentView())
2790                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
2791               else
2792                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2793             }
2794             else
2795             {
2796               theDi << aViewName << " ";
2797             }
2798           }
2799         }
2800       }
2801     }
2802   }
2803   return 0;
2804 }
2805
2806 //==============================================================================
2807 //function : GetMousePosition
2808 //purpose  :
2809 //==============================================================================
2810 void ViewerTest::GetMousePosition (Standard_Integer& theX,
2811                                    Standard_Integer& theY)
2812 {
2813   if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
2814   {
2815     theX = aViewCtrl->LastMousePosition().x();
2816     theY = aViewCtrl->LastMousePosition().y();
2817   }
2818 }
2819
2820 //==============================================================================
2821 //function : VViewProj
2822 //purpose  : Switch view projection
2823 //==============================================================================
2824 static int VViewProj (Draw_Interpretor& ,
2825                       Standard_Integer theNbArgs,
2826                       const char** theArgVec)
2827 {
2828   static Standard_Boolean isYup = Standard_False;
2829   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2830   if (aView.IsNull())
2831   {
2832     std::cout << "Error: no active view\n";
2833     return 1;
2834   }
2835
2836   TCollection_AsciiString aCmdName (theArgVec[0]);
2837   Standard_Boolean isGeneralCmd = Standard_False;
2838   if (aCmdName == "vfront")
2839   {
2840     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2841   }
2842   else if (aCmdName == "vback")
2843   {
2844     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2845   }
2846   else if (aCmdName == "vtop")
2847   {
2848     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2849   }
2850   else if (aCmdName == "vbottom")
2851   {
2852     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2853   }
2854   else if (aCmdName == "vleft")
2855   {
2856     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2857   }
2858   else if (aCmdName == "vright")
2859   {
2860     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2861   }
2862   else if (aCmdName == "vaxo")
2863   {
2864     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2865   }
2866   else
2867   {
2868     isGeneralCmd = Standard_True;
2869     for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2870     {
2871       TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2872       anArgCase.LowerCase();
2873       if (anArgCase == "-zup")
2874       {
2875         isYup = Standard_False;
2876       }
2877       else if (anArgCase == "-yup")
2878       {
2879         isYup = Standard_True;
2880       }
2881       else if (anArgCase == "-front"
2882             || anArgCase == "front"
2883             || anArgCase == "-f"
2884             || anArgCase == "f")
2885       {
2886         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2887       }
2888       else if (anArgCase == "-back"
2889             || anArgCase == "back"
2890             || anArgCase == "-b"
2891             || anArgCase == "b")
2892       {
2893         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2894       }
2895       else if (anArgCase == "-top"
2896             || anArgCase == "top"
2897             || anArgCase == "-t"
2898             || anArgCase == "t")
2899       {
2900         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2901       }
2902       else if (anArgCase == "-bottom"
2903             || anArgCase == "bottom"
2904             || anArgCase == "-bot"
2905             || anArgCase == "bot"
2906             || anArgCase == "-b"
2907             || anArgCase == "b")
2908       {
2909         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2910       }
2911       else if (anArgCase == "-left"
2912             || anArgCase == "left"
2913             || anArgCase == "-l"
2914             || anArgCase == "l")
2915       {
2916         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2917       }
2918       else if (anArgCase == "-right"
2919             || anArgCase == "right"
2920             || anArgCase == "-r"
2921             || anArgCase == "r")
2922       {
2923         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2924       }
2925       else if (anArgCase == "-axoleft"
2926             || anArgCase == "-leftaxo"
2927             || anArgCase == "axoleft"
2928             || anArgCase == "leftaxo")
2929       {
2930         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
2931       }
2932       else if (anArgCase == "-axo"
2933             || anArgCase == "axo"
2934             || anArgCase == "-a"
2935             || anArgCase == "a"
2936             || anArgCase == "-axoright"
2937             || anArgCase == "-rightaxo"
2938             || anArgCase == "axoright"
2939             || anArgCase == "rightaxo")
2940       {
2941         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2942       }
2943       else if (anArgCase == "+x")
2944       {
2945         aView->SetProj (V3d_Xpos, isYup);
2946       }
2947       else if (anArgCase == "-x")
2948       {
2949         aView->SetProj (V3d_Xneg, isYup);
2950       }
2951       else if (anArgCase == "+y")
2952       {
2953         aView->SetProj (V3d_Ypos, isYup);
2954       }
2955       else if (anArgCase == "-y")
2956       {
2957         aView->SetProj (V3d_Yneg, isYup);
2958       }
2959       else if (anArgCase == "+z")
2960       {
2961         aView->SetProj (V3d_Zpos, isYup);
2962       }
2963       else if (anArgCase == "-z")
2964       {
2965         aView->SetProj (V3d_Zneg, isYup);
2966       }
2967       else if (anArgCase == "+x+y+z")
2968       {
2969         aView->SetProj (V3d_XposYposZpos, isYup);
2970       }
2971       else if (anArgCase == "+x+y-z")
2972       {
2973         aView->SetProj (V3d_XposYposZneg, isYup);
2974       }
2975       else if (anArgCase == "+x-y+z")
2976       {
2977         aView->SetProj (V3d_XposYnegZpos, isYup);
2978       }
2979       else if (anArgCase == "+x-y-z")
2980       {
2981         aView->SetProj (V3d_XposYnegZneg, isYup);
2982       }
2983       else if (anArgCase == "-x+y+z")
2984       {
2985         aView->SetProj (V3d_XnegYposZpos, isYup);
2986       }
2987       else if (anArgCase == "-x+y-z")
2988       {
2989         aView->SetProj (V3d_XnegYposZneg, isYup);
2990       }
2991       else if (anArgCase == "-x-y+z")
2992       {
2993         aView->SetProj (V3d_XnegYnegZpos, isYup);
2994       }
2995       else if (anArgCase == "-x-y-z")
2996       {
2997         aView->SetProj (V3d_XnegYnegZneg, isYup);
2998       }
2999       else if (anArgCase == "+x+y")
3000       {
3001         aView->SetProj (V3d_XposYpos, isYup);
3002       }
3003       else if (anArgCase == "+x-y")
3004       {
3005         aView->SetProj (V3d_XposYneg, isYup);
3006       }
3007       else if (anArgCase == "-x+y")
3008       {
3009         aView->SetProj (V3d_XnegYpos, isYup);
3010       }
3011       else if (anArgCase == "-x-y")
3012       {
3013         aView->SetProj (V3d_XnegYneg, isYup);
3014       }
3015       else if (anArgCase == "+x+z")
3016       {
3017         aView->SetProj (V3d_XposZpos, isYup);
3018       }
3019       else if (anArgCase == "+x-z")
3020       {
3021         aView->SetProj (V3d_XposZneg, isYup);
3022       }
3023       else if (anArgCase == "-x+z")
3024       {
3025         aView->SetProj (V3d_XnegZpos, isYup);
3026       }
3027       else if (anArgCase == "-x-z")
3028       {
3029         aView->SetProj (V3d_XnegZneg, isYup);
3030       }
3031       else if (anArgCase == "+y+z")
3032       {
3033         aView->SetProj (V3d_YposZpos, isYup);
3034       }
3035       else if (anArgCase == "+y-z")
3036       {
3037         aView->SetProj (V3d_YposZneg, isYup);
3038       }
3039       else if (anArgCase == "-y+z")
3040       {
3041         aView->SetProj (V3d_YnegZpos, isYup);
3042       }
3043       else if (anArgCase == "-y-z")
3044       {
3045         aView->SetProj (V3d_YnegZneg, isYup);
3046       }
3047       else if (anArgIter + 1 < theNbArgs
3048             && anArgCase == "-frame"
3049             && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
3050       {
3051         TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
3052         aFrameDef.LowerCase();
3053         gp_Dir aRight, anUp;
3054         if (aFrameDef.Value (2) == aFrameDef.Value (4))
3055         {
3056           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3057           return 1;
3058         }
3059
3060         if (aFrameDef.Value (2) == 'x')
3061         {
3062           aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
3063         }
3064         else if (aFrameDef.Value (2) == 'y')
3065         {
3066           aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
3067         }
3068         else if (aFrameDef.Value (2) == 'z')
3069         {
3070           aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
3071         }
3072         else
3073         {
3074           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3075           return 1;
3076         }
3077
3078         if (aFrameDef.Value (4) == 'x')
3079         {
3080           anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
3081         }
3082         else if (aFrameDef.Value (4) == 'y')
3083         {
3084           anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
3085         }
3086         else if (aFrameDef.Value (4) == 'z')
3087         {
3088           anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
3089         }
3090         else
3091         {
3092           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3093           return 1;
3094         }
3095
3096         const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
3097         const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
3098         const gp_Dir aDir = anUp.Crossed (aRight);
3099         aCamera->SetCenter (gp_Pnt (0, 0, 0));
3100         aCamera->SetDirection (aDir);
3101         aCamera->SetUp (anUp);
3102         aCamera->OrthogonalizeUp();
3103
3104         aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
3105         aView->Update();
3106       }
3107       else
3108       {
3109         std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3110         return 1;
3111       }
3112     }
3113   }
3114
3115   if (!isGeneralCmd
3116     && theNbArgs != 1)
3117   {
3118     std::cout << "Syntax error: wrong number of arguments\n";
3119     return 1;
3120   }
3121   return 0;
3122 }
3123
3124 //==============================================================================
3125 //function : VHelp
3126 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
3127 //Draw arg : No args
3128 //==============================================================================
3129
3130 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3131 {
3132   di << "=========================\n";
3133   di << "F : FitAll\n";
3134   di << "T : TopView\n";
3135   di << "B : BottomView\n";
3136   di << "R : RightView\n";
3137   di << "L : LeftView\n";
3138   di << "A : AxonometricView\n";
3139   di << "D : ResetView\n";
3140
3141   di << "=========================\n";
3142   di << "S : Shading\n";
3143   di << "W : Wireframe\n";
3144   di << "H : HiddenLineRemoval\n";
3145   di << "U : Unset display mode\n";
3146   di << "Delete : Remove selection from viewer\n";
3147
3148   di << "=========================\n";
3149   di << "Selection mode \n";
3150   di << "0 : Shape\n";
3151   di << "1 : Vertex\n";
3152   di << "2 : Edge\n";
3153   di << "3 : Wire\n";
3154   di << "4 : Face\n";
3155   di << "5 : Shell\n";
3156   di << "6 : Solid\n";
3157   di << "7 : Compound\n";
3158
3159   di << "=========================\n";
3160   di << "< : Hilight next detected\n";
3161   di << "> : Hilight previous detected\n";
3162
3163   return 0;
3164 }
3165
3166 #ifdef _WIN32
3167
3168 static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
3169                                            UINT theMsg,
3170                                            WPARAM wParam,
3171                                            LPARAM lParam )
3172 {
3173   if (ViewerTest_myViews.IsEmpty())
3174   {
3175     return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3176   }
3177
3178   switch (theMsg)
3179   {
3180     case WM_CLOSE:
3181     {
3182       // Delete view from map of views
3183       ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
3184       return 0;
3185     }
3186     case WM_ACTIVATE:
3187     {
3188       if (LOWORD(wParam) == WA_CLICKACTIVE
3189        || LOWORD(wParam) == WA_ACTIVE
3190        || ViewerTest::CurrentView().IsNull())
3191       {
3192         // Activate inactive window
3193         if (VT_GetWindow().IsNull()
3194          || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3195         {
3196           ActivateView (FindViewIdByWindowHandle (theWinHandle));
3197         }
3198       }
3199       break;
3200     }
3201     default:
3202     {
3203       return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3204     }
3205   }
3206   return 0;
3207 }
3208
3209 static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
3210                                         UINT theMsg,
3211                                         WPARAM wParam,
3212                                         LPARAM lParam)
3213 {
3214   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3215   if (aView.IsNull())
3216   {
3217     return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3218   }
3219
3220   switch (theMsg)
3221   {
3222     case WM_PAINT:
3223     {
3224       PAINTSTRUCT aPaint;
3225       BeginPaint(theWinHandle, &aPaint);
3226       EndPaint  (theWinHandle, &aPaint);
3227       ViewerTest::CurrentEventManager()->ProcessExpose();
3228       break;
3229     }
3230     case WM_SIZE:
3231     {
3232       ViewerTest::CurrentEventManager()->ProcessConfigure();
3233       break;
3234     }
3235     case WM_MOVE:
3236     case WM_MOVING:
3237     case WM_SIZING:
3238     {
3239       switch (aView->RenderingParams().StereoMode)
3240       {
3241         case Graphic3d_StereoMode_RowInterlaced:
3242         case Graphic3d_StereoMode_ColumnInterlaced:
3243         case Graphic3d_StereoMode_ChessBoard:
3244         {
3245           // track window moves to reverse stereo pair
3246           aView->MustBeResized();
3247           aView->Update();
3248           break;
3249         }
3250         default:
3251           break;
3252       }
3253       break;
3254     }
3255     case WM_KEYUP:
3256     case WM_KEYDOWN:
3257     {
3258       const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
3259       if (aVKey != Aspect_VKey_UNKNOWN)
3260       {
3261         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3262         if (theMsg == WM_KEYDOWN)
3263         {
3264           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3265         }
3266         else
3267         {
3268           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3269         }
3270         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3271       }
3272       break;
3273     }
3274     case WM_LBUTTONUP:
3275     case WM_MBUTTONUP:
3276     case WM_RBUTTONUP:
3277     case WM_LBUTTONDOWN:
3278     case WM_MBUTTONDOWN:
3279     case WM_RBUTTONDOWN:
3280     {
3281       const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3282       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3283       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3284       switch (theMsg)
3285       {
3286         case WM_LBUTTONUP:
3287         case WM_LBUTTONDOWN:
3288           aButton = Aspect_VKeyMouse_LeftButton;
3289           break;
3290         case WM_MBUTTONUP:
3291         case WM_MBUTTONDOWN:
3292           aButton = Aspect_VKeyMouse_MiddleButton;
3293           break;
3294         case WM_RBUTTONUP:
3295         case WM_RBUTTONDOWN:
3296           aButton = Aspect_VKeyMouse_RightButton;
3297           break;
3298       }
3299       if (theMsg == WM_LBUTTONDOWN
3300        || theMsg == WM_MBUTTONDOWN
3301        || theMsg == WM_RBUTTONDOWN)
3302       {
3303         if (aButton == Aspect_VKeyMouse_LeftButton)
3304         {
3305           TheIsAnimating = Standard_False;
3306         }
3307
3308         SetFocus  (theWinHandle);
3309         SetCapture(theWinHandle);
3310         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3311       }
3312       else
3313       {
3314         ReleaseCapture();
3315         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3316       }
3317       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3318       break;
3319     }
3320     case WM_MOUSEWHEEL:
3321     {
3322       const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3323       const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
3324       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3325       Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
3326       POINT aCursorPnt = { aPos.x(), aPos.y() };
3327       if (ScreenToClient (theWinHandle, &aCursorPnt))
3328       {
3329         aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3330       }
3331
3332       ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3333       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3334       break;
3335     }
3336     case WM_MOUSEMOVE:
3337     {
3338       Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3339       Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (wParam);
3340       Aspect_VKeyFlags aFlags   = WNT_Window::MouseKeyFlagsFromEvent(wParam);
3341
3342       // don't make a slide-show from input events - fetch the actual mouse cursor position
3343       CURSORINFO aCursor;
3344       aCursor.cbSize = sizeof(aCursor);
3345       if (::GetCursorInfo (&aCursor) != FALSE)
3346       {
3347         POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
3348         if (ScreenToClient (theWinHandle, &aCursorPnt))
3349         {
3350           // as we override mouse position, we need overriding also mouse state
3351           aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3352           aButtons = WNT_Window::MouseButtonsAsync();
3353           aFlags   = WNT_Window::MouseKeyFlagsAsync();
3354         }
3355       }
3356
3357       if (VT_GetWindow().IsNull()
3358       || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3359       {
3360         // mouse move events come also for inactive windows
3361         break;
3362       }
3363
3364       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3365       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
3366       break;
3367     }
3368     default:
3369     {
3370       return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3371     }
3372   }
3373   return 0L;
3374 }
3375
3376 //==============================================================================
3377 //function : ViewerMainLoop
3378 //purpose  : Get a Event on the view and dispatch it
3379 //==============================================================================
3380
3381 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3382 {
3383   Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
3384   if (aViewCtrl.IsNull()
3385    || theNbArgs < 4)
3386   {
3387     return 0;
3388   }
3389
3390   aViewCtrl->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3391
3392   std::cout << "Start picking\n";
3393
3394   MSG aMsg;
3395   aMsg.wParam = 1;
3396   while (aViewCtrl->ToPickPoint())
3397   {
3398     // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
3399     if (GetMessageW (&aMsg, NULL, 0, 0))
3400     {
3401       TranslateMessage (&aMsg);
3402       DispatchMessageW (&aMsg);
3403     }
3404   }
3405
3406   std::cout << "Picking done\n";
3407   return 0;
3408 }
3409
3410 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
3411
3412 int min( int a, int b )
3413 {
3414   if( a<b )
3415     return a;
3416   else
3417     return b;
3418 }
3419
3420 int max( int a, int b )
3421 {
3422   if( a>b )
3423     return a;
3424   else
3425     return b;
3426 }
3427
3428 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3429 {
3430   static XEvent aReport;
3431   const Standard_Boolean toPick = theNbArgs > 0;
3432   if (theNbArgs > 0)
3433   {
3434     if (ViewerTest::CurrentEventManager().IsNull())
3435     {
3436       return 0;
3437     }
3438     ViewerTest::CurrentEventManager()->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3439   }
3440
3441   Display* aDisplay = GetDisplayConnection()->GetDisplay();
3442   XNextEvent (aDisplay, &aReport);
3443
3444   // Handle event for the chosen display connection
3445   switch (aReport.type)
3446   {
3447     case ClientMessage:
3448     {
3449       if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
3450       {
3451         // Close the window
3452         ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
3453         return toPick ? 0 : 1;
3454       }
3455       break;
3456     }
3457     case FocusIn:
3458     {
3459       // Activate inactive view
3460       Window aWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3461       if (aWindow != aReport.xfocus.window)
3462       {
3463         ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
3464       }
3465       break;
3466     }
3467     case Expose:
3468     {
3469       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3470       if (anXWindow == aReport.xexpose.window)
3471       {
3472         ViewerTest::CurrentEventManager()->ProcessExpose();
3473       }
3474
3475       // remove all the ExposureMask and process them at once
3476       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3477       {
3478         if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
3479         {
3480           break;
3481         }
3482       }
3483
3484       break;
3485     }
3486     case ConfigureNotify:
3487     {
3488       // remove all the StructureNotifyMask and process them at once
3489       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3490       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3491       {
3492         if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
3493         {
3494           break;
3495         }
3496       }
3497
3498       if (anXWindow == aReport.xconfigure.window)
3499       {
3500         ViewerTest::CurrentEventManager()->ProcessConfigure();
3501       }
3502       break;
3503     }
3504     case KeyPress:
3505     case KeyRelease:
3506     {
3507       XKeyEvent*   aKeyEvent = (XKeyEvent* )&aReport;
3508       const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
3509       const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
3510       if (aVKey != Aspect_VKey_UNKNOWN)
3511       {
3512         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3513         if (aReport.type == KeyPress)
3514         {
3515           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3516         }
3517         else
3518         {
3519           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3520         }
3521         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3522       }
3523       break;
3524     }
3525     case ButtonPress:
3526     case ButtonRelease:
3527     {
3528       const Graphic3d_Vec2i aPos (aReport.xbutton.x, aReport.xbutton.y);
3529       Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
3530       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3531       if (aReport.xbutton.button == Button1)
3532       {
3533         aButton = Aspect_VKeyMouse_LeftButton;
3534       }
3535       if (aReport.xbutton.button == Button2)
3536       {
3537         aButton = Aspect_VKeyMouse_MiddleButton;
3538       }
3539       if (aReport.xbutton.button == Button3)
3540       {
3541         aButton = Aspect_VKeyMouse_RightButton;
3542       }
3543
3544       if (aReport.xbutton.state & ControlMask)
3545       {
3546         aFlags |= Aspect_VKeyFlags_CTRL;
3547       }
3548       if (aReport.xbutton.state & ShiftMask)
3549       {
3550         aFlags |= Aspect_VKeyFlags_SHIFT;
3551       }
3552       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3553       {
3554         aFlags |= Aspect_VKeyFlags_ALT;
3555       }
3556
3557       if (aReport.xbutton.button == Button4
3558        || aReport.xbutton.button == Button5)
3559       {
3560         if (aReport.type != ButtonPress)
3561         {
3562           break;
3563         }
3564
3565         const double aDeltaF = (aReport.xbutton.button == Button4 ? 1.0 : -1.0);
3566         ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3567       }
3568       else if (aReport.type == ButtonPress)
3569       {
3570         if (aButton == Aspect_VKeyMouse_LeftButton)
3571         {
3572           TheIsAnimating = Standard_False;
3573         }
3574         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3575       }
3576       else
3577       {
3578         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3579       }
3580       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3581       break;
3582     }
3583     case MotionNotify:
3584     {
3585       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3586       if (anXWindow != aReport.xmotion.window)
3587       {
3588         break;
3589       }
3590
3591       // remove all the ButtonMotionMask and process them at once
3592       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3593       {
3594         if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
3595         {
3596           break;
3597         }
3598       }
3599
3600       Graphic3d_Vec2i aPos (aReport.xmotion.x, aReport.xmotion.y);
3601       Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
3602       Aspect_VKeyFlags aFlags   = Aspect_VKeyFlags_NONE;
3603       if ((aReport.xmotion.state & Button1Mask) != 0)
3604       {
3605         aButtons |= Aspect_VKeyMouse_LeftButton;
3606       }
3607       else if ((aReport.xmotion.state & Button2Mask) != 0)
3608       {
3609         aButtons |= Aspect_VKeyMouse_MiddleButton;
3610       }
3611       else if ((aReport.xmotion.state & Button3Mask) != 0)
3612       {
3613         aButtons |= Aspect_VKeyMouse_RightButton;
3614       }
3615
3616       if (aReport.xmotion.state & ControlMask)
3617       {
3618         aFlags |= Aspect_VKeyFlags_CTRL;
3619       }
3620       if (aReport.xmotion.state & ShiftMask)
3621       {
3622         aFlags |= Aspect_VKeyFlags_SHIFT;
3623       }
3624       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3625       {
3626         aFlags |= Aspect_VKeyFlags_ALT;
3627       }
3628
3629       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3630       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3631       break;
3632     }
3633   }
3634   return (!toPick || ViewerTest::CurrentEventManager()->ToPickPoint()) ? 1 : 0;
3635 }
3636
3637 //==============================================================================
3638 //function : VProcessEvents
3639 //purpose  : manage the event in the Viewer window (see Tcl_CreateFileHandler())
3640 //==============================================================================
3641 static void VProcessEvents (ClientData theDispX, int)
3642 {
3643   Display* aDispX = (Display* )theDispX;
3644   Handle(Aspect_DisplayConnection) aDispConn;
3645   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
3646        aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
3647   {
3648     const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
3649     if (aDispConnTmp->GetDisplay() == aDispX)
3650     {
3651       aDispConn = aDispConnTmp;
3652       break;
3653     }
3654   }
3655   if (aDispConn.IsNull())
3656   {
3657     std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
3658     return;
3659   }
3660
3661   // process new events in queue
3662   SetDisplayConnection (aDispConn);
3663   int aNbRemain = 0;
3664   for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
3665   {
3666     const int anEventResult = ViewerMainLoop (0, NULL);
3667     if (anEventResult == 0)
3668     {
3669       return;
3670     }
3671
3672     aNbRemain = XPending (aDispX);
3673     if (++anEventIter >= aNbEventsMax
3674      || aNbRemain <= 0)
3675     {
3676       break;
3677     }
3678   }
3679
3680   // Listening X events through Tcl_CreateFileHandler() callback is fragile,
3681   // it is possible that new events will arrive to queue before the end of this callback
3682   // so that either this callback should go into an infinite loop (blocking processing of other events)
3683   // or to keep unprocessed events till the next queue update (which can arrive not soon).
3684   // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
3685   if (aNbRemain != 0)
3686   {
3687     XEvent aDummyEvent;
3688     memset (&aDummyEvent, 0, sizeof(aDummyEvent));
3689     aDummyEvent.type = ClientMessage;
3690     aDummyEvent.xclient.format = 32;
3691     XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
3692     XFlush (aDispX);
3693   }
3694
3695   if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
3696   {
3697     SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
3698   }
3699 }
3700 #endif
3701
3702 //==============================================================================
3703 //function : OSWindowSetup
3704 //purpose  : Setup for the X11 window to be able to cath the event
3705 //==============================================================================
3706
3707
3708 static void OSWindowSetup()
3709 {
3710 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
3711   // X11
3712
3713   Window  window   = VT_GetWindow()->XWindow();
3714   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
3715   Display *aDisplay = GetDisplayConnection()->GetDisplay();
3716   XSynchronize(aDisplay, 1);
3717
3718   // X11 : For keyboard on SUN
3719   XWMHints wmhints;
3720   wmhints.flags = InputHint;
3721   wmhints.input = 1;
3722
3723   XSetWMHints( aDisplay, window, &wmhints);
3724
3725   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask | KeyReleaseMask |
3726     ButtonPressMask | ButtonReleaseMask |
3727     StructureNotifyMask |
3728     PointerMotionMask |
3729     Button1MotionMask | Button2MotionMask |
3730     Button3MotionMask | FocusChangeMask
3731     );
3732   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
3733   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
3734
3735   XSynchronize(aDisplay, 0);
3736
3737 #else
3738   // _WIN32
3739 #endif
3740
3741 }
3742
3743 //==============================================================================
3744 //function : VFit
3745 //purpose  :
3746 //==============================================================================
3747
3748 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
3749 {
3750   const Handle(V3d_View) aView = ViewerTest::CurrentView();
3751   if (aView.IsNull())
3752   {
3753     std::cout << "Error: no active viewer!\n";
3754     return 1;
3755   }
3756
3757   Standard_Boolean toFit = Standard_True;
3758   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
3759   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3760   {
3761     TCollection_AsciiString anArg (theArgv[anArgIter]);
3762     anArg.LowerCase();
3763     if (anUpdateTool.parseRedrawMode (anArg))
3764     {
3765       continue;
3766     }
3767     else if (anArg == "-selected")
3768     {
3769       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
3770       toFit = Standard_False;
3771     }
3772     else
3773     {
3774       std::cout << "Syntax error at '" << anArg << "'\n";
3775     }
3776   }
3777
3778   if (toFit)
3779   {
3780     aView->FitAll (0.01, Standard_False);
3781   }
3782   return 0;
3783 }
3784
3785 //=======================================================================
3786 //function : VFitArea
3787 //purpose  : Fit view to show area located between two points
3788 //         : given in world 2D or 3D coordinates.
3789 //=======================================================================
3790 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
3791 {
3792   Handle(V3d_View) aView = ViewerTest::CurrentView();
3793   if (aView.IsNull())
3794   {
3795     std::cerr << theArgVec[0] << "Error: No active view.\n";
3796     return 1;
3797   }
3798
3799   // Parse arguments.
3800   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
3801   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
3802
3803   if (theArgNb == 5)
3804   {
3805     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3806     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3807     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
3808     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
3809   }
3810   else if (theArgNb == 7)
3811   {
3812     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3813     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3814     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
3815     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
3816     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
3817     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
3818   }
3819   else
3820   {
3821     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
3822     theDI.PrintHelp(theArgVec[0]);
3823     return 1;
3824   }
3825
3826   // Convert model coordinates to view space
3827   Handle(Graphic3d_Camera) aCamera = aView->Camera();
3828   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
3829   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
3830
3831   // Determine fit area
3832   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
3833   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
3834
3835   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
3836
3837   if (aDiagonal < Precision::Confusion())
3838   {
3839     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
3840     return 1;
3841   }
3842
3843   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
3844   return 0;
3845 }
3846
3847 //==============================================================================
3848 //function : VZFit
3849 //purpose  : ZFitall, no DRAW arguments
3850 //Draw arg : No args
3851 //==============================================================================
3852 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3853 {
3854   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
3855
3856   if (aCurrentView.IsNull())
3857   {
3858     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
3859     return 1;
3860   }
3861
3862   if (theArgsNb == 1)
3863   {
3864     aCurrentView->ZFitAll();
3865     aCurrentView->Redraw();
3866     return 0;
3867   }
3868
3869   Standard_Real aScale = 1.0;
3870
3871   if (theArgsNb >= 2)
3872   {
3873     aScale = Draw::Atoi (theArgVec[1]);
3874   }
3875
3876   aCurrentView->ZFitAll (aScale);
3877   aCurrentView->Redraw();
3878
3879   return 0;
3880 }
3881
3882 //==============================================================================
3883 //function : VRepaint
3884 //purpose  :
3885 //==============================================================================
3886 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
3887 {
3888   Handle(V3d_View) aView = ViewerTest::CurrentView();
3889   if (aView.IsNull())
3890   {
3891     std::cout << "Error: no active viewer!\n";
3892     return 1;
3893   }
3894
3895   Standard_Boolean isImmediateUpdate = Standard_False;
3896   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3897   {
3898     TCollection_AsciiString anArg (theArgVec[anArgIter]);
3899     anArg.LowerCase();
3900     if (anArg == "-immediate"
3901      || anArg == "-imm")
3902     {
3903       isImmediateUpdate = Standard_True;
3904       if (anArgIter + 1 < theArgNb
3905        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
3906       {
3907         ++anArgIter;
3908       }
3909     }
3910     else if (anArg == "-continuous"
3911           || anArg == "-cont"
3912           || anArg == "-fps"
3913           || anArg == "-framerate")
3914     {
3915       Standard_Real aFps = -1.0;
3916       if (anArgIter + 1 < theArgNb
3917        && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
3918       {
3919         aFps = Draw::Atof (theArgVec[++anArgIter]);
3920       }
3921
3922       ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
3923       if (Abs (aFps) >= 1.0)
3924       {
3925         aRedrawer.Start (aView->Window(), aFps);
3926       }
3927       else
3928       {
3929         aRedrawer.Stop();
3930       }
3931     }
3932     else
3933     {
3934       std::cout << "Syntax error at '" << anArg << "'\n";
3935       return 1;
3936     }
3937   }
3938
3939   if (isImmediateUpdate)
3940   {
3941     aView->RedrawImmediate();
3942   }
3943   else
3944   {
3945     aView->Redraw();
3946   }
3947   return 0;
3948 }
3949
3950 //==============================================================================
3951 //function : VClear
3952 //purpose  : Remove all the object from the viewer
3953 //Draw arg : No args
3954 //==============================================================================
3955
3956 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3957 {
3958   Handle(V3d_View) V = ViewerTest::CurrentView();
3959   if(!V.IsNull())
3960     ViewerTest::Clear();
3961   return 0;
3962 }
3963
3964 //==============================================================================
3965 //function : VPick
3966 //purpose  :
3967 //==============================================================================
3968
3969 static int VPick (Draw_Interpretor& ,
3970                   Standard_Integer theNbArgs,
3971                   const char** theArgVec)
3972 {
3973   if (ViewerTest::CurrentView().IsNull())
3974   {
3975     return 1;
3976   }
3977
3978   if (theNbArgs < 4)
3979   {
3980     std::cout << "Syntax error: Invalid number of arguments\n";
3981     return 1;
3982   }
3983
3984   while (ViewerMainLoop (theNbArgs, theArgVec))
3985   {
3986     //
3987   }
3988
3989   return 0;
3990 }
3991
3992 namespace
3993 {
3994
3995   //! Changes the background
3996   //! @param theDrawInterpretor the interpreter of the Draw Harness application
3997   //! @param theNumberOfCommandLineArguments the number of passed command line arguments
3998   //! @param theCommandLineArguments the array of command line arguments
3999   //! @return TCL_OK if changing was successful, or TCL_ERROR otherwise
4000   static int vbackground (Draw_Interpretor&      theDrawInterpretor,
4001                           const Standard_Integer theNumberOfCommandLineArguments,
4002                           const char** const     theCommandLineArguments)
4003   {
4004     if (theNumberOfCommandLineArguments < 1)
4005     {
4006       return TCL_ERROR;
4007     }
4008     BackgroundChanger aBackgroundChanger;
4009     if (!aBackgroundChanger.ProcessCommandLine (theDrawInterpretor,
4010                                                 theNumberOfCommandLineArguments,
4011                                                 theCommandLineArguments))
4012     {
4013       theDrawInterpretor << "Wrong command arguments.\n"
4014                             "Type 'help "
4015                          << theCommandLineArguments[0] << "' for information about command options and its arguments.\n";
4016       return TCL_ERROR;
4017     }
4018     return TCL_OK;
4019   }
4020
4021 } // namespace
4022
4023 //==============================================================================
4024 //function : VScale
4025 //purpose  : View Scaling
4026 //==============================================================================
4027
4028 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4029 {
4030   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4031   if ( V3dView.IsNull() ) return 1;
4032
4033   if ( argc != 4 ) {
4034     di << argv[0] << "Invalid number of arguments\n";
4035     return 1;
4036   }
4037   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
4038   return 0;
4039 }
4040 //==============================================================================
4041 //function : VZBuffTrihedron
4042 //purpose  :
4043 //==============================================================================
4044
4045 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
4046                             Standard_Integer  theArgNb,
4047                             const char**      theArgVec)
4048 {
4049   Handle(V3d_View) aView = ViewerTest::CurrentView();
4050   if (aView.IsNull())
4051   {
4052     std::cout << "Error: no active viewer!\n";
4053     return 1;
4054   }
4055
4056   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4057
4058   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
4059   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
4060   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
4061   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
4062   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
4063   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
4064   Standard_Real                 aScale        = 0.1;
4065   Standard_Real                 aSizeRatio    = 0.8;
4066   Standard_Real                 anArrowDiam   = 0.05;
4067   Standard_Integer              aNbFacets     = 12;
4068   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4069   {
4070     Standard_CString        anArg = theArgVec[anArgIter];
4071     TCollection_AsciiString aFlag (anArg);
4072     aFlag.LowerCase();
4073     if (anUpdateTool.parseRedrawMode (aFlag))
4074     {
4075       continue;
4076     }
4077     else if (aFlag == "-on")
4078     {
4079       continue;
4080     }
4081     else if (aFlag == "-off")
4082     {
4083       aView->TriedronErase();
4084       return 0;
4085     }
4086     else if (aFlag == "-pos"
4087           || aFlag == "-position"
4088           || aFlag == "-corner")
4089     {
4090       if (++anArgIter >= theArgNb)
4091       {
4092         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4093         return 1;
4094       }
4095
4096       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
4097       aPosName.LowerCase();
4098       if (aPosName == "center")
4099       {
4100         aPosition = Aspect_TOTP_CENTER;
4101       }
4102       else if (aPosName == "left_lower"
4103             || aPosName == "lower_left"
4104             || aPosName == "leftlower"
4105             || aPosName == "lowerleft")
4106       {
4107         aPosition = Aspect_TOTP_LEFT_LOWER;
4108       }
4109       else if (aPosName == "left_upper"
4110             || aPosName == "upper_left"
4111             || aPosName == "leftupper"
4112             || aPosName == "upperleft")
4113       {
4114         aPosition = Aspect_TOTP_LEFT_UPPER;
4115       }
4116       else if (aPosName == "right_lower"
4117             || aPosName == "lower_right"
4118             || aPosName == "rightlower"
4119             || aPosName == "lowerright")
4120       {
4121         aPosition = Aspect_TOTP_RIGHT_LOWER;
4122       }
4123       else if (aPosName == "right_upper"
4124             || aPosName == "upper_right"
4125             || aPosName == "rightupper"
4126             || aPosName == "upperright")
4127       {
4128         aPosition = Aspect_TOTP_RIGHT_UPPER;
4129       }
4130       else
4131       {
4132         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
4133         return 1;
4134       }
4135     }
4136     else if (aFlag == "-type")
4137     {
4138       if (++anArgIter >= theArgNb)
4139       {
4140         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4141         return 1;
4142       }
4143
4144       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
4145       aTypeName.LowerCase();
4146       if (aTypeName == "wireframe"
4147        || aTypeName == "wire")
4148       {
4149         aVisType = V3d_WIREFRAME;
4150       }
4151       else if (aTypeName == "zbuffer"
4152             || aTypeName == "shaded")
4153       {
4154         aVisType = V3d_ZBUFFER;
4155       }
4156       else
4157       {
4158         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
4159       }
4160     }
4161     else if (aFlag == "-scale")
4162     {
4163       if (++anArgIter >= theArgNb)
4164       {
4165         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4166         return 1;
4167       }
4168
4169       aScale = Draw::Atof (theArgVec[anArgIter]);
4170     }
4171     else if (aFlag == "-size"
4172           || aFlag == "-sizeratio")
4173     {
4174       if (++anArgIter >= theArgNb)
4175       {
4176         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4177         return 1;
4178       }
4179
4180       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
4181     }
4182     else if (aFlag == "-arrowdiam"
4183           || aFlag == "-arrowdiameter")
4184     {
4185       if (++anArgIter >= theArgNb)
4186       {
4187         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4188         return 1;
4189       }
4190
4191       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
4192     }
4193     else if (aFlag == "-nbfacets")
4194     {
4195       if (++anArgIter >= theArgNb)
4196       {
4197         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4198         return 1;
4199       }
4200
4201       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
4202     }
4203     else if (aFlag == "-colorlabel"
4204           || aFlag == "-colorlabels")
4205     {
4206       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4207                                                            theArgVec + anArgIter + 1,
4208                                                            aLabelsColor);
4209       if (aNbParsed == 0)
4210       {
4211         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4212         return 1;
4213       }
4214       anArgIter += aNbParsed;
4215     }
4216     else if (aFlag == "-colorarrowx")
4217     {
4218       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4219                                                            theArgVec + anArgIter + 1,
4220                                                            anArrowColorX);
4221       if (aNbParsed == 0)
4222       {
4223         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4224         return 1;
4225       }
4226       anArgIter += aNbParsed;
4227     }
4228     else if (aFlag == "-colorarrowy")
4229     {
4230       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4231                                                            theArgVec + anArgIter + 1,
4232                                                            anArrowColorY);
4233       if (aNbParsed == 0)
4234       {
4235         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4236         return 1;
4237       }
4238       anArgIter += aNbParsed;
4239     }
4240     else if (aFlag == "-colorarrowz")
4241     {
4242       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4243                                                            theArgVec + anArgIter + 1,
4244                                                            anArrowColorZ);
4245       if (aNbParsed == 0)
4246       {
4247         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4248         return 1;
4249       }
4250       anArgIter += aNbParsed;
4251     }
4252     else
4253     {
4254       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4255       return 1;
4256     }
4257   }
4258
4259   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
4260                                aSizeRatio, anArrowDiam, aNbFacets);
4261   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
4262   aView->ZFitAll();
4263   return 0;
4264 }
4265
4266 //==============================================================================
4267 //function : VRotate
4268 //purpose  : Camera Rotating
4269 //==============================================================================
4270
4271 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
4272 {
4273   Handle(V3d_View) aView = ViewerTest::CurrentView();
4274   if (aView.IsNull())
4275   {
4276     std::cout << "No active view!\n";
4277     return 1;
4278   }
4279
4280   Standard_Boolean hasFlags = Standard_False;
4281   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4282   {
4283     Standard_CString        anArg (theArgVec[anArgIter]);
4284     TCollection_AsciiString aFlag (anArg);
4285     aFlag.LowerCase();
4286     if (aFlag == "-mousestart"
4287      || aFlag == "-mousefrom")
4288     {
4289       hasFlags = Standard_True;
4290       if (anArgIter + 2 >= theArgNb)
4291       {
4292         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4293         return 1;
4294       }
4295
4296       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4297       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4298       aView->StartRotation (anX, anY);
4299     }
4300     else if (aFlag == "-mousemove")
4301     {
4302       hasFlags = Standard_True;
4303       if (anArgIter + 2 >= theArgNb)
4304       {
4305         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4306         return 1;
4307       }
4308
4309       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4310       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4311       aView->Rotation (anX, anY);
4312     }
4313     else if (theArgNb != 4
4314           && theArgNb != 7)
4315     {
4316       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4317       return 1;
4318     }
4319   }
4320
4321   if (hasFlags)
4322   {
4323     return 0;
4324   }
4325   else if (theArgNb == 4)
4326   {
4327     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4328     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4329     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4330     aView->Rotate (anAX, anAY, anAZ);
4331     return 0;
4332   }
4333   else if (theArgNb == 7)
4334   {
4335     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4336     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4337     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4338
4339     Standard_Real anX = Draw::Atof (theArgVec[4]);
4340     Standard_Real anY = Draw::Atof (theArgVec[5]);
4341     Standard_Real anZ = Draw::Atof (theArgVec[6]);
4342
4343     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
4344     return 0;
4345   }
4346
4347   std::cout << "Error: Invalid number of arguments\n";
4348   return 1;
4349 }
4350
4351 //==============================================================================
4352 //function : VZoom
4353 //purpose  : View zoom in / out (relative to current zoom)
4354 //==============================================================================
4355
4356 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4357   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4358   if ( V3dView.IsNull() ) {
4359     return 1;
4360   }
4361
4362   if ( argc == 2 ) {
4363     Standard_Real coef = Draw::Atof(argv[1]);
4364     if ( coef <= 0.0 ) {
4365       di << argv[1] << "Invalid value\n";
4366       return 1;
4367     }
4368     V3dView->SetZoom( Draw::Atof(argv[1]) );
4369     return 0;
4370   } else {
4371     di << argv[0] << " Invalid number of arguments\n";
4372     return 1;
4373   }
4374 }
4375
4376 //==============================================================================
4377 //function : VPan
4378 //purpose  : View panning (in pixels)
4379 //==============================================================================
4380
4381 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4382   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4383   if ( V3dView.IsNull() ) return 1;
4384
4385   if ( argc == 3 ) {
4386     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
4387     return 0;
4388   } else {
4389     di << argv[0] << " Invalid number of arguments\n";
4390     return 1;
4391   }
4392 }
4393
4394 //==============================================================================
4395 //function : VPlace
4396 //purpose  : Place the point (in pixels) at the center of the window
4397 //==============================================================================
4398 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
4399 {
4400   Handle(V3d_View) aView = ViewerTest::CurrentView();
4401   if (aView.IsNull())
4402   {
4403     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
4404     return 1;
4405   }
4406
4407   if (theArgNb != 3)
4408   {
4409     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
4410     return 1;
4411   }
4412
4413   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
4414
4415   return 0;
4416 }
4417
4418 static int VColorScale (Draw_Interpretor& theDI,
4419                         Standard_Integer  theArgNb,
4420                         const char**      theArgVec)
4421 {
4422   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4423   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
4424   if (aContext.IsNull())
4425   {
4426     std::cout << "Error: no active view!\n";
4427     return 1;
4428   }
4429   if (theArgNb <= 1)
4430   {
4431     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
4432     return 1;
4433   }
4434
4435   Handle(AIS_ColorScale) aColorScale;
4436   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
4437   {
4438     // find existing object
4439     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
4440     if (aColorScale.IsNull())
4441     {
4442       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
4443       return 1;
4444     }
4445   }
4446
4447   if (theArgNb <= 2)
4448   {
4449     if (aColorScale.IsNull())
4450     {
4451       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
4452       return 1;
4453     }
4454
4455     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
4456           << "Min range: "            << aColorScale->GetMin() << "\n"
4457           << "Max range: "            << aColorScale->GetMax() << "\n"
4458           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
4459           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
4460           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
4461           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
4462           << "Label position: ";
4463     switch (aColorScale->GetLabelPosition())
4464     {
4465       case Aspect_TOCSP_NONE:
4466         theDI << "None\n";
4467         break;
4468       case Aspect_TOCSP_LEFT:
4469         theDI << "Left\n";
4470         break;
4471       case Aspect_TOCSP_RIGHT:
4472         theDI << "Right\n";
4473         break;
4474       case Aspect_TOCSP_CENTER:
4475         theDI << "Center\n";
4476         break;
4477     }
4478     return 0;
4479   }
4480
4481   if (aColorScale.IsNull())
4482   {
4483     aColorScale = new AIS_ColorScale();
4484     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4485     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4486   }
4487
4488   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
4489   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
4490   {
4491     Standard_CString        anArg = theArgVec[anArgIter];
4492     TCollection_AsciiString aFlag (anArg);
4493     aFlag.LowerCase();
4494     if (anUpdateTool.parseRedrawMode (aFlag))
4495     {
4496       continue;
4497     }
4498     else if (aFlag == "-range")
4499     {
4500       if (anArgIter + 3 >= theArgNb)
4501       {
4502         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4503         return 1;
4504       }
4505
4506       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
4507       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
4508       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
4509       if (!aRangeMin.IsRealValue()
4510        || !aRangeMax.IsRealValue())
4511       {
4512         std::cout << "Error: the range values should be real!\n";
4513         return 1;
4514       }
4515       else if (!aNbIntervals.IsIntegerValue())
4516       {
4517         std::cout << "Error: the number of intervals should be integer!\n";
4518         return 1;
4519       }
4520
4521       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
4522       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
4523     }
4524     else if (aFlag == "-font")
4525     {
4526       if (anArgIter + 1 >= theArgNb)
4527       {
4528         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4529         return 1;
4530       }
4531       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
4532       if (!aFontArg.IsIntegerValue())
4533       {
4534         std::cout << "Error: HeightFont value should be integer!\n";
4535         return 1;
4536       }
4537
4538       aColorScale->SetTextHeight (aFontArg.IntegerValue());
4539       anArgIter += 1;
4540     }
4541     else if (aFlag == "-textpos")
4542     {
4543       if (anArgIter + 1 >= theArgNb)
4544       {
4545         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4546         return 1;
4547       }
4548
4549       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
4550       aTextPosArg.LowerCase();
4551       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
4552       if (aTextPosArg == "none")
4553       {
4554         aLabPosition = Aspect_TOCSP_NONE;
4555       }
4556       else if (aTextPosArg == "left")
4557       {
4558         aLabPosition = Aspect_TOCSP_LEFT;
4559       }
4560       else if (aTextPosArg == "right")
4561       {
4562         aLabPosition = Aspect_TOCSP_RIGHT;
4563       }
4564       else if (aTextPosArg == "center")
4565       {
4566         aLabPosition = Aspect_TOCSP_CENTER;
4567       }
4568       else
4569       {
4570         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
4571         return 1;
4572       }
4573       aColorScale->SetLabelPosition (aLabPosition);
4574     }
4575     else if (aFlag == "-logarithmic"
4576           || aFlag == "-log")
4577     {
4578       if (anArgIter + 1 >= theArgNb)
4579       {
4580         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4581         return 1;
4582       }
4583
4584       Standard_Boolean IsLog;
4585       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
4586       {
4587         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4588         return 1;
4589       }
4590       aColorScale->SetLogarithmic (IsLog);
4591     }
4592     else if (aFlag == "-huerange"
4593           || aFlag == "-hue")
4594     {
4595       if (anArgIter + 2 >= theArgNb)
4596       {
4597         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4598         return 1;
4599       }
4600
4601       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
4602       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
4603       aColorScale->SetHueRange (aHueMin, aHueMax);
4604     }
4605     else if (aFlag == "-colorrange")
4606     {
4607       Quantity_Color aColorMin, aColorMax;
4608       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4609                                                             theArgVec + (anArgIter + 1),
4610                                                             aColorMin);
4611       anArgIter += aNbParsed1;
4612       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4613                                                             theArgVec + (anArgIter + 1),
4614                                                             aColorMax);
4615       anArgIter += aNbParsed2;
4616       if (aNbParsed1 == 0
4617        || aNbParsed2 == 0)
4618       {
4619         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4620         return 1;
4621       }
4622
4623       aColorScale->SetColorRange (aColorMin, aColorMax);
4624     }
4625     else if (aFlag == "-reversed"
4626           || aFlag == "-inverted"
4627           || aFlag == "-topdown"
4628           || aFlag == "-bottomup")
4629     {
4630       Standard_Boolean toEnable = Standard_True;
4631       if (anArgIter + 1 < theArgNb
4632        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
4633       {
4634         ++anArgIter;
4635       }
4636       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
4637     }
4638     else if (aFlag == "-smooth"
4639           || aFlag == "-smoothtransition")
4640     {
4641       Standard_Boolean toEnable = Standard_True;
4642       if (anArgIter + 1 < theArgNb
4643        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4644       {
4645         ++anArgIter;
4646       }
4647       aColorScale->SetSmoothTransition (toEnable);
4648     }
4649     else if (aFlag == "-xy")
4650     {
4651       if (anArgIter + 2 >= theArgNb)
4652       {
4653         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4654         return 1;
4655       }
4656
4657       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
4658       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
4659       if (!anX.IsIntegerValue()
4660        || !anY.IsIntegerValue())
4661       {
4662         std::cout << "Error: coordinates should be integer values!\n";
4663         return 1;
4664       }
4665
4666       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
4667     }
4668     else if (aFlag == "-width"
4669           || aFlag == "-w"
4670           || aFlag == "-breadth")
4671     {
4672       if (anArgIter + 1 >= theArgNb)
4673       {
4674         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4675         return 1;
4676       }
4677
4678       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
4679       if (!aBreadth.IsIntegerValue())
4680       {
4681         std::cout << "Error: a width should be an integer value!\n";
4682         return 1;
4683       }
4684       aColorScale->SetBreadth (aBreadth.IntegerValue());
4685     }
4686     else if (aFlag == "-height"
4687           || aFlag == "-h")
4688     {
4689       if (anArgIter + 1 >= theArgNb)
4690       {
4691         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4692         return 1;
4693       }
4694
4695       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
4696       if (!aHeight.IsIntegerValue())
4697       {
4698         std::cout << "Error: a width should be an integer value!\n";
4699         return 1;
4700       }
4701       aColorScale->SetHeight (aHeight.IntegerValue());
4702     }
4703     else if (aFlag == "-color")
4704     {
4705       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4706       {
4707         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
4708         return 1;
4709       }
4710       else if (anArgIter + 2 >= theArgNb)
4711       {
4712         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4713         return 1;
4714       }
4715
4716       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
4717       if (!anInd.IsIntegerValue())
4718       {
4719         std::cout << "Error: Index value should be integer!\n";
4720         return 1;
4721       }
4722       const Standard_Integer anIndex = anInd.IntegerValue();
4723       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
4724       {
4725         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
4726         return 1;
4727       }
4728
4729       Quantity_Color aColor;
4730       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4731                                                            theArgVec + (anArgIter + 1),
4732                                                            aColor);
4733       if (aNbParsed == 0)
4734       {
4735         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4736         return 1;
4737       }
4738       aColorScale->SetIntervalColor (aColor, anIndex);
4739       aColorScale->SetColorType (Aspect_TOCSD_USER);
4740       anArgIter += aNbParsed;
4741     }
4742     else if (aFlag == "-label")
4743     {
4744       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4745       {
4746         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4747         return 1;
4748       }
4749       else if (anArgIter + 2 >= theArgNb)
4750       {
4751         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4752         return 1;
4753       }
4754
4755       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4756       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4757       {
4758         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4759         return 1;
4760       }
4761
4762       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4763       aColorScale->SetLabel     (aText, anIndex);
4764       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4765       anArgIter += 2;
4766     }
4767     else if (aFlag == "-labelat"
4768           || aFlag == "-labat"
4769           || aFlag == "-labelatborder"
4770           || aFlag == "-labatborder"
4771           || aFlag == "-labelatcenter"
4772           || aFlag == "-labatcenter")
4773     {
4774       Standard_Boolean toEnable = Standard_True;
4775       if (aFlag == "-labelat"
4776        || aFlag == "-labat")
4777       {
4778         Standard_Integer aLabAtBorder = -1;
4779         if (++anArgIter >= theArgNb)
4780         {
4781           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4782           anAtBorder.LowerCase();
4783           if (anAtBorder == "border")
4784           {
4785             aLabAtBorder = 1;
4786           }
4787           else if (anAtBorder == "center")
4788           {
4789             aLabAtBorder = 0;
4790           }
4791         }
4792         if (aLabAtBorder == -1)
4793         {
4794           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4795           return 1;
4796         }
4797         toEnable = (aLabAtBorder == 1);
4798       }
4799       else if (anArgIter + 1 < theArgNb
4800             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4801       {
4802         ++anArgIter;
4803       }
4804       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4805                                   || aFlag == "-labatcenter"
4806                                    ? !toEnable
4807                                    :  toEnable);
4808     }
4809     else if (aFlag == "-colors")
4810     {
4811       Aspect_SequenceOfColor aSeq;
4812       for (;;)
4813       {
4814         Quantity_Color aColor;
4815         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4816                                                              theArgVec + (anArgIter + 1),
4817                                                              aColor);
4818         if (aNbParsed == 0)
4819         {
4820           break;
4821         }
4822         anArgIter += aNbParsed;
4823         aSeq.Append (aColor);
4824       }
4825       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4826       {
4827         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4828                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4829         return 1;
4830       }
4831
4832       aColorScale->SetColors    (aSeq);
4833       aColorScale->SetColorType (Aspect_TOCSD_USER);
4834     }
4835     else if (aFlag == "-labels"
4836           || aFlag == "-freelabels")
4837     {
4838       if (anArgIter + 1 >= theArgNb)
4839       {
4840         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4841         return 1;
4842       }
4843
4844       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4845                                  ? aColorScale->GetNumberOfIntervals() + 1
4846                                  : aColorScale->GetNumberOfIntervals();
4847       if (aFlag == "-freelabels")
4848       {
4849         ++anArgIter;
4850         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4851       }
4852       if (anArgIter + aNbLabels >= theArgNb)
4853       {
4854         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4855         return 1;
4856       }
4857
4858       TColStd_SequenceOfExtendedString aSeq;
4859       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4860       {
4861         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4862       }
4863       aColorScale->SetLabels (aSeq);
4864       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4865     }
4866     else if (aFlag == "-title")
4867     {
4868       if (anArgIter + 1 >= theArgNb)
4869       {
4870         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4871         return 1;
4872       }
4873
4874       Standard_Boolean isTwoArgs = Standard_False;
4875       if (anArgIter + 2 < theArgNb)
4876       {
4877         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4878         aSecondArg.LowerCase();
4879       Standard_DISABLE_DEPRECATION_WARNINGS
4880         if (aSecondArg == "none")
4881         {
4882           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4883           isTwoArgs = Standard_True;
4884         }
4885         else if (aSecondArg == "left")
4886         {
4887           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4888           isTwoArgs = Standard_True;
4889         }
4890         else if (aSecondArg == "right")
4891         {
4892           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4893           isTwoArgs = Standard_True;
4894         }
4895         else if (aSecondArg == "center")
4896         {
4897           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4898           isTwoArgs = Standard_True;
4899         }
4900       Standard_ENABLE_DEPRECATION_WARNINGS
4901       }
4902
4903       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4904       if (isTwoArgs)
4905       {
4906         anArgIter += 1;
4907       }
4908       anArgIter += 1;
4909     }
4910     else if (aFlag == "-demoversion"
4911           || aFlag == "-demo")
4912     {
4913       aColorScale->SetPosition (0, 0);
4914       aColorScale->SetTextHeight (16);
4915       aColorScale->SetRange (0.0, 100.0);
4916       aColorScale->SetNumberOfIntervals (10);
4917       aColorScale->SetBreadth (0);
4918       aColorScale->SetHeight  (0);
4919       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4920       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4921       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4922     }
4923     else if (aFlag == "-findcolor")
4924     {
4925       if (anArgIter + 1 >= theArgNb)
4926       {
4927         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4928         return 1;
4929       }
4930
4931       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4932
4933       if (!anArg1.IsRealValue())
4934       {
4935         std::cout << "Error: the value should be real!\n";
4936         return 1;
4937       }
4938
4939       Quantity_Color aColor;
4940       aColorScale->FindColor (anArg1.RealValue(), aColor);
4941       theDI << Quantity_Color::StringName (aColor.Name());
4942       return 0;
4943     }
4944     else
4945     {
4946       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4947       return 1;
4948     }
4949   }
4950
4951   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4952   aView->Window()->Size (aWinWidth, aWinHeight);
4953   if (aColorScale->GetBreadth() == 0)
4954   {
4955     aColorScale->SetBreadth (aWinWidth);
4956   }
4957   if (aColorScale->GetHeight() == 0)
4958   {
4959     aColorScale->SetHeight (aWinHeight);
4960   }
4961   aColorScale->SetToUpdate();
4962   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4963   return 0;
4964 }
4965
4966 //==============================================================================
4967 //function : VGraduatedTrihedron
4968 //purpose  : Displays or hides a graduated trihedron
4969 //==============================================================================
4970 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4971                                   Quantity_Color& theColor)
4972 {
4973   Quantity_NameOfColor aColorName;
4974   TCollection_AsciiString aVal = theValue;
4975   aVal.UpperCase();
4976   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4977   {
4978     return Standard_False;
4979   }
4980   theColor = Quantity_Color (aColorName);
4981   return Standard_True;
4982 }
4983
4984 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4985 {
4986   if (theArgNum < 2)
4987   {
4988     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4989               << theArgs[0] <<"' for more information.\n";
4990     return 1;  //TCL_ERROR
4991   }
4992
4993   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4994   TCollection_AsciiString aParseKey;
4995   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4996   {
4997     TCollection_AsciiString anArg (theArgs [anArgIt]);
4998
4999     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
5000     {
5001       aParseKey = anArg;
5002       aParseKey.Remove (1);
5003       aParseKey.LowerCase();
5004       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
5005       continue;
5006     }
5007
5008     if (aParseKey.IsEmpty())
5009     {
5010       continue;
5011     }
5012
5013     aMapOfArgs(aParseKey)->Append (anArg);
5014   }
5015
5016   // Check parameters
5017   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
5018        aMapIt.More(); aMapIt.Next())
5019   {
5020     const TCollection_AsciiString& aKey = aMapIt.Key();
5021     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
5022
5023     // Bool key, without arguments
5024     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
5025         && anArgs->IsEmpty())
5026     {
5027       continue;
5028     }
5029
5030     // One argument
5031     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
5032           && anArgs->Length() == 1)
5033     {
5034       continue;
5035     }
5036
5037     // On/off arguments
5038     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
5039         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
5040         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
5041         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
5042         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
5043     {
5044       continue;
5045     }
5046
5047     // One string argument
5048     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
5049           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
5050           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5051     {
5052       continue;
5053     }
5054
5055     // One integer argument
5056     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
5057           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
5058           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
5059           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
5060          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
5061     {
5062       continue;
5063     }
5064
5065     // One real argument
5066     if ( aKey.IsEqual ("arrowlength")
5067          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
5068     {
5069       continue;
5070     }
5071
5072     // Two string arguments
5073     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
5074          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5075     {
5076       continue;
5077     }
5078
5079     TCollection_AsciiString aLowerKey;
5080     aLowerKey  = "-";
5081     aLowerKey += aKey;
5082     aLowerKey.LowerCase();
5083     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
5084     std::cout << "Type help for more information.\n";
5085     return 1;
5086   }
5087
5088   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
5089   if (anAISContext.IsNull())
5090   {
5091     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
5092     return 1;
5093   }
5094
5095   Standard_Boolean toDisplay = Standard_True;
5096   Quantity_Color aColor;
5097   Graphic3d_GraduatedTrihedron aTrihedronData;
5098   // Process parameters
5099   Handle(TColStd_HSequenceOfAsciiString) aValues;
5100   if (aMapOfArgs.Find ("off", aValues))
5101   {
5102     toDisplay = Standard_False;
5103   }
5104
5105   // AXES NAMES
5106   if (aMapOfArgs.Find ("xname", aValues))
5107   {
5108     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
5109   }
5110   if (aMapOfArgs.Find ("yname", aValues))
5111   {
5112     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
5113   }
5114   if (aMapOfArgs.Find ("zname", aValues))
5115   {
5116     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
5117   }
5118   if (aMapOfArgs.Find ("xdrawname", aValues))
5119   {
5120     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5121   }
5122   if (aMapOfArgs.Find ("ydrawname", aValues))
5123   {
5124     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5125   }
5126   if (aMapOfArgs.Find ("zdrawname", aValues))
5127   {
5128     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5129   }
5130   if (aMapOfArgs.Find ("xnameoffset", aValues))
5131   {
5132     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5133   }
5134   if (aMapOfArgs.Find ("ynameoffset", aValues))
5135   {
5136     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5137   }
5138   if (aMapOfArgs.Find ("znameoffset", aValues))
5139   {
5140     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5141   }
5142
5143   // COLORS
5144   if (aMapOfArgs.Find ("xnamecolor", aValues))
5145   {
5146     if (!GetColor (aValues->Value(1), aColor))
5147     {
5148       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
5149       return 1;
5150     }
5151     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
5152   }
5153   if (aMapOfArgs.Find ("ynamecolor", aValues))
5154   {
5155     if (!GetColor (aValues->Value(1), aColor))
5156     {
5157       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
5158       return 1;
5159     }
5160     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
5161   }
5162   if (aMapOfArgs.Find ("znamecolor", aValues))
5163   {
5164     if (!GetColor (aValues->Value(1), aColor))
5165     {
5166       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
5167       return 1;
5168     }
5169     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
5170   }
5171   if (aMapOfArgs.Find ("xcolor", aValues))
5172   {
5173     if (!GetColor (aValues->Value(1), aColor))
5174     {
5175       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
5176       return 1;
5177     }
5178     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
5179   }
5180   if (aMapOfArgs.Find ("ycolor", aValues))
5181   {
5182     if (!GetColor (aValues->Value(1), aColor))
5183     {
5184       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
5185       return 1;
5186     }
5187     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
5188   }
5189   if (aMapOfArgs.Find ("zcolor", aValues))
5190   {
5191     if (!GetColor (aValues->Value(1), aColor))
5192     {
5193       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
5194       return 1;
5195     }
5196     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
5197   }
5198
5199   // TICKMARKS
5200   if (aMapOfArgs.Find ("xticks", aValues))
5201   {
5202     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5203   }
5204   if (aMapOfArgs.Find ("yticks", aValues))
5205   {
5206     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5207   }
5208   if (aMapOfArgs.Find ("zticks", aValues))
5209   {
5210     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5211   }
5212   if (aMapOfArgs.Find ("xticklength", aValues))
5213   {
5214     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5215   }
5216   if (aMapOfArgs.Find ("yticklength", aValues))
5217   {
5218     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5219   }
5220   if (aMapOfArgs.Find ("zticklength", aValues))
5221   {
5222     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5223   }
5224   if (aMapOfArgs.Find ("xdrawticks", aValues))
5225   {
5226     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5227   }
5228   if (aMapOfArgs.Find ("ydrawticks", aValues))
5229   {
5230     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5231   }
5232   if (aMapOfArgs.Find ("zdrawticks", aValues))
5233   {
5234     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5235   }
5236
5237   // VALUES
5238   if (aMapOfArgs.Find ("xdrawvalues", aValues))
5239   {
5240     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5241   }
5242   if (aMapOfArgs.Find ("ydrawvalues", aValues))
5243   {
5244     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5245   }
5246   if (aMapOfArgs.Find ("zdrawvalues", aValues))
5247   {
5248     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5249   }
5250   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
5251   {
5252     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5253   }
5254   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
5255   {
5256     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5257   }
5258   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
5259   {
5260     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5261   }
5262
5263   // ARROWS
5264   if (aMapOfArgs.Find ("arrowlength", aValues))
5265   {
5266     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
5267   }
5268
5269   // FONTS
5270   if (aMapOfArgs.Find ("namefont", aValues))
5271   {
5272     aTrihedronData.SetNamesFont (aValues->Value(1));
5273   }
5274   if (aMapOfArgs.Find ("valuesfont", aValues))
5275   {
5276     aTrihedronData.SetValuesFont (aValues->Value(1));
5277   }
5278
5279   if (aMapOfArgs.Find ("drawgrid", aValues))
5280   {
5281     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
5282   }
5283   if (aMapOfArgs.Find ("drawaxes", aValues))
5284   {
5285     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
5286   }
5287
5288   // The final step: display of erase trihedron
5289   if (toDisplay)
5290   {
5291     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
5292   }
5293   else
5294   {
5295     ViewerTest::CurrentView()->GraduatedTrihedronErase();
5296   }
5297
5298   ViewerTest::GetAISContext()->UpdateCurrentViewer();
5299   ViewerTest::CurrentView()->Redraw();
5300
5301   return 0;
5302 }
5303
5304 //==============================================================================
5305 //function : VTile
5306 //purpose  :
5307 //==============================================================================
5308 static int VTile (Draw_Interpretor& theDI,
5309                   Standard_Integer  theArgNb,
5310                   const char**      theArgVec)
5311 {
5312   Handle(V3d_View) aView = ViewerTest::CurrentView();
5313   if (aView.IsNull())
5314   {
5315     std::cerr << "Error: no active viewer.\n";
5316     return 1;
5317   }
5318
5319   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
5320   if (theArgNb < 2)
5321   {
5322     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
5323           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
5324           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
5325     return 0;
5326   }
5327
5328   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
5329   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5330   {
5331     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5332     anArg.LowerCase();
5333     if (anArg == "-lowerleft"
5334      || anArg == "-upperleft")
5335     {
5336       if (anArgIter + 3 < theArgNb)
5337       {
5338         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5339         return 1;
5340       }
5341       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
5342       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5343       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5344     }
5345     else if (anArg == "-total"
5346           || anArg == "-totalsize"
5347           || anArg == "-viewsize")
5348     {
5349       if (anArgIter + 3 < theArgNb)
5350       {
5351         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5352         return 1;
5353       }
5354       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5355       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5356       if (aTile.TotalSize.x() < 1
5357        || aTile.TotalSize.y() < 1)
5358       {
5359         std::cerr << "Error: total size is incorrect.\n";
5360         return 1;
5361       }
5362     }
5363     else if (anArg == "-tilesize")
5364     {
5365       if (anArgIter + 3 < theArgNb)
5366       {
5367         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5368         return 1;
5369       }
5370
5371       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5372       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5373       if (aTile.TileSize.x() < 1
5374        || aTile.TileSize.y() < 1)
5375       {
5376         std::cerr << "Error: tile size is incorrect.\n";
5377         return 1;
5378       }
5379     }
5380     else if (anArg == "-unset")
5381     {
5382       aView->Camera()->SetTile (Graphic3d_CameraTile());
5383       aView->Redraw();
5384       return 0;
5385     }
5386   }
5387
5388   if (aTile.TileSize.x() < 1
5389    || aTile.TileSize.y() < 1)
5390   {
5391     std::cerr << "Error: tile size is undefined.\n";
5392     return 1;
5393   }
5394   else if (aTile.TotalSize.x() < 1
5395         || aTile.TotalSize.y() < 1)
5396   {
5397     std::cerr << "Error: total size is undefined.\n";
5398     return 1;
5399   }
5400
5401   aView->Camera()->SetTile (aTile);
5402   aView->Redraw();
5403   return 0;
5404 }
5405
5406 //! Format ZLayer ID.
5407 inline const char* formZLayerId (const Standard_Integer theLayerId)
5408 {
5409   switch (theLayerId)
5410   {
5411     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
5412     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
5413     case Graphic3d_ZLayerId_Top:     return "[TOP]";
5414     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
5415     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
5416     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
5417   }
5418   return "";
5419 }
5420
5421 //! Print the ZLayer information.
5422 inline void printZLayerInfo (Draw_Interpretor& theDI,
5423                              const Graphic3d_ZLayerSettings& theLayer)
5424 {
5425   if (!theLayer.Name().IsEmpty())
5426   {
5427     theDI << "  Name: " << theLayer.Name() << "\n";
5428   }
5429   if (theLayer.IsImmediate())
5430   {
5431     theDI << "  Immediate: TRUE\n";
5432   }
5433   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
5434   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
5435   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
5436   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
5437   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
5438   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
5439   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
5440   {
5441     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
5442   }
5443 }
5444
5445 //==============================================================================
5446 //function : VZLayer
5447 //purpose  : Test z layer operations for v3d viewer
5448 //==============================================================================
5449 static int VZLayer (Draw_Interpretor& theDI,
5450                     Standard_Integer  theArgNb,
5451                     const char**      theArgVec)
5452 {
5453   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5454   if (aContextAIS.IsNull())
5455   {
5456     std::cout << "No active viewer!\n";
5457     return 1;
5458   }
5459
5460   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
5461   if (theArgNb < 2)
5462   {
5463     TColStd_SequenceOfInteger aLayers;
5464     aViewer->GetAllZLayers (aLayers);
5465     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5466     {
5467       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
5468       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
5469       printZLayerInfo (theDI, aSettings);
5470     }
5471     return 1;
5472   }
5473
5474   Standard_Integer anArgIter = 1;
5475   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5476   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
5477   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5478   {
5479     ++anArgIter;
5480   }
5481
5482   {
5483     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
5484     if (aFirstArg.IsIntegerValue())
5485     {
5486       ++anArgIter;
5487       aLayerId = aFirstArg.IntegerValue();
5488     }
5489     else
5490     {
5491       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
5492       {
5493         ++anArgIter;
5494       }
5495     }
5496   }
5497
5498   Graphic3d_ZLayerId anOtherLayerId = Graphic3d_ZLayerId_UNKNOWN;
5499   for (; anArgIter < theArgNb; ++anArgIter)
5500   {
5501     // perform operation
5502     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5503     anArg.LowerCase();
5504     if (anUpdateTool.parseRedrawMode (anArg))
5505     {
5506       //
5507     }
5508     else if (anArg == "-add"
5509           || anArg == "add")
5510     {
5511       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5512       if (!aViewer->AddZLayer (aLayerId))
5513       {
5514         std::cout << "Error: can not add a new z layer!\n";
5515         return 0;
5516       }
5517
5518       theDI << aLayerId;
5519     }
5520     else if (anArg == "-insertbefore"
5521           && anArgIter + 1 < theArgNb
5522           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5523     {
5524       ++anArgIter;
5525       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5526       if (!aViewer->InsertLayerBefore (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5527       {
5528         std::cout << "Error: can not add a new z layer!\n";
5529         return 0;
5530       }
5531
5532       theDI << aLayerId;
5533     }
5534     else if (anArg == "-insertafter"
5535           && anArgIter + 1 < theArgNb
5536           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5537     {
5538       ++anArgIter;
5539       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5540       if (!aViewer->InsertLayerAfter (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5541       {
5542         std::cout << "Error: can not add a new z layer!\n";
5543         return 0;
5544       }
5545
5546       theDI << aLayerId;
5547     }
5548     else if (anArg == "-del"
5549           || anArg == "-delete"
5550           || anArg == "del")
5551     {
5552       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5553       {
5554         if (++anArgIter >= theArgNb)
5555         {
5556           std::cout << "Syntax error: id of z layer to remove is missing\n";
5557           return 1;
5558         }
5559
5560         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5561       }
5562
5563       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
5564        || aLayerId == Graphic3d_ZLayerId_Default
5565        || aLayerId == Graphic3d_ZLayerId_Top
5566        || aLayerId == Graphic3d_ZLayerId_Topmost
5567        || aLayerId == Graphic3d_ZLayerId_TopOSD
5568        || aLayerId == Graphic3d_ZLayerId_BotOSD)
5569       {
5570         std::cout << "Syntax error: standard Z layer can not be removed\n";
5571         return 1;
5572       }
5573
5574       // move all object displayed in removing layer to default layer
5575       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5576            anObjIter.More(); anObjIter.Next())
5577       {
5578         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
5579         if (aPrs.IsNull()
5580          || aPrs->ZLayer() != aLayerId)
5581         {
5582           continue;
5583         }
5584         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
5585       }
5586
5587       if (!aViewer->RemoveZLayer (aLayerId))
5588       {
5589         std::cout << "Z layer can not be removed!\n";
5590       }
5591       else
5592       {
5593         theDI << aLayerId << " ";
5594       }
5595     }
5596     else if (anArg == "-get"
5597           || anArg == "get")
5598     {
5599       TColStd_SequenceOfInteger aLayers;
5600       aViewer->GetAllZLayers (aLayers);
5601       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5602       {
5603         theDI << aLayeriter.Value() << " ";
5604       }
5605
5606       theDI << "\n";
5607     }
5608     else if (anArg == "-name")
5609     {
5610       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5611       {
5612         std::cout << "Syntax error: id of Z layer is missing\n";
5613         return 1;
5614       }
5615
5616       if (++anArgIter >= theArgNb)
5617       {
5618         std::cout << "Syntax error: name is missing\n";
5619         return 1;
5620       }
5621
5622       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5623       aSettings.SetName (theArgVec[anArgIter]);
5624       aViewer->SetZLayerSettings (aLayerId, aSettings);
5625     }
5626     else if (anArg == "-origin")
5627     {
5628       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5629       {
5630         std::cout << "Syntax error: id of Z layer is missing\n";
5631         return 1;
5632       }
5633
5634       if (anArgIter + 2 >= theArgNb)
5635       {
5636         std::cout << "Syntax error: origin coordinates are missing\n";
5637         return 1;
5638       }
5639
5640       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5641       gp_XYZ anOrigin;
5642       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5643       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5644       anOrigin.SetZ (0.0);
5645       if (anArgIter + 3 < theArgNb)
5646       {
5647         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5648         anArgIter += 3;
5649       }
5650       else
5651       {
5652         anArgIter += 2;
5653       }
5654       aSettings.SetOrigin (anOrigin);
5655       aViewer->SetZLayerSettings (aLayerId, aSettings);
5656     }
5657     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5658           && anArgIter + 1 < theArgNb
5659           && (anArg == "-cullingdistance"
5660            || anArg == "-cullingdist"
5661            || anArg == "-culldistance"
5662            || anArg == "-culldist"
5663            || anArg == "-distcull"
5664            || anArg == "-distculling"
5665            || anArg == "-distanceculling"))
5666     {
5667       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5668       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5669       aSettings.SetCullingDistance (aDist);
5670       aViewer->SetZLayerSettings (aLayerId, aSettings);
5671     }
5672     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5673           && anArgIter + 1 < theArgNb
5674           && (anArg == "-cullingsize"
5675            || anArg == "-cullsize"
5676            || anArg == "-sizecull"
5677            || anArg == "-sizeculling"))
5678     {
5679       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5680       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5681       aSettings.SetCullingSize (aSize);
5682       aViewer->SetZLayerSettings (aLayerId, aSettings);
5683     }
5684     else if (anArg == "-settings"
5685           || anArg == "settings")
5686     {
5687       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5688       {
5689         if (++anArgIter >= theArgNb)
5690         {
5691           std::cout << "Syntax error: id of Z layer is missing\n";
5692           return 1;
5693         }
5694
5695         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5696       }
5697
5698       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5699       printZLayerInfo (theDI, aSettings);
5700     }
5701     else if (anArg == "-enable"
5702           || anArg == "enable"
5703           || anArg == "-disable"
5704           || anArg == "disable")
5705     {
5706       const Standard_Boolean toEnable = anArg == "-enable"
5707                                      || anArg == "enable";
5708       if (++anArgIter >= theArgNb)
5709       {
5710         std::cout << "Syntax error: option name is missing\n";
5711         return 1;
5712       }
5713
5714       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5715       aSubOp.LowerCase();
5716       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5717       {
5718         if (++anArgIter >= theArgNb)
5719         {
5720           std::cout << "Syntax error: id of Z layer is missing\n";
5721           return 1;
5722         }
5723
5724         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5725       }
5726
5727       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5728       if (aSubOp == "depthtest"
5729        || aSubOp == "test")
5730       {
5731         aSettings.SetEnableDepthTest (toEnable);
5732       }
5733       else if (aSubOp == "depthwrite"
5734             || aSubOp == "write")
5735       {
5736         aSettings.SetEnableDepthWrite (toEnable);
5737       }
5738       else if (aSubOp == "depthclear"
5739             || aSubOp == "clear")
5740       {
5741         aSettings.SetClearDepth (toEnable);
5742       }
5743       else if (aSubOp == "depthoffset"
5744             || aSubOp == "offset")
5745       {
5746         Graphic3d_PolygonOffset aParams;
5747         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5748         if (toEnable)
5749         {
5750           if (anArgIter + 2 >= theArgNb)
5751           {
5752             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5753             return 1;
5754           }
5755
5756           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5757           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5758         }
5759         aSettings.SetPolygonOffset (aParams);
5760       }
5761       else if (aSubOp == "positiveoffset"
5762             || aSubOp == "poffset")
5763       {
5764         if (toEnable)
5765         {
5766           aSettings.SetDepthOffsetPositive();
5767         }
5768         else
5769         {
5770           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5771         }
5772       }
5773       else if (aSubOp == "negativeoffset"
5774             || aSubOp == "noffset")
5775       {
5776         if (toEnable)
5777         {
5778           aSettings.SetDepthOffsetNegative();
5779         }
5780         else
5781         {
5782           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5783         }
5784       }
5785       else if (aSubOp == "textureenv")
5786       {
5787         aSettings.SetEnvironmentTexture (toEnable);
5788       }
5789       else if (aSubOp == "raytracing")
5790       {
5791         aSettings.SetRaytracable (toEnable);
5792       }
5793
5794       aViewer->SetZLayerSettings (aLayerId, aSettings);
5795     }
5796     else
5797     {
5798       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5799       return 1;
5800     }
5801   }
5802
5803   return 0;
5804 }
5805
5806 // The interactive presentation of 2d layer item
5807 // for "vlayerline" command it provides a presentation of
5808 // line with user-defined linewidth, linetype and transparency.
5809 class V3d_LineItem : public AIS_InteractiveObject
5810 {
5811 public:
5812   // CASCADE RTTI
5813   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5814
5815   // constructor
5816   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5817                                Standard_Real X2, Standard_Real Y2,
5818                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5819                                Standard_Real theWidth    = 0.5,
5820                                Standard_Real theTransp   = 1.0);
5821
5822   private:
5823
5824   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5825                 const Handle(Prs3d_Presentation)& thePresentation,
5826                 const Standard_Integer theMode) Standard_OVERRIDE;
5827
5828   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5829                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5830   {}
5831
5832 private:
5833
5834   Standard_Real       myX1, myY1, myX2, myY2;
5835   Aspect_TypeOfLine   myType;
5836   Standard_Real       myWidth;
5837 };
5838
5839 // default constructor for line item
5840 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5841                            Standard_Real X2, Standard_Real Y2,
5842                            Aspect_TypeOfLine theType,
5843                            Standard_Real theWidth,
5844                            Standard_Real theTransp) :
5845   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5846   myType(theType), myWidth(theWidth)
5847 {
5848   SetTransparency (1-theTransp);
5849 }
5850
5851 // render line
5852 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5853                             const Handle(Prs3d_Presentation)& thePresentation,
5854                             const Standard_Integer /*theMode*/)
5855 {
5856   thePresentation->Clear();
5857   Quantity_Color aColor (Quantity_NOC_RED);
5858   Standard_Integer aWidth, aHeight;
5859   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5860   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5861   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5862   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5863   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5864   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5865   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5866   aGroup->AddPrimitiveArray (aPrim);
5867 }
5868
5869 //=============================================================================
5870 //function : VLayerLine
5871 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5872 //         : linewidth, transparency coefficient
5873 //============================================================================
5874 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5875 {
5876   // get the active view
5877   Handle(V3d_View) aView = ViewerTest::CurrentView();
5878   if (aView.IsNull())
5879   {
5880     di << "Call vinit before!\n";
5881     return 1;
5882   }
5883   else if (argc < 5)
5884   {
5885     di << "Use: " << argv[0];
5886     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5887     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5888     di << "              0 - solid  \n";
5889     di << "              1 - dashed \n";
5890     di << "              2 - dot    \n";
5891     di << "              3 - dashdot\n";
5892     di << " transparency : { 0.0 - 1.0 } \n";
5893     di << "                  0.0 - transparent\n";
5894     di << "                  1.0 - visible    \n";
5895     return 1;
5896   }
5897
5898   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5899   // get the input params
5900   Standard_Real X1 = Draw::Atof(argv[1]);
5901   Standard_Real Y1 = Draw::Atof(argv[2]);
5902   Standard_Real X2 = Draw::Atof(argv[3]);
5903   Standard_Real Y2 = Draw::Atof(argv[4]);
5904
5905   Standard_Real aWidth = 0.5;
5906   Standard_Real aTransparency = 1.0;
5907
5908   // has width
5909   if (argc > 5)
5910     aWidth = Draw::Atof(argv[5]);
5911
5912   // select appropriate line type
5913   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5914   if (argc > 6
5915   && !ViewerTest::ParseLineType (argv[6], aLineType))
5916   {
5917     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5918     return 1;
5919   }
5920
5921   // has transparency
5922   if (argc > 7)
5923   {
5924     aTransparency = Draw::Atof(argv[7]);
5925     if (aTransparency < 0 || aTransparency > 1.0)
5926       aTransparency = 1.0;
5927   }
5928
5929   static Handle (V3d_LineItem) aLine;
5930   if (!aLine.IsNull())
5931   {
5932     aContext->Erase (aLine, Standard_False);
5933   }
5934   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5935                             aLineType, aWidth,
5936                             aTransparency);
5937
5938   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5939   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5940   aLine->SetToUpdate();
5941   aContext->Display (aLine, Standard_True);
5942
5943   return 0;
5944 }
5945
5946
5947 //==============================================================================
5948 //function : VGrid
5949 //purpose  :
5950 //==============================================================================
5951
5952 static int VGrid (Draw_Interpretor& /*theDI*/,
5953                   Standard_Integer  theArgNb,
5954                   const char**      theArgVec)
5955 {
5956   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5957   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5958   if (aView.IsNull() || aViewer.IsNull())
5959   {
5960     std::cerr << "Error: no active view\n";
5961     return 1;
5962   }
5963
5964   Aspect_GridType     aType = aViewer->GridType();
5965   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5966   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5967   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5968   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
5969   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5970   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5971   {
5972     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5973     anArg.LowerCase();
5974     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5975     {
5976       continue;
5977     }
5978     else if (anArgIter + 1 < theArgNb
5979           && anArg == "-type")
5980     {
5981       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5982       anArgNext.LowerCase();
5983       if (anArgNext == "r"
5984        || anArgNext == "rect"
5985        || anArgNext == "rectangular")
5986       {
5987         aType = Aspect_GT_Rectangular;
5988       }
5989       else if (anArgNext == "c"
5990             || anArgNext == "circ"
5991             || anArgNext == "circular")
5992       {
5993         aType = Aspect_GT_Circular;
5994       }
5995       else
5996       {
5997         std::cout << "Syntax error at '" << anArgNext << "'\n";
5998         return 1;
5999       }
6000     }
6001     else if (anArgIter + 1 < theArgNb
6002           && anArg == "-mode")
6003     {
6004       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
6005       anArgNext.LowerCase();
6006       if (anArgNext == "l"
6007        || anArgNext == "line"
6008        || anArgNext == "lines")
6009       {
6010         aMode = Aspect_GDM_Lines;
6011       }
6012       else if (anArgNext == "p"
6013             || anArgNext == "point"
6014             || anArgNext == "points")
6015       {
6016         aMode = Aspect_GDM_Points;
6017       }
6018       else
6019       {
6020         std::cout << "Syntax error at '" << anArgNext << "'\n";
6021         return 1;
6022       }
6023     }
6024     else if (anArgIter + 2 < theArgNb
6025           && (anArg == "-origin"
6026            || anArg == "-orig"))
6027     {
6028       hasOrigin = true;
6029       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6030                               Draw::Atof (theArgVec[anArgIter + 2]));
6031       anArgIter += 2;
6032     }
6033     else if (anArgIter + 2 < theArgNb
6034           && anArg == "-step")
6035     {
6036       hasStep = true;
6037       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6038                             Draw::Atof (theArgVec[anArgIter + 2]));
6039       if (aNewStepXY.x() <= 0.0
6040        || aNewStepXY.y() <= 0.0)
6041       {
6042         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6043         return 1;
6044       }
6045       anArgIter += 2;
6046     }
6047     else if (anArgIter + 1 < theArgNb
6048           && (anArg == "-angle"
6049            || anArg == "-rotangle"
6050            || anArg == "-rotationangle"))
6051     {
6052       hasRotAngle = true;
6053       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
6054     }
6055     else if (anArgIter + 1 < theArgNb
6056           && (anArg == "-zoffset"
6057            || anArg == "-dz"))
6058     {
6059       hasZOffset = true;
6060       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
6061     }
6062     else if (anArgIter + 1 < theArgNb
6063           && anArg == "-radius")
6064     {
6065       hasSize = true;
6066       ++anArgIter;
6067       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
6068       if (aNewStepXY.x() <= 0.0)
6069       {
6070         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
6071         return 1;
6072       }
6073     }
6074     else if (anArgIter + 2 < theArgNb
6075           && anArg == "-size")
6076     {
6077       hasSize = true;
6078       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6079                             Draw::Atof (theArgVec[anArgIter + 2]));
6080       if (aNewStepXY.x() <= 0.0
6081        || aNewStepXY.y() <= 0.0)
6082       {
6083         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6084         return 1;
6085       }
6086       anArgIter += 2;
6087     }
6088     else if (anArg == "r"
6089           || anArg == "rect"
6090           || anArg == "rectangular")
6091     {
6092       aType = Aspect_GT_Rectangular;
6093     }
6094     else if (anArg == "c"
6095           || anArg == "circ"
6096           || anArg == "circular")
6097     {
6098       aType = Aspect_GT_Circular;
6099     }
6100     else if (anArg == "l"
6101           || anArg == "line"
6102           || anArg == "lines")
6103     {
6104       aMode = Aspect_GDM_Lines;
6105     }
6106     else if (anArg == "p"
6107           || anArg == "point"
6108           || anArg == "points")
6109     {
6110       aMode = Aspect_GDM_Points;
6111     }
6112     else if (anArgIter + 1 >= theArgNb
6113           && anArg == "off")
6114     {
6115       aViewer->DeactivateGrid();
6116       return 0;
6117     }
6118     else
6119     {
6120       std::cout << "Syntax error at '" << anArg << "'\n";
6121       return 1;
6122     }
6123   }
6124
6125   if (aType == Aspect_GT_Rectangular)
6126   {
6127     Graphic3d_Vec2d anOrigXY, aStepXY;
6128     Standard_Real aRotAngle = 0.0;
6129     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6130     if (hasOrigin)
6131     {
6132       anOrigXY = aNewOriginXY;
6133     }
6134     if (hasStep)
6135     {
6136       aStepXY = aNewStepXY;
6137     }
6138     if (hasRotAngle)
6139     {
6140       aRotAngle = aNewRotAngle;
6141     }
6142     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6143     if (hasSize || hasZOffset)
6144     {
6145       Graphic3d_Vec3d aSize;
6146       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6147       if (hasSize)
6148       {
6149         aSize.x() = aNewSizeXY.x();
6150         aSize.y() = aNewSizeXY.y();
6151       }
6152       if (hasZOffset)
6153       {
6154         aSize.z() = aNewZOffset;
6155       }
6156       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6157     }
6158   }
6159   else if (aType == Aspect_GT_Circular)
6160   {
6161     Graphic3d_Vec2d anOrigXY;
6162     Standard_Real aRadiusStep;
6163     Standard_Integer aDivisionNumber;
6164     Standard_Real aRotAngle = 0.0;
6165     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6166     if (hasOrigin)
6167     {
6168       anOrigXY = aNewOriginXY;
6169     }
6170     if (hasStep)
6171     {
6172       aRadiusStep     = aNewStepXY[0];
6173       aDivisionNumber = (int )aNewStepXY[1];
6174       if (aDivisionNumber < 1)
6175       {
6176         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
6177         return 1;
6178       }
6179     }
6180     if (hasRotAngle)
6181     {
6182       aRotAngle = aNewRotAngle;
6183     }
6184
6185     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6186     if (hasSize || hasZOffset)
6187     {
6188       Standard_Real aRadius = 0.0, aZOffset = 0.0;
6189       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
6190       if (hasSize)
6191       {
6192         aRadius = aNewSizeXY.x();
6193         if (aNewSizeXY.y() != 0.0)
6194         {
6195           std::cout << "Syntax error: circular size should be specified as radius\n";
6196           return 1;
6197         }
6198       }
6199       if (hasZOffset)
6200       {
6201         aZOffset = aNewZOffset;
6202       }
6203       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
6204     }
6205   }
6206   aViewer->ActivateGrid (aType, aMode);
6207   return 0;
6208 }
6209
6210 //==============================================================================
6211 //function : VPriviledgedPlane
6212 //purpose  :
6213 //==============================================================================
6214
6215 static int VPriviledgedPlane (Draw_Interpretor& theDI,
6216                               Standard_Integer  theArgNb,
6217                               const char**      theArgVec)
6218 {
6219   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
6220   {
6221     std::cerr << "Error: wrong number of arguments! See usage:\n";
6222     theDI.PrintHelp (theArgVec[0]);
6223     return 1;
6224   }
6225
6226   // get the active viewer
6227   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6228   if (aViewer.IsNull())
6229   {
6230     std::cerr << "Error: no active viewer. Please call vinit.\n";
6231     return 1;
6232   }
6233
6234   if (theArgNb == 1)
6235   {
6236     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
6237     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
6238     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
6239     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
6240     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
6241           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
6242           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
6243     return 0;
6244   }
6245
6246   Standard_Integer anArgIdx = 1;
6247   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
6248   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
6249   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
6250   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
6251   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
6252   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
6253
6254   gp_Ax3 aPriviledgedPlane;
6255   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
6256   gp_Dir aNorm (aNormX, aNormY, aNormZ);
6257   if (theArgNb > 7)
6258   {
6259     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
6260     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
6261     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
6262     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
6263     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
6264   }
6265   else
6266   {
6267     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
6268   }
6269
6270   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
6271
6272   return 0;
6273 }
6274
6275 //==============================================================================
6276 //function : VConvert
6277 //purpose  :
6278 //==============================================================================
6279
6280 static int VConvert (Draw_Interpretor& theDI,
6281                      Standard_Integer  theArgNb,
6282                      const char**      theArgVec)
6283 {
6284   // get the active view
6285   Handle(V3d_View) aView = ViewerTest::CurrentView();
6286   if (aView.IsNull())
6287   {
6288     std::cerr << "Error: no active view. Please call vinit.\n";
6289     return 1;
6290   }
6291
6292   enum { Model, Ray, View, Window, Grid } aMode = Model;
6293
6294   // access coordinate arguments
6295   TColStd_SequenceOfReal aCoord;
6296   Standard_Integer anArgIdx = 1;
6297   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
6298   {
6299     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6300     if (!anArg.IsRealValue())
6301     {
6302       break;
6303     }
6304     aCoord.Append (anArg.RealValue());
6305   }
6306
6307   // non-numeric argument too early
6308   if (aCoord.IsEmpty())
6309   {
6310     std::cerr << "Error: wrong number of arguments! See usage:\n";
6311     theDI.PrintHelp (theArgVec[0]);
6312     return 1;
6313   }
6314
6315   // collect all other arguments and options
6316   for (; anArgIdx < theArgNb; ++anArgIdx)
6317   {
6318     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6319     anArg.LowerCase();
6320     if      (anArg == "window") aMode = Window;
6321     else if (anArg == "view")   aMode = View;
6322     else if (anArg == "grid")   aMode = Grid;
6323     else if (anArg == "ray")    aMode = Ray;
6324     else
6325     {
6326       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
6327       theDI.PrintHelp (theArgVec[0]);
6328       return 1;
6329     }
6330   }
6331
6332   // complete input checks
6333   if ((aCoord.Length() == 1 && theArgNb > 3) ||
6334       (aCoord.Length() == 2 && theArgNb > 4) ||
6335       (aCoord.Length() == 3 && theArgNb > 5))
6336   {
6337     std::cerr << "Error: wrong number of arguments! See usage:\n";
6338     theDI.PrintHelp (theArgVec[0]);
6339     return 1;
6340   }
6341
6342   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6343   Standard_Integer aXYp[2] = {0, 0};
6344
6345   // convert one-dimensional coordinate
6346   if (aCoord.Length() == 1)
6347   {
6348     switch (aMode)
6349     {
6350       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
6351       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
6352       default:
6353         std::cerr << "Error: wrong arguments! See usage:\n";
6354         theDI.PrintHelp (theArgVec[0]);
6355         return 1;
6356     }
6357   }
6358
6359   // convert 2D coordinates from projection or view reference space
6360   if (aCoord.Length() == 2)
6361   {
6362     switch (aMode)
6363     {
6364       case Model :
6365         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6366         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6367         return 0;
6368
6369       case View :
6370         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
6371         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
6372         return 0;
6373
6374       case Window :
6375         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
6376         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6377         return 0;
6378
6379       case Grid :
6380         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6381         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
6382         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6383         return 0;
6384
6385       case Ray :
6386         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
6387                                 (Standard_Integer) aCoord (2),
6388                                 aXYZ[0], aXYZ[1], aXYZ[2],
6389                                 aXYZ[3], aXYZ[4], aXYZ[5]);
6390         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6391         return 0;
6392
6393       default:
6394         std::cerr << "Error: wrong arguments! See usage:\n";
6395         theDI.PrintHelp (theArgVec[0]);
6396         return 1;
6397     }
6398   }
6399
6400   // convert 3D coordinates from view reference space
6401   else if (aCoord.Length() == 3)
6402   {
6403     switch (aMode)
6404     {
6405       case Window :
6406         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
6407         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6408         return 0;
6409
6410       case Grid :
6411         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
6412         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6413         return 0;
6414
6415       default:
6416         std::cerr << "Error: wrong arguments! See usage:\n";
6417         theDI.PrintHelp (theArgVec[0]);
6418         return 1;
6419     }
6420   }
6421
6422   return 0;
6423 }
6424
6425 //==============================================================================
6426 //function : VFps
6427 //purpose  :
6428 //==============================================================================
6429
6430 static int VFps (Draw_Interpretor& theDI,
6431                  Standard_Integer  theArgNb,
6432                  const char**      theArgVec)
6433 {
6434   // get the active view
6435   Handle(V3d_View) aView = ViewerTest::CurrentView();
6436   if (aView.IsNull())
6437   {
6438     std::cerr << "No active view. Please call vinit.\n";
6439     return 1;
6440   }
6441
6442   Standard_Integer aFramesNb = -1;
6443   Standard_Real aDuration = -1.0;
6444   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6445   {
6446     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6447     anArg.LowerCase();
6448     if (aDuration < 0.0
6449      && anArgIter + 1 < theArgNb
6450      && (anArg == "-duration"
6451       || anArg == "-dur"
6452       || anArg == "-time"))
6453     {
6454       aDuration = Draw::Atof (theArgVec[++anArgIter]);
6455     }
6456     else if (aFramesNb < 0
6457           && anArg.IsIntegerValue())
6458     {
6459       aFramesNb = anArg.IntegerValue();
6460       if (aFramesNb <= 0)
6461       {
6462         std::cerr << "Syntax error at '" << anArg << "'\n";
6463         return 1;
6464       }
6465     }
6466     else
6467     {
6468       std::cerr << "Syntax error at '" << anArg << "'\n";
6469       return 1;
6470     }
6471   }
6472   if (aFramesNb < 0 && aDuration < 0.0)
6473   {
6474     aFramesNb = 100;
6475   }
6476
6477   // the time is meaningless for first call
6478   // due to async OpenGl rendering
6479   aView->Redraw();
6480
6481   // redraw view in loop to estimate average values
6482   OSD_Timer aTimer;
6483   aTimer.Start();
6484   Standard_Integer aFrameIter = 1;
6485   for (;; ++aFrameIter)
6486   {
6487     aView->Redraw();
6488     if ((aFramesNb > 0
6489       && aFrameIter >= aFramesNb)
6490      || (aDuration > 0.0
6491       && aTimer.ElapsedTime() >= aDuration))
6492     {
6493       break;
6494     }
6495   }
6496   aTimer.Stop();
6497   Standard_Real aCpu;
6498   const Standard_Real aTime = aTimer.ElapsedTime();
6499   aTimer.OSD_Chronometer::Show (aCpu);
6500
6501   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
6502   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
6503
6504   // return statistics
6505   theDI << "FPS: " << aFpsAver << "\n"
6506         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
6507
6508   // compute additional statistics in ray-tracing mode
6509   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
6510   if (aParams.Method == Graphic3d_RM_RAYTRACING)
6511   {
6512     Graphic3d_Vec2i aWinSize (0, 0);
6513     aView->Window()->Size (aWinSize.x(), aWinSize.y());
6514
6515     // 1 shadow ray and 1 secondary ray pew each bounce
6516     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
6517     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
6518   }
6519
6520   return 0;
6521 }
6522
6523 //! Auxiliary function for parsing glsl dump level argument.
6524 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
6525                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
6526 {
6527   TCollection_AsciiString aTypeStr (theArg);
6528   aTypeStr.LowerCase();
6529   if (aTypeStr == "off"
6530    || aTypeStr == "0")
6531   {
6532     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6533   }
6534   else if (aTypeStr == "short")
6535   {
6536     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
6537   }
6538   else if (aTypeStr == "full"
6539         || aTypeStr == "1")
6540   {
6541     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6542   }
6543   else
6544   {
6545     return Standard_False;
6546   }
6547   return Standard_True;
6548 }
6549
6550 //==============================================================================
6551 //function : VGlDebug
6552 //purpose  :
6553 //==============================================================================
6554
6555 static int VGlDebug (Draw_Interpretor& theDI,
6556                      Standard_Integer  theArgNb,
6557                      const char**      theArgVec)
6558 {
6559   Handle(OpenGl_GraphicDriver) aDriver;
6560   Handle(V3d_View) aView = ViewerTest::CurrentView();
6561   if (!aView.IsNull())
6562   {
6563     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
6564   }
6565   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
6566   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
6567
6568   if (theArgNb < 2)
6569   {
6570     TCollection_AsciiString aDebActive, aSyncActive;
6571     if (aCaps == NULL)
6572     {
6573       aCaps = aDefCaps;
6574     }
6575     else
6576     {
6577       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
6578                                                                   "GL_ARB_debug_output");
6579       aDebActive = isActive ? " (active)" : " (inactive)";
6580       if (isActive)
6581       {
6582         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
6583         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
6584       }
6585     }
6586
6587     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
6588       + "glslSourceCode: "
6589       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
6590          ? "Off"
6591          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
6592           ? "Short"
6593           : "Full")
6594       + "\n";
6595     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
6596           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
6597           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
6598           << aGlslCodeDebugStatus
6599           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
6600     return 0;
6601   }
6602
6603   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6604   {
6605     Standard_CString        anArg     = theArgVec[anArgIter];
6606     TCollection_AsciiString anArgCase (anArg);
6607     anArgCase.LowerCase();
6608     Standard_Boolean toEnableDebug = Standard_True;
6609     if (anArgCase == "-glsl"
6610      || anArgCase == "-glslwarn"
6611      || anArgCase == "-glslwarns"
6612      || anArgCase == "-glslwarnings")
6613     {
6614       Standard_Boolean toShowWarns = Standard_True;
6615       if (++anArgIter < theArgNb
6616       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
6617       {
6618         --anArgIter;
6619       }
6620       aDefCaps->glslWarnings = toShowWarns;
6621       if (aCaps != NULL)
6622       {
6623         aCaps->glslWarnings = toShowWarns;
6624       }
6625     }
6626     else if (anArgCase == "-extra"
6627           || anArgCase == "-extramsg"
6628           || anArgCase == "-extramessages")
6629     {
6630       Standard_Boolean toShow = Standard_True;
6631       if (++anArgIter < theArgNb
6632       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
6633       {
6634         --anArgIter;
6635       }
6636       aDefCaps->suppressExtraMsg = !toShow;
6637       if (aCaps != NULL)
6638       {
6639         aCaps->suppressExtraMsg = !toShow;
6640       }
6641     }
6642     else if (anArgCase == "-noextra"
6643           || anArgCase == "-noextramsg"
6644           || anArgCase == "-noextramessages")
6645     {
6646       Standard_Boolean toSuppress = Standard_True;
6647       if (++anArgIter < theArgNb
6648       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
6649       {
6650         --anArgIter;
6651       }
6652       aDefCaps->suppressExtraMsg = toSuppress;
6653       if (aCaps != NULL)
6654       {
6655         aCaps->suppressExtraMsg = toSuppress;
6656       }
6657     }
6658     else if (anArgCase == "-sync")
6659     {
6660       Standard_Boolean toSync = Standard_True;
6661       if (++anArgIter < theArgNb
6662       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
6663       {
6664         --anArgIter;
6665       }
6666       aDefCaps->contextSyncDebug = toSync;
6667       if (toSync)
6668       {
6669         aDefCaps->contextDebug = Standard_True;
6670       }
6671     }
6672     else if (anArgCase == "-glslsourcecode"
6673           || anArgCase == "-glslcode")
6674     {
6675       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6676       if (++anArgIter < theArgNb
6677       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
6678       {
6679         --anArgIter;
6680       }
6681       aDefCaps->glslDumpLevel = aGslsDumpLevel;
6682       if (aCaps != NULL)
6683       {
6684         aCaps->glslDumpLevel = aGslsDumpLevel;
6685       }
6686     }
6687     else if (anArgCase == "-debug")
6688     {
6689       if (++anArgIter < theArgNb
6690       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
6691       {
6692         --anArgIter;
6693       }
6694       aDefCaps->contextDebug = toEnableDebug;
6695     }
6696     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
6697           && (anArgIter + 1 == theArgNb))
6698     {
6699       // simple alias to turn on almost everything
6700       aDefCaps->contextDebug     = toEnableDebug;
6701       aDefCaps->contextSyncDebug = toEnableDebug;
6702       aDefCaps->glslWarnings     = toEnableDebug;
6703       if (!toEnableDebug)
6704       {
6705         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6706       }
6707       aDefCaps->suppressExtraMsg = !toEnableDebug;
6708       if (aCaps != NULL)
6709       {
6710         aCaps->contextDebug     = toEnableDebug;
6711         aCaps->contextSyncDebug = toEnableDebug;
6712         aCaps->glslWarnings     = toEnableDebug;
6713         if (!toEnableDebug)
6714         {
6715           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6716         }
6717         aCaps->suppressExtraMsg = !toEnableDebug;
6718       }
6719     }
6720     else
6721     {
6722       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
6723       return 1;
6724     }
6725   }
6726
6727   return 0;
6728 }
6729
6730 //==============================================================================
6731 //function : VVbo
6732 //purpose  :
6733 //==============================================================================
6734
6735 static int VVbo (Draw_Interpretor& theDI,
6736                  Standard_Integer  theArgNb,
6737                  const char**      theArgVec)
6738 {
6739   const Standard_Boolean toSet    = (theArgNb > 1);
6740   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
6741   if (toSet)
6742   {
6743     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
6744   }
6745
6746   // get the context
6747   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6748   if (aContextAIS.IsNull())
6749   {
6750     if (!toSet)
6751     {
6752       std::cerr << "No active view!\n";
6753     }
6754     return 1;
6755   }
6756   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
6757   if (!aDriver.IsNull())
6758   {
6759     if (!toSet)
6760     {
6761       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
6762     }
6763     else
6764     {
6765       aDriver->ChangeOptions().vboDisable = toUseVbo;
6766     }
6767   }
6768
6769   return 0;
6770 }
6771
6772 //==============================================================================
6773 //function : VCaps
6774 //purpose  :
6775 //==============================================================================
6776
6777 static int VCaps (Draw_Interpretor& theDI,
6778                   Standard_Integer  theArgNb,
6779                   const char**      theArgVec)
6780 {
6781   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
6782   Handle(OpenGl_GraphicDriver)   aDriver;
6783   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6784   if (!aContext.IsNull())
6785   {
6786     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
6787     aCaps   = &aDriver->ChangeOptions();
6788   }
6789
6790   if (theArgNb < 2)
6791   {
6792     theDI << "sRGB:    " << (aCaps->sRGBDisable       ? "0" : "1") << "\n";
6793     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
6794     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
6795     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
6796     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
6797     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
6798     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
6799     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
6800     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
6801     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
6802     theDI << "NoExt:"    << (aCaps->contextNoExtensions ? "1" : "0") << "\n";
6803     theDI << "MaxVersion:" << aCaps->contextMajorVersionUpper << "." << aCaps->contextMinorVersionUpper << "\n";
6804     return 0;
6805   }
6806
6807   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6808   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6809   {
6810     Standard_CString        anArg     = theArgVec[anArgIter];
6811     TCollection_AsciiString anArgCase (anArg);
6812     anArgCase.LowerCase();
6813     if (anUpdateTool.parseRedrawMode (anArg))
6814     {
6815       continue;
6816     }
6817     else if (anArgCase == "-vsync"
6818           || anArgCase == "-swapinterval")
6819     {
6820       Standard_Boolean toEnable = Standard_True;
6821       if (++anArgIter < theArgNb
6822       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6823       {
6824         --anArgIter;
6825       }
6826       aCaps->swapInterval = toEnable;
6827     }
6828     else if (anArgCase == "-ffp")
6829     {
6830       Standard_Boolean toEnable = Standard_True;
6831       if (++anArgIter < theArgNb
6832       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6833       {
6834         --anArgIter;
6835       }
6836       aCaps->ffpEnable = toEnable;
6837     }
6838     else if (anArgCase == "-polygonmode")
6839     {
6840       Standard_Boolean toEnable = Standard_True;
6841       if (++anArgIter < theArgNb
6842       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6843       {
6844         --anArgIter;
6845       }
6846       aCaps->usePolygonMode = toEnable;
6847     }
6848     else if (anArgCase == "-srgb")
6849     {
6850       Standard_Boolean toEnable = Standard_True;
6851       if (++anArgIter < theArgNb
6852       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6853       {
6854         --anArgIter;
6855       }
6856       aCaps->sRGBDisable = !toEnable;
6857     }
6858     else if (anArgCase == "-vbo")
6859     {
6860       Standard_Boolean toEnable = Standard_True;
6861       if (++anArgIter < theArgNb
6862       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6863       {
6864         --anArgIter;
6865       }
6866       aCaps->vboDisable = !toEnable;
6867     }
6868     else if (anArgCase == "-sprite"
6869           || anArgCase == "-sprites")
6870     {
6871       Standard_Boolean toEnable = Standard_True;
6872       if (++anArgIter < theArgNb
6873       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6874       {
6875         --anArgIter;
6876       }
6877       aCaps->pntSpritesDisable = !toEnable;
6878     }
6879     else if (anArgCase == "-softmode")
6880     {
6881       Standard_Boolean toEnable = Standard_True;
6882       if (++anArgIter < theArgNb
6883       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6884       {
6885         --anArgIter;
6886       }
6887       aCaps->contextNoAccel = toEnable;
6888     }
6889     else if (anArgCase == "-winbuffer"
6890           || anArgCase == "-windowbuffer"
6891           || anArgCase == "-usewinbuffer"
6892           || anArgCase == "-usewindowbuffer"
6893           || anArgCase == "-usesystembuffer")
6894     {
6895       Standard_Boolean toEnable = Standard_True;
6896       if (++anArgIter < theArgNb
6897       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6898       {
6899         --anArgIter;
6900       }
6901       aCaps->useSystemBuffer = toEnable;
6902     }
6903     else if (anArgCase == "-accel"
6904           || anArgCase == "-acceleration")
6905     {
6906       Standard_Boolean toEnable = Standard_True;
6907       if (++anArgIter < theArgNb
6908       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6909       {
6910         --anArgIter;
6911       }
6912       aCaps->contextNoAccel = !toEnable;
6913     }
6914     else if (anArgCase == "-compat"
6915           || anArgCase == "-compatprofile"
6916           || anArgCase == "-compatible"
6917           || anArgCase == "-compatibleprofile")
6918     {
6919       Standard_Boolean toEnable = Standard_True;
6920       if (++anArgIter < theArgNb
6921       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6922       {
6923         --anArgIter;
6924       }
6925       aCaps->contextCompatible = toEnable;
6926       if (!aCaps->contextCompatible)
6927       {
6928         aCaps->ffpEnable = Standard_False;
6929       }
6930     }
6931     else if (anArgCase == "-core"
6932           || anArgCase == "-coreprofile")
6933     {
6934       Standard_Boolean toEnable = Standard_True;
6935       if (++anArgIter < theArgNb
6936       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6937       {
6938         --anArgIter;
6939       }
6940       aCaps->contextCompatible = !toEnable;
6941       if (!aCaps->contextCompatible)
6942       {
6943         aCaps->ffpEnable = Standard_False;
6944       }
6945     }
6946     else if (anArgCase == "-stereo"
6947           || anArgCase == "-quadbuffer")
6948     {
6949       Standard_Boolean toEnable = Standard_True;
6950       if (++anArgIter < theArgNb
6951       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6952       {
6953         --anArgIter;
6954       }
6955       aCaps->contextStereo = toEnable;
6956     }
6957     else if (anArgCase == "-noext"
6958           || anArgCase == "-noextensions"
6959           || anArgCase == "-noextension")
6960     {
6961       Standard_Boolean toDisable = Standard_True;
6962       if (++anArgIter < theArgNb
6963       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
6964       {
6965         --anArgIter;
6966       }
6967       aCaps->contextNoExtensions = toDisable;
6968     }
6969     else if (anArgCase == "-maxversion"
6970           || anArgCase == "-upperversion"
6971           || anArgCase == "-limitversion")
6972     {
6973       Standard_Integer aVer[2] = { -2, -1 };
6974       for (Standard_Integer aValIter = 0; aValIter < 2; ++aValIter)
6975       {
6976         if (anArgIter + 1 < theArgNb)
6977         {
6978           const TCollection_AsciiString aStr (theArgVec[anArgIter + 1]);
6979           if (aStr.IsIntegerValue())
6980           {
6981             aVer[aValIter] = aStr.IntegerValue();
6982             ++anArgIter;
6983           }
6984         }
6985       }
6986       if (aVer[0] < -1
6987        || aVer[1] < -1)
6988       {
6989         std::cout << "Syntax error at '" << anArgCase << "'\n";
6990         return 1;
6991       }
6992       aCaps->contextMajorVersionUpper = aVer[0];
6993       aCaps->contextMinorVersionUpper = aVer[1];
6994     }
6995     else
6996     {
6997       std::cout << "Error: unknown argument '" << anArg << "'\n";
6998       return 1;
6999     }
7000   }
7001   if (aCaps != &ViewerTest_myDefaultCaps)
7002   {
7003     ViewerTest_myDefaultCaps = *aCaps;
7004   }
7005   return 0;
7006 }
7007
7008 //==============================================================================
7009 //function : VMemGpu
7010 //purpose  :
7011 //==============================================================================
7012
7013 static int VMemGpu (Draw_Interpretor& theDI,
7014                     Standard_Integer  theArgNb,
7015                     const char**      theArgVec)
7016 {
7017   // get the context
7018   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
7019   if (aContextAIS.IsNull())
7020   {
7021     std::cerr << "No active view. Please call vinit.\n";
7022     return 1;
7023   }
7024
7025   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
7026   if (aDriver.IsNull())
7027   {
7028     std::cerr << "Graphic driver not available.\n";
7029     return 1;
7030   }
7031
7032   Standard_Size aFreeBytes = 0;
7033   TCollection_AsciiString anInfo;
7034   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
7035   {
7036     std::cerr << "Information not available.\n";
7037     return 1;
7038   }
7039
7040   if (theArgNb > 1 && *theArgVec[1] == 'f')
7041   {
7042     theDI << Standard_Real (aFreeBytes);
7043   }
7044   else
7045   {
7046     theDI << anInfo;
7047   }
7048
7049   return 0;
7050 }
7051
7052 // ==============================================================================
7053 // function : VReadPixel
7054 // purpose  :
7055 // ==============================================================================
7056 static int VReadPixel (Draw_Interpretor& theDI,
7057                        Standard_Integer  theArgNb,
7058                        const char**      theArgVec)
7059 {
7060   // get the active view
7061   Handle(V3d_View) aView = ViewerTest::CurrentView();
7062   if (aView.IsNull())
7063   {
7064     std::cerr << "No active view. Please call vinit.\n";
7065     return 1;
7066   }
7067   else if (theArgNb < 3)
7068   {
7069     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
7070     return 1;
7071   }
7072
7073   Image_Format         aFormat     = Image_Format_RGBA;
7074   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
7075
7076   Standard_Integer aWidth, aHeight;
7077   aView->Window()->Size (aWidth, aHeight);
7078   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
7079   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
7080   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
7081   {
7082     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
7083     return 1;
7084   }
7085
7086   bool toShowName = false, toShowHls = false, toShowHex = false, toShow_sRGB = false;
7087   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
7088   {
7089     TCollection_AsciiString aParam (theArgVec[anIter]);
7090     aParam.LowerCase();
7091     if (aParam == "-rgb"
7092      || aParam == "rgb"
7093      || aParam == "-srgb"
7094      || aParam == "srgb")
7095     {
7096       aFormat     = Image_Format_RGB;
7097       aBufferType = Graphic3d_BT_RGB;
7098       toShow_sRGB = aParam == "-srgb" || aParam == "srgb";
7099     }
7100     else if (aParam == "-hls"
7101           || aParam == "hls")
7102     {
7103       aFormat     = Image_Format_RGB;
7104       aBufferType = Graphic3d_BT_RGB;
7105       toShowHls   = Standard_True;
7106     }
7107     else if (aParam == "-rgbf"
7108           || aParam == "rgbf")
7109     {
7110       aFormat     = Image_Format_RGBF;
7111       aBufferType = Graphic3d_BT_RGB;
7112     }
7113     else if (aParam == "-rgba"
7114           || aParam == "rgba"
7115           || aParam == "-srgba"
7116           || aParam == "srgba")
7117     {
7118       aFormat     = Image_Format_RGBA;
7119       aBufferType = Graphic3d_BT_RGBA;
7120       toShow_sRGB = aParam == "-srgba" || aParam == "srgba";
7121     }
7122     else if (aParam == "-rgbaf"
7123           || aParam == "rgbaf")
7124     {
7125       aFormat     = Image_Format_RGBAF;
7126       aBufferType = Graphic3d_BT_RGBA;
7127     }
7128     else if (aParam == "-depth"
7129           || aParam == "depth")
7130     {
7131       aFormat     = Image_Format_GrayF;
7132       aBufferType = Graphic3d_BT_Depth;
7133     }
7134     else if (aParam == "-name"
7135           || aParam == "name")
7136     {
7137       toShowName = Standard_True;
7138     }
7139     else if (aParam == "-hex"
7140           || aParam == "hex")
7141     {
7142       toShowHex = Standard_True;
7143     }
7144     else
7145     {
7146       std::cout << "Syntax error at '" << aParam << "'\n";
7147       return 1;
7148     }
7149   }
7150
7151   Image_PixMap anImage;
7152   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
7153   {
7154     std::cerr << "Image allocation failed\n";
7155     return 1;
7156   }
7157   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
7158   {
7159     std::cerr << "Image dump failed\n";
7160     return 1;
7161   }
7162
7163   // redirect possible warning messages that could have been added by ToPixMap
7164   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
7165   // contaminate result of the command
7166   Standard_CString aWarnLog = theDI.Result();
7167   if (aWarnLog != NULL && aWarnLog[0] != '\0')
7168   {
7169     std::cout << aWarnLog << std::endl;
7170   }
7171   theDI.Reset();
7172
7173   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY, true);
7174   if (toShowName)
7175   {
7176     if (aBufferType == Graphic3d_BT_RGBA)
7177     {
7178       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
7179     }
7180     else
7181     {
7182       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
7183     }
7184   }
7185   else if (toShowHex)
7186   {
7187     if (aBufferType == Graphic3d_BT_RGBA)
7188     {
7189       theDI << Quantity_ColorRGBA::ColorToHex (aColor);
7190     }
7191     else
7192     {
7193       theDI << Quantity_Color::ColorToHex (aColor.GetRGB());
7194     }
7195   }
7196   else
7197   {
7198     switch (aBufferType)
7199     {
7200       default:
7201       case Graphic3d_BT_RGB:
7202       {
7203         if (toShowHls)
7204         {
7205           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
7206         }
7207         else if (toShow_sRGB)
7208         {
7209           const Graphic3d_Vec4 aColor_sRGB = Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor);
7210           theDI << aColor_sRGB.r() << " " << aColor_sRGB.g() << " " << aColor_sRGB.b();
7211         }
7212         else
7213         {
7214           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
7215         }
7216         break;
7217       }
7218       case Graphic3d_BT_RGBA:
7219       {
7220         const Graphic3d_Vec4 aVec4 = toShow_sRGB ? Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor) : (Graphic3d_Vec4 )aColor;
7221         theDI << aVec4.r() << " " << aVec4.g() << " " << aVec4.b() << " " << aVec4.a();
7222         break;
7223       }
7224       case Graphic3d_BT_Depth:
7225       {
7226         theDI << aColor.GetRGB().Red();
7227         break;
7228       }
7229     }
7230   }
7231
7232   return 0;
7233 }
7234
7235 //! Auxiliary presentation for an image plane.
7236 class ViewerTest_ImagePrs : public AIS_InteractiveObject
7237 {
7238 public:
7239   //! Main constructor.
7240   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
7241                        const Standard_Real theWidth,
7242                        const Standard_Real theHeight,
7243                        const TCollection_AsciiString& theLabel)
7244   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
7245   {
7246     SetDisplayMode (0);
7247     SetHilightMode (1);
7248     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
7249     {
7250       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
7251       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
7252       Graphic3d_MaterialAspect aMat;
7253       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
7254       aMat.SetAmbientColor  (Quantity_NOC_BLACK);
7255       aMat.SetDiffuseColor  (Quantity_NOC_WHITE);
7256       aMat.SetSpecularColor (Quantity_NOC_BLACK);
7257       aMat.SetEmissiveColor (Quantity_NOC_BLACK);
7258       aFillAspect->SetFrontMaterial (aMat);
7259       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
7260       aFillAspect->SetTextureMapOn();
7261     }
7262     {
7263       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
7264       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
7265       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
7266       myDrawer->SetTextAspect (aTextAspect);
7267     }
7268     {
7269       const gp_Dir aNorm (0.0, 0.0, 1.0);
7270       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
7271       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
7272       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
7273       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
7274       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
7275       myTris->AddEdge (1);
7276       myTris->AddEdge (2);
7277       myTris->AddEdge (3);
7278       myTris->AddEdge (3);
7279       myTris->AddEdge (2);
7280       myTris->AddEdge (4);
7281
7282       myRect = new Graphic3d_ArrayOfPolylines (4);
7283       myRect->AddVertex (myTris->Vertice (1));
7284       myRect->AddVertex (myTris->Vertice (3));
7285       myRect->AddVertex (myTris->Vertice (4));
7286       myRect->AddVertex (myTris->Vertice (2));
7287     }
7288   }
7289
7290   //! Returns TRUE for accepted display modes.
7291   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7292
7293   //! Compute presentation.
7294   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7295   {
7296     switch (theMode)
7297     {
7298       case 0:
7299       {
7300         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7301         aGroup->AddPrimitiveArray (myTris);
7302         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7303         aGroup->AddPrimitiveArray (myRect);
7304         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7305         return;
7306       }
7307       case 1:
7308       {
7309         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7310         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7311         aGroup->AddPrimitiveArray (myRect);
7312         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7313         return;
7314       }
7315     }
7316   }
7317
7318   //! Compute selection.
7319   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7320   {
7321     if (theMode == 0)
7322     {
7323       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7324       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7325       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7326       theSel->Add (aSensitive);
7327     }
7328   }
7329
7330 private:
7331   Handle(Graphic3d_ArrayOfTriangles) myTris;
7332   Handle(Graphic3d_ArrayOfPolylines) myRect;
7333   TCollection_AsciiString myLabel;
7334   Standard_Real myWidth;
7335   Standard_Real myHeight;
7336 };
7337
7338 //==============================================================================
7339 //function : VDiffImage
7340 //purpose  : The draw-command compares two images.
7341 //==============================================================================
7342
7343 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7344 {
7345   if (theArgNb < 3)
7346   {
7347     std::cout << "Syntax error: not enough arguments.\n";
7348     return 1;
7349   }
7350
7351   Standard_Integer anArgIter = 1;
7352   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7353   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7354   TCollection_AsciiString aDiffImagePath;
7355   Standard_Real    aTolColor        = -1.0;
7356   Standard_Integer toBlackWhite     = -1;
7357   Standard_Integer isBorderFilterOn = -1;
7358   Standard_Boolean isOldSyntax = Standard_False;
7359   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7360   for (; anArgIter < theArgNb; ++anArgIter)
7361   {
7362     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7363     anArg.LowerCase();
7364     if (anArgIter + 1 < theArgNb
7365      && (anArg == "-toleranceofcolor"
7366       || anArg == "-tolerancecolor"
7367       || anArg == "-tolerance"
7368       || anArg == "-toler"))
7369     {
7370       aTolColor = Atof (theArgVec[++anArgIter]);
7371       if (aTolColor < 0.0 || aTolColor > 1.0)
7372       {
7373         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7374         return 1;
7375       }
7376     }
7377     else if (anArg == "-blackwhite")
7378     {
7379       Standard_Boolean toEnable = Standard_True;
7380       if (anArgIter + 1 < theArgNb
7381        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7382       {
7383         ++anArgIter;
7384       }
7385       toBlackWhite = toEnable ? 1 : 0;
7386     }
7387     else if (anArg == "-borderfilter")
7388     {
7389       Standard_Boolean toEnable = Standard_True;
7390       if (anArgIter + 1 < theArgNb
7391        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7392       {
7393         ++anArgIter;
7394       }
7395       isBorderFilterOn = toEnable ? 1 : 0;
7396     }
7397     else if (anArg == "-exitonclose")
7398     {
7399       ViewerTest_EventManager::ToExitOnCloseView() = true;
7400       if (anArgIter + 1 < theArgNb
7401        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToExitOnCloseView()))
7402       {
7403         ++anArgIter;
7404       }
7405     }
7406     else if (anArg == "-closeonescape"
7407           || anArg == "-closeonesc")
7408     {
7409       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
7410       if (anArgIter + 1 < theArgNb
7411        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
7412       {
7413         ++anArgIter;
7414       }
7415     }
7416     else if (anArgIter + 3 < theArgNb
7417           && anArg == "-display")
7418     {
7419       aViewName   = theArgVec[++anArgIter];
7420       aPrsNameRef = theArgVec[++anArgIter];
7421       aPrsNameNew = theArgVec[++anArgIter];
7422       if (anArgIter + 1 < theArgNb
7423       && *theArgVec[anArgIter + 1] != '-')
7424       {
7425         aPrsNameDiff = theArgVec[++anArgIter];
7426       }
7427     }
7428     else if (aTolColor < 0.0
7429           && anArg.IsRealValue())
7430     {
7431       isOldSyntax = Standard_True;
7432       aTolColor = anArg.RealValue();
7433       if (aTolColor < 0.0 || aTolColor > 1.0)
7434       {
7435         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7436         return 1;
7437       }
7438     }
7439     else if (isOldSyntax
7440           && toBlackWhite == -1
7441           && (anArg == "0" || anArg == "1"))
7442     {
7443       toBlackWhite = anArg == "1" ? 1 : 0;
7444     }
7445     else if (isOldSyntax
7446           && isBorderFilterOn == -1
7447           && (anArg == "0" || anArg == "1"))
7448     {
7449       isBorderFilterOn = anArg == "1" ? 1 : 0;
7450     }
7451     else if (aDiffImagePath.IsEmpty())
7452     {
7453       aDiffImagePath = theArgVec[anArgIter];
7454     }
7455     else
7456     {
7457       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7458       return 1;
7459     }
7460   }
7461
7462   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7463   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7464   if (!anImgRef->Load (anImgPathRef))
7465   {
7466     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7467     return 1;
7468   }
7469   if (!anImgNew->Load (anImgPathNew))
7470   {
7471     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7472     return 1;
7473   }
7474
7475   // compare the images
7476   Image_Diff aComparer;
7477   Standard_Integer aDiffColorsNb = -1;
7478   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7479   {
7480     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7481     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7482     aDiffColorsNb = aComparer.Compare();
7483     theDI << aDiffColorsNb << "\n";
7484   }
7485
7486   // save image of difference
7487   Handle(Image_AlienPixMap) aDiff;
7488   if (aDiffColorsNb > 0
7489   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7490   {
7491     aDiff = new Image_AlienPixMap();
7492     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7493     {
7494       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7495       return 1;
7496     }
7497     aComparer.SaveDiffImage (*aDiff);
7498     if (!aDiffImagePath.IsEmpty()
7499      && !aDiff->Save (aDiffImagePath))
7500     {
7501       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7502       return 1;
7503     }
7504   }
7505
7506   if (aViewName.IsEmpty())
7507   {
7508     return 0;
7509   }
7510
7511   ViewerTest_Names aViewNames (aViewName);
7512   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7513   {
7514     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7515     theDI.Eval (aCommand.ToCString());
7516   }
7517
7518   Standard_Integer aPxLeft = 0;
7519   Standard_Integer aPxTop  = 0;
7520   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7521   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7522                               ? int(anImgRef->SizeY() * 2)
7523                               : int(anImgRef->SizeY());
7524   TCollection_AsciiString aDisplayName;
7525   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7526                                                             aViewName, aDisplayName);
7527
7528   Standard_Real aRatio = anImgRef->Ratio();
7529   Standard_Real aSizeX = 1.0;
7530   Standard_Real aSizeY = aSizeX / aRatio;
7531   {
7532     OSD_Path aPath (anImgPathRef);
7533     TCollection_AsciiString aLabelRef;
7534     if (!aPath.Name().IsEmpty())
7535     {
7536       aLabelRef = aPath.Name() + aPath.Extension();
7537     }
7538     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7539
7540     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7541     gp_Trsf aTrsfRef;
7542     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7543     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7544     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7545   }
7546   {
7547     OSD_Path aPath (anImgPathNew);
7548     TCollection_AsciiString aLabelNew;
7549     if (!aPath.Name().IsEmpty())
7550     {
7551       aLabelNew = aPath.Name() + aPath.Extension();
7552     }
7553     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7554
7555     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7556     gp_Trsf aTrsfRef;
7557     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7558     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7559     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7560   }
7561   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7562   if (!aDiff.IsNull())
7563   {
7564     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7565     gp_Trsf aTrsfDiff;
7566     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7567     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7568   }
7569   if (!aPrsNameDiff.IsEmpty())
7570   {
7571     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7572   }
7573   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7574   ViewerTest::CurrentView()->FitAll();
7575   return 0;
7576 }
7577
7578 //=======================================================================
7579 //function : VSelect
7580 //purpose  : Emulates different types of selection by mouse:
7581 //           1) single click selection
7582 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7583 //           3) selection with polygon having corners at
7584 //           pixel positions (x1,y1),...,(xn,yn)
7585 //           4) any of these selections with shift button pressed
7586 //=======================================================================
7587 static Standard_Integer VSelect (Draw_Interpretor& ,
7588                                  Standard_Integer theNbArgs,
7589                                  const char** theArgVec)
7590 {
7591   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7592   if (aCtx.IsNull())
7593   {
7594     std::cout << "Error: no active View\n";
7595     return 1;
7596   }
7597
7598   NCollection_Sequence<Graphic3d_Vec2i> aPnts;
7599   bool isShiftSelection = false, toAllowOverlap = false;
7600   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7601   {
7602     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7603     anArg.LowerCase();
7604     if (anArg == "-allowoverlap")
7605     {
7606       toAllowOverlap = true;
7607       if (anArgIter + 1 < theNbArgs
7608        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toAllowOverlap))
7609       {
7610         ++anArgIter;
7611       }
7612     }
7613     else if (anArgIter + 1 < theNbArgs
7614           && anArg.IsIntegerValue()
7615           && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
7616     {
7617       const TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
7618       aPnts.Append (Graphic3d_Vec2i (anArg.IntegerValue(), anArgNext.IntegerValue()));
7619     }
7620     else if (anArgIter + 1 == theNbArgs
7621           && anArg.IsIntegerValue())
7622     {
7623       isShiftSelection = anArg.IntegerValue() == 1;
7624     }
7625     else
7626     {
7627       std::cout << "Syntax error at '" << anArg << "'\n";
7628       return 1;
7629     }
7630   }
7631   if (toAllowOverlap
7632    && aPnts.Length() != 2)
7633   {
7634     std::cout << "Syntax error: -allowoverlap key is applied only for rectangle selection\n";
7635     return 1;
7636   }
7637   if (toAllowOverlap)
7638   {
7639     aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
7640   }
7641
7642   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7643   if (aPnts.IsEmpty())
7644   {
7645     if (isShiftSelection)
7646     {
7647       aCtx->ShiftSelect (false);
7648     }
7649     else
7650     {
7651       aCtx->Select (false);
7652     }
7653     aCtx->CurrentViewer()->Invalidate();
7654   }
7655   else if (aPnts.Length() == 2)
7656   {
7657     if (toAllowOverlap
7658      && aPnts.First().y() < aPnts.Last().y())
7659     {
7660       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7661     }
7662     else if (!toAllowOverlap
7663            && aPnts.First().y() > aPnts.Last().y())
7664     {
7665       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7666     }
7667     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7668   }
7669   else
7670   {
7671     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7672   }
7673   aCurrentEventManager->FlushViewEvents (aCtx, ViewerTest::CurrentView(), true);
7674   return 0;
7675 }
7676
7677 //=======================================================================
7678 //function : VMoveTo
7679 //purpose  : Emulates cursor movement to defined pixel position
7680 //=======================================================================
7681 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7682                                 Standard_Integer theNbArgs,
7683                                 const char**     theArgVec)
7684 {
7685   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7686   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7687   if (aContext.IsNull())
7688   {
7689     std::cout << "Error: no active View\n";
7690     return 1;
7691   }
7692
7693   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7694   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7695   {
7696     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7697     anArgStr.LowerCase();
7698     if (anArgStr == "-reset"
7699      || anArgStr == "-clear")
7700     {
7701       if (anArgIter + 1 < theNbArgs)
7702       {
7703         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7704         return 1;
7705       }
7706
7707       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7708                                        && aContext->CurrentViewer()->GridEcho();
7709       if (toEchoGrid)
7710       {
7711         aContext->CurrentViewer()->HideGridEcho (aView);
7712       }
7713       if (aContext->ClearDetected() || toEchoGrid)
7714       {
7715         aContext->CurrentViewer()->RedrawImmediate();
7716       }
7717       return 0;
7718     }
7719     else if (aMousePos.x() == IntegerLast()
7720           && anArgStr.IsIntegerValue())
7721     {
7722       aMousePos.x() = anArgStr.IntegerValue();
7723     }
7724     else if (aMousePos.y() == IntegerLast()
7725           && anArgStr.IsIntegerValue())
7726     {
7727       aMousePos.y() = anArgStr.IntegerValue();
7728     }
7729     else
7730     {
7731       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7732       return 1;
7733     }
7734   }
7735
7736   if (aMousePos.x() == IntegerLast()
7737    || aMousePos.y() == IntegerLast())
7738   {
7739     std::cout << "Syntax error: wrong number of arguments\n";
7740     return 1;
7741   }
7742
7743   ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
7744   ViewerTest::CurrentEventManager()->UpdateMousePosition (aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
7745   ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
7746
7747   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7748   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7749   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7750   {
7751     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7752     {
7753       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7754       break;
7755     }
7756   }
7757   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7758   return 0;
7759 }
7760
7761 namespace
7762 {
7763   //! Global map storing all animations registered in ViewerTest.
7764   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7765
7766   //! The animation calling the Draw Harness command.
7767   class ViewerTest_AnimationProc : public AIS_Animation
7768   {
7769   public:
7770
7771     //! Main constructor.
7772     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7773                               Draw_Interpretor* theDI,
7774                               const TCollection_AsciiString& theCommand)
7775     : AIS_Animation (theAnimationName),
7776       myDrawInter(theDI),
7777       myCommand  (theCommand)
7778     {
7779       //
7780     }
7781
7782   protected:
7783
7784     //! Evaluate the command.
7785     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7786     {
7787       TCollection_AsciiString aCmd = myCommand;
7788       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7789       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7790       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7791       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7792       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7793       myDrawInter->Eval (aCmd.ToCString());
7794     }
7795
7796     //! Find the keyword in the command and replace it with value.
7797     //! @return the position of the keyword to pass value
7798     void replace (TCollection_AsciiString&       theCmd,
7799                   const TCollection_AsciiString& theKey,
7800                   const TCollection_AsciiString& theVal)
7801     {
7802       TCollection_AsciiString aCmd (theCmd);
7803       aCmd.LowerCase();
7804       const Standard_Integer aPos = aCmd.Search (theKey);
7805       if (aPos == -1)
7806       {
7807         return;
7808       }
7809
7810       TCollection_AsciiString aPart1, aPart2;
7811       Standard_Integer aPart1To = aPos - 1;
7812       if (aPart1To >= 1
7813        && aPart1To <= theCmd.Length())
7814       {
7815         aPart1 = theCmd.SubString (1, aPart1To);
7816       }
7817
7818       Standard_Integer aPart2From = aPos + theKey.Length();
7819       if (aPart2From >= 1
7820        && aPart2From <= theCmd.Length())
7821       {
7822         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7823       }
7824
7825       theCmd = aPart1 + theVal + aPart2;
7826     }
7827
7828   protected:
7829
7830     Draw_Interpretor*       myDrawInter;
7831     TCollection_AsciiString myCommand;
7832
7833   };
7834
7835   //! Replace the animation with the new one.
7836   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7837                                 Handle(AIS_Animation)&       theAnimation,
7838                                 const Handle(AIS_Animation)& theAnimationNew)
7839   {
7840     theAnimationNew->CopyFrom (theAnimation);
7841     if (!theParentAnimation.IsNull())
7842     {
7843       theParentAnimation->Replace (theAnimation, theAnimationNew);
7844     }
7845     else
7846     {
7847       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
7848       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7849     }
7850     theAnimation = theAnimationNew;
7851   }
7852
7853   //! Parse the point.
7854   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7855   {
7856     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7857     if (!anXYZ[0].IsRealValue()
7858      || !anXYZ[1].IsRealValue()
7859      || !anXYZ[2].IsRealValue())
7860     {
7861       return Standard_False;
7862     }
7863
7864     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7865     return Standard_True;
7866   }
7867
7868   //! Parse the quaternion.
7869   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7870   {
7871     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7872     if (!anXYZW[0].IsRealValue()
7873      || !anXYZW[1].IsRealValue()
7874      || !anXYZW[2].IsRealValue()
7875      || !anXYZW[3].IsRealValue())
7876     {
7877       return Standard_False;
7878     }
7879
7880     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7881     return Standard_True;
7882   }
7883
7884   //! Auxiliary class for flipping image upside-down.
7885   class ImageFlipper
7886   {
7887   public:
7888
7889     //! Empty constructor.
7890     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7891
7892     //! Perform flipping.
7893     Standard_Boolean FlipY (Image_PixMap& theImage)
7894     {
7895       if (theImage.IsEmpty()
7896        || theImage.SizeX() == 0
7897        || theImage.SizeY() == 0)
7898       {
7899         return Standard_False;
7900       }
7901
7902       const Standard_Size aRowSize = theImage.SizeRowBytes();
7903       if (myTmp.Size() < aRowSize
7904       && !myTmp.Allocate (aRowSize))
7905       {
7906         return Standard_False;
7907       }
7908
7909       // for odd height middle row should be left as is
7910       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7911       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7912       {
7913         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7914         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7915         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7916         memcpy (aTop,               aBot,         aRowSize);
7917         memcpy (aBot,               myTmp.Data(), aRowSize);
7918       }
7919       return Standard_True;
7920     }
7921
7922   private:
7923     NCollection_Buffer myTmp;
7924   };
7925
7926 }
7927
7928 //=================================================================================================
7929 //function : VViewParams
7930 //purpose  : Gets or sets AIS View characteristics
7931 //=================================================================================================
7932 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7933 {
7934   Handle(V3d_View) aView = ViewerTest::CurrentView();
7935   if (aView.IsNull())
7936   {
7937     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7938     return 1;
7939   }
7940
7941   Standard_Boolean toSetProj     = Standard_False;
7942   Standard_Boolean toSetUp       = Standard_False;
7943   Standard_Boolean toSetAt       = Standard_False;
7944   Standard_Boolean toSetEye      = Standard_False;
7945   Standard_Boolean toSetScale    = Standard_False;
7946   Standard_Boolean toSetSize     = Standard_False;
7947   Standard_Boolean toSetCenter2d = Standard_False;
7948   Standard_Real    aViewScale = aView->Scale();
7949   Standard_Real    aViewSize  = 1.0;
7950   Graphic3d_Vec2i  aCenter2d;
7951   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7952   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7953   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7954   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7955   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7956   if (theArgsNb == 1)
7957   {
7958     // print all of the available view parameters
7959     char aText[4096];
7960     Sprintf (aText,
7961              "Scale: %g\n"
7962              "Proj:  %12g %12g %12g\n"
7963              "Up:    %12g %12g %12g\n"
7964              "At:    %12g %12g %12g\n"
7965              "Eye:   %12g %12g %12g\n",
7966               aViewScale,
7967               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7968               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7969               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7970               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7971     theDi << aText;
7972     return 0;
7973   }
7974
7975   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7976   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7977   {
7978     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7979     anArg.LowerCase();
7980     if (anUpdateTool.parseRedrawMode (anArg))
7981     {
7982       continue;
7983     }
7984     else if (anArg == "-cmd"
7985           || anArg == "-command"
7986           || anArg == "-args")
7987     {
7988       char aText[4096];
7989       Sprintf (aText,
7990                "-scale %g "
7991                "-proj %g %g %g "
7992                "-up %g %g %g "
7993                "-at %g %g %g\n",
7994                 aViewScale,
7995                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7996                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7997                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7998       theDi << aText;
7999     }
8000     else if (anArg == "-scale"
8001           || anArg == "-size")
8002     {
8003       if (anArgIter + 1 < theArgsNb
8004        && *theArgVec[anArgIter + 1] != '-')
8005       {
8006         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
8007         if (aValueArg.IsRealValue())
8008         {
8009           ++anArgIter;
8010           if (anArg == "-scale")
8011           {
8012             toSetScale = Standard_True;
8013             aViewScale = aValueArg.RealValue();
8014           }
8015           else if (anArg == "-size")
8016           {
8017             toSetSize = Standard_True;
8018             aViewSize = aValueArg.RealValue();
8019           }
8020           continue;
8021         }
8022       }
8023       if (anArg == "-scale")
8024       {
8025         theDi << "Scale: " << aView->Scale() << "\n";
8026       }
8027       else if (anArg == "-size")
8028       {
8029         Graphic3d_Vec2d aSizeXY;
8030         aView->Size (aSizeXY.x(), aSizeXY.y());
8031         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
8032       }
8033     }
8034     else if (anArg == "-eye"
8035           || anArg == "-at"
8036           || anArg == "-up"
8037           || anArg == "-proj")
8038     {
8039       if (anArgIter + 3 < theArgsNb)
8040       {
8041         gp_XYZ anXYZ;
8042         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
8043         {
8044           anArgIter += 3;
8045           if (anArg == "-eye")
8046           {
8047             toSetEye = Standard_True;
8048             aViewEye = anXYZ;
8049           }
8050           else if (anArg == "-at")
8051           {
8052             toSetAt = Standard_True;
8053             aViewAt = anXYZ;
8054           }
8055           else if (anArg == "-up")
8056           {
8057             toSetUp = Standard_True;
8058             aViewUp = anXYZ;
8059           }
8060           else if (anArg == "-proj")
8061           {
8062             toSetProj = Standard_True;
8063             aViewProj = anXYZ;
8064           }
8065           continue;
8066         }
8067       }
8068
8069       if (anArg == "-eye")
8070       {
8071         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
8072       }
8073       else if (anArg == "-at")
8074       {
8075         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
8076       }
8077       else if (anArg == "-up")
8078       {
8079         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
8080       }
8081       else if (anArg == "-proj")
8082       {
8083         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
8084       }
8085     }
8086     else if (anArg == "-center")
8087     {
8088       if (anArgIter + 2 < theArgsNb)
8089       {
8090         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
8091         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
8092         if (anX.IsIntegerValue()
8093          && anY.IsIntegerValue())
8094         {
8095           toSetCenter2d = Standard_True;
8096           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
8097         }
8098       }
8099     }
8100     else
8101     {
8102       std::cout << "Syntax error at '" << anArg << "'\n";
8103       return 1;
8104     }
8105   }
8106
8107   // change view parameters in proper order
8108   if (toSetScale)
8109   {
8110     aView->SetScale (aViewScale);
8111   }
8112   if (toSetSize)
8113   {
8114     aView->SetSize (aViewSize);
8115   }
8116   if (toSetEye)
8117   {
8118     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
8119   }
8120   if (toSetAt)
8121   {
8122     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
8123   }
8124   if (toSetProj)
8125   {
8126     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
8127   }
8128   if (toSetUp)
8129   {
8130     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
8131   }
8132   if (toSetCenter2d)
8133   {
8134     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
8135   }
8136
8137   return 0;
8138 }
8139
8140 //==============================================================================
8141 //function : V2DMode
8142 //purpose  :
8143 //==============================================================================
8144 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
8145 {
8146   bool is2dMode = true;
8147   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
8148   if (aV3dView.IsNull())
8149   {
8150     std::cout << "Error: no active view.\n";
8151     return 1;
8152   }
8153   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8154   {
8155     const TCollection_AsciiString anArg = theArgVec[anArgIt];
8156     TCollection_AsciiString anArgCase = anArg;
8157     anArgCase.LowerCase();
8158     if (anArgIt + 1 < theArgsNb
8159      && anArgCase == "-name")
8160     {
8161       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
8162       TCollection_AsciiString aViewName = aViewNames.GetViewName();
8163       if (!ViewerTest_myViews.IsBound1 (aViewName))
8164       {
8165         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
8166         return 1;
8167       }
8168       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
8169     }
8170     else if (anArgCase == "-mode")
8171     {
8172       if (anArgIt + 1 < theArgsNb
8173        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
8174       {
8175         ++anArgIt;
8176       }
8177     }
8178     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
8179     {
8180       //
8181     }
8182     else
8183     {
8184       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
8185       return 1;
8186     }
8187   }
8188
8189   aV3dView->SetView2DMode (is2dMode);
8190   return 0;
8191 }
8192
8193 //==============================================================================
8194 //function : VAnimation
8195 //purpose  :
8196 //==============================================================================
8197 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
8198                                     Standard_Integer  theArgNb,
8199                                     const char**      theArgVec)
8200 {
8201   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
8202   if (theArgNb < 2)
8203   {
8204     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
8205          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
8206     {
8207       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
8208     }
8209     return 0;
8210   }
8211   if (aCtx.IsNull())
8212   {
8213     std::cout << "Error: no active view\n";
8214     return 1;
8215   }
8216
8217   Standard_Integer anArgIter = 1;
8218   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
8219   if (aNameArg.IsEmpty())
8220   {
8221     std::cout << "Syntax error: animation name is not defined.\n";
8222     return 1;
8223   }
8224
8225   TCollection_AsciiString aNameArgLower = aNameArg;
8226   aNameArgLower.LowerCase();
8227   if (aNameArgLower == "-reset"
8228    || aNameArgLower == "-clear")
8229   {
8230     ViewerTest_AnimationTimelineMap.Clear();
8231     return 0;
8232   }
8233   else if (aNameArg.Value (1) == '-')
8234   {
8235     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
8236     return 1;
8237   }
8238
8239   const char* aNameSplitter = "/";
8240   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
8241   if (aSplitPos == -1)
8242   {
8243     aNameSplitter = ".";
8244     aSplitPos = aNameArg.Search (aNameSplitter);
8245   }
8246
8247   // find existing or create a new animation by specified name within syntax "parent.child".
8248   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
8249   for (; !aNameArg.IsEmpty();)
8250   {
8251     TCollection_AsciiString aNameParent;
8252     if (aSplitPos != -1)
8253     {
8254       if (aSplitPos == aNameArg.Length())
8255       {
8256         std::cout << "Syntax error: animation name is not defined.\n";
8257         return 1;
8258       }
8259
8260       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
8261       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
8262
8263       aSplitPos = aNameArg.Search (aNameSplitter);
8264     }
8265     else
8266     {
8267       aNameParent = aNameArg;
8268       aNameArg.Clear();
8269     }
8270
8271     if (anAnimation.IsNull())
8272     {
8273       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
8274       {
8275         anAnimation = new AIS_Animation (aNameParent);
8276         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8277       }
8278       aRootAnimation = anAnimation;
8279     }
8280     else
8281     {
8282       aParentAnimation = anAnimation;
8283       anAnimation = aParentAnimation->Find (aNameParent);
8284       if (anAnimation.IsNull())
8285       {
8286         anAnimation = new AIS_Animation (aNameParent);
8287         aParentAnimation->Add (anAnimation);
8288       }
8289     }
8290   }
8291
8292   if (anArgIter >= theArgNb)
8293   {
8294     // just print the list of children
8295     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8296     {
8297       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8298     }
8299     return 0;
8300   }
8301
8302   // animation parameters
8303   Standard_Boolean toPlay = Standard_False;
8304   Standard_Real aPlaySpeed     = 1.0;
8305   Standard_Real aPlayStartTime = anAnimation->StartPts();
8306   Standard_Real aPlayDuration  = anAnimation->Duration();
8307   Standard_Boolean isFreeCamera = Standard_False;
8308   Standard_Boolean isLockLoop   = Standard_False;
8309
8310   // video recording parameters
8311   TCollection_AsciiString aRecFile;
8312   Image_VideoParams aRecParams;
8313
8314   Handle(V3d_View) aView = ViewerTest::CurrentView();
8315   for (; anArgIter < theArgNb; ++anArgIter)
8316   {
8317     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8318     anArg.LowerCase();
8319     // general options
8320     if (anArg == "-reset"
8321      || anArg == "-clear")
8322     {
8323       anAnimation->Clear();
8324     }
8325     else if (anArg == "-remove"
8326           || anArg == "-del"
8327           || anArg == "-delete")
8328     {
8329       if (!aParentAnimation.IsNull())
8330       {
8331         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8332       }
8333       else
8334       {
8335         aParentAnimation->Remove (anAnimation);
8336       }
8337     }
8338     // playback options
8339     else if (anArg == "-play")
8340     {
8341       toPlay = Standard_True;
8342       if (++anArgIter < theArgNb)
8343       {
8344         if (*theArgVec[anArgIter] == '-')
8345         {
8346           --anArgIter;
8347           continue;
8348         }
8349         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8350
8351         if (++anArgIter < theArgNb)
8352         {
8353           if (*theArgVec[anArgIter] == '-')
8354           {
8355             --anArgIter;
8356             continue;
8357           }
8358           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8359         }
8360       }
8361     }
8362     else if (anArg == "-resume")
8363     {
8364       toPlay = Standard_True;
8365       aPlayStartTime = anAnimation->ElapsedTime();
8366       if (++anArgIter < theArgNb)
8367       {
8368         if (*theArgVec[anArgIter] == '-')
8369         {
8370           --anArgIter;
8371           continue;
8372         }
8373
8374         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8375       }
8376     }
8377     else if (anArg == "-playspeed"
8378           || anArg == "-speed")
8379     {
8380       if (++anArgIter >= theArgNb)
8381       {
8382         std::cout << "Syntax error at " << anArg << ".\n";
8383         return 1;
8384       }
8385       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8386     }
8387     else if (anArg == "-lock"
8388           || anArg == "-lockloop"
8389           || anArg == "-playlockloop")
8390     {
8391       isLockLoop = Standard_True;
8392     }
8393     else if (anArg == "-freecamera"
8394           || anArg == "-playfreecamera"
8395           || anArg == "-freelook")
8396     {
8397       isFreeCamera = Standard_True;
8398     }
8399     // video recodring options
8400     else if (anArg == "-rec"
8401           || anArg == "-record")
8402     {
8403       if (++anArgIter >= theArgNb)
8404       {
8405         std::cout << "Syntax error at " << anArg << ".\n";
8406         return 1;
8407       }
8408
8409       aRecFile = theArgVec[anArgIter];
8410       if (aRecParams.FpsNum <= 0)
8411       {
8412         aRecParams.FpsNum = 24;
8413       }
8414
8415       if (anArgIter + 2 < theArgNb
8416       && *theArgVec[anArgIter + 1] != '-'
8417       && *theArgVec[anArgIter + 2] != '-')
8418       {
8419         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8420         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8421         if (aWidthArg .IsIntegerValue()
8422          && aHeightArg.IsIntegerValue())
8423         {
8424           aRecParams.Width  = aWidthArg .IntegerValue();
8425           aRecParams.Height = aHeightArg.IntegerValue();
8426           anArgIter += 2;
8427         }
8428       }
8429     }
8430     else if (anArg == "-fps")
8431     {
8432       if (++anArgIter >= theArgNb)
8433       {
8434         std::cout << "Syntax error at " << anArg << ".\n";
8435         return 1;
8436       }
8437
8438       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8439       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8440       if (aSplitIndex == 0)
8441       {
8442         aRecParams.FpsNum = aFpsArg.IntegerValue();
8443       }
8444       else
8445       {
8446         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8447         aFpsArg.Split (aFpsArg.Length() - 1);
8448         const TCollection_AsciiString aNumStr = aFpsArg;
8449         aRecParams.FpsNum = aNumStr.IntegerValue();
8450         aRecParams.FpsDen = aDenStr.IntegerValue();
8451         if (aRecParams.FpsDen < 1)
8452         {
8453           std::cout << "Syntax error at " << anArg << ".\n";
8454           return 1;
8455         }
8456       }
8457     }
8458     else if (anArg == "-format")
8459     {
8460       if (++anArgIter >= theArgNb)
8461       {
8462         std::cout << "Syntax error at " << anArg << ".\n";
8463         return 1;
8464       }
8465       aRecParams.Format = theArgVec[anArgIter];
8466     }
8467     else if (anArg == "-pix_fmt"
8468           || anArg == "-pixfmt"
8469           || anArg == "-pixelformat")
8470     {
8471       if (++anArgIter >= theArgNb)
8472       {
8473         std::cout << "Syntax error at " << anArg << ".\n";
8474         return 1;
8475       }
8476       aRecParams.PixelFormat = theArgVec[anArgIter];
8477     }
8478     else if (anArg == "-codec"
8479           || anArg == "-vcodec"
8480           || anArg == "-videocodec")
8481     {
8482       if (++anArgIter >= theArgNb)
8483       {
8484         std::cout << "Syntax error at " << anArg << ".\n";
8485         return 1;
8486       }
8487       aRecParams.VideoCodec = theArgVec[anArgIter];
8488     }
8489     else if (anArg == "-crf"
8490           || anArg == "-preset"
8491           || anArg == "-qp")
8492     {
8493       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8494       if (++anArgIter >= theArgNb)
8495       {
8496         std::cout << "Syntax error at " << anArg << ".\n";
8497         return 1;
8498       }
8499
8500       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8501     }
8502     // animation definition options
8503     else if (anArg == "-start"
8504           || anArg == "-starttime"
8505           || anArg == "-startpts")
8506     {
8507       if (++anArgIter >= theArgNb)
8508       {
8509         std::cout << "Syntax error at " << anArg << ".\n";
8510         return 1;
8511       }
8512
8513       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8514       aRootAnimation->UpdateTotalDuration();
8515     }
8516     else if (anArg == "-end"
8517           || anArg == "-endtime"
8518           || anArg == "-endpts")
8519     {
8520       if (++anArgIter >= theArgNb)
8521       {
8522         std::cout << "Syntax error at " << anArg << ".\n";
8523         return 1;
8524       }
8525
8526       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8527       aRootAnimation->UpdateTotalDuration();
8528     }
8529     else if (anArg == "-dur"
8530           || anArg == "-duration")
8531     {
8532       if (++anArgIter >= theArgNb)
8533       {
8534         std::cout << "Syntax error at " << anArg << ".\n";
8535         return 1;
8536       }
8537
8538       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8539       aRootAnimation->UpdateTotalDuration();
8540     }
8541     else if (anArg == "-command"
8542           || anArg == "-cmd"
8543           || anArg == "-invoke"
8544           || anArg == "-eval"
8545           || anArg == "-proc")
8546     {
8547       if (++anArgIter >= theArgNb)
8548       {
8549         std::cout << "Syntax error at " << anArg << ".\n";
8550         return 1;
8551       }
8552
8553       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8554       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8555     }
8556     else if (anArg == "-objecttrsf"
8557           || anArg == "-objectransformation"
8558           || anArg == "-objtransformation"
8559           || anArg == "-objtrsf"
8560           || anArg == "-object"
8561           || anArg == "-obj")
8562     {
8563       if (++anArgIter >= theArgNb)
8564       {
8565         std::cout << "Syntax error at " << anArg << ".\n";
8566         return 1;
8567       }
8568
8569       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8570       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8571       Handle(AIS_InteractiveObject) anObject;
8572       if (!aMapOfAIS.Find2 (anObjName, anObject))
8573       {
8574         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8575         return 1;
8576       }
8577
8578       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8579       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8580       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8581       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8582       Standard_Boolean isTrsfSet = Standard_False;
8583       Standard_Integer aTrsfArgIter = anArgIter + 1;
8584       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8585       {
8586         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8587         aTrsfArg.LowerCase();
8588         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8589         if (aTrsfArg.StartsWith ("-rotation")
8590          || aTrsfArg.StartsWith ("-rot"))
8591         {
8592           isTrsfSet = Standard_True;
8593           if (aTrsfArgIter + 4 >= theArgNb
8594           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8595           {
8596             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8597             return 1;
8598           }
8599           aTrsfArgIter += 4;
8600         }
8601         else if (aTrsfArg.StartsWith ("-location")
8602               || aTrsfArg.StartsWith ("-loc"))
8603         {
8604           isTrsfSet = Standard_True;
8605           if (aTrsfArgIter + 3 >= theArgNb
8606           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8607           {
8608             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8609             return 1;
8610           }
8611           aTrsfArgIter += 3;
8612         }
8613         else if (aTrsfArg.StartsWith ("-scale"))
8614         {
8615           isTrsfSet = Standard_True;
8616           if (++aTrsfArgIter >= theArgNb)
8617           {
8618             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8619             return 1;
8620           }
8621
8622           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8623           if (!aScaleStr.IsRealValue())
8624           {
8625             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8626             return 1;
8627           }
8628           aScales[anIndex] = aScaleStr.RealValue();
8629         }
8630         else
8631         {
8632           anArgIter = aTrsfArgIter - 1;
8633           break;
8634         }
8635       }
8636       if (!isTrsfSet)
8637       {
8638         std::cout << "Syntax error at " << anArg << ".\n";
8639         return 1;
8640       }
8641       else if (aTrsfArgIter >= theArgNb)
8642       {
8643         anArgIter = theArgNb;
8644       }
8645
8646       aTrsfs[0].SetRotation        (aRotQuats[0]);
8647       aTrsfs[1].SetRotation        (aRotQuats[1]);
8648       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8649       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8650       aTrsfs[0].SetScaleFactor     (aScales[0]);
8651       aTrsfs[1].SetScaleFactor     (aScales[1]);
8652
8653       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8654       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8655     }
8656     else if (anArg == "-viewtrsf"
8657           || anArg == "-view")
8658     {
8659       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8660       if (aCamAnimation.IsNull())
8661       {
8662         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8663         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8664       }
8665
8666       Handle(Graphic3d_Camera) aCams[2] =
8667       {
8668         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8669         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8670       };
8671
8672       Standard_Boolean isTrsfSet = Standard_False;
8673       Standard_Integer aViewArgIter = anArgIter + 1;
8674       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8675       {
8676         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8677         aViewArg.LowerCase();
8678         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8679         if (aViewArg.StartsWith ("-scale"))
8680         {
8681           isTrsfSet = Standard_True;
8682           if (++aViewArgIter >= theArgNb)
8683           {
8684             std::cout << "Syntax error at " << anArg << ".\n";
8685             return 1;
8686           }
8687
8688           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8689           if (!aScaleStr.IsRealValue())
8690           {
8691             std::cout << "Syntax error at " << aViewArg << ".\n";
8692             return 1;
8693           }
8694           Standard_Real aScale = aScaleStr.RealValue();
8695           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8696           aCams[anIndex]->SetScale (aScale);
8697         }
8698         else if (aViewArg.StartsWith ("-eye")
8699               || aViewArg.StartsWith ("-center")
8700               || aViewArg.StartsWith ("-at")
8701               || aViewArg.StartsWith ("-up"))
8702         {
8703           isTrsfSet = Standard_True;
8704           gp_XYZ anXYZ;
8705           if (aViewArgIter + 3 >= theArgNb
8706           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8707           {
8708             std::cout << "Syntax error at " << aViewArg << ".\n";
8709             return 1;
8710           }
8711           aViewArgIter += 3;
8712
8713           if (aViewArg.StartsWith ("-eye"))
8714           {
8715             aCams[anIndex]->SetEye (anXYZ);
8716           }
8717           else if (aViewArg.StartsWith ("-center")
8718                 || aViewArg.StartsWith ("-at"))
8719           {
8720             aCams[anIndex]->SetCenter (anXYZ);
8721           }
8722           else if (aViewArg.StartsWith ("-up"))
8723           {
8724             aCams[anIndex]->SetUp (anXYZ);
8725           }
8726         }
8727         else
8728         {
8729           anArgIter = aViewArgIter - 1;
8730           break;
8731         }
8732       }
8733       if (!isTrsfSet)
8734       {
8735         std::cout << "Syntax error at " << anArg << ".\n";
8736         return 1;
8737       }
8738       else if (aViewArgIter >= theArgNb)
8739       {
8740         anArgIter = theArgNb;
8741       }
8742
8743       aCamAnimation->SetCameraStart(aCams[0]);
8744       aCamAnimation->SetCameraEnd  (aCams[1]);
8745     }
8746     else
8747     {
8748       std::cout << "Syntax error at " << anArg << ".\n";
8749       return 1;
8750     }
8751   }
8752
8753   if (!toPlay && aRecFile.IsEmpty())
8754   {
8755     return 0;
8756   }
8757
8758   // Start animation timeline and process frame updating.
8759   TheIsAnimating = Standard_True;
8760   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8761   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8762   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8763   if (isFreeCamera)
8764   {
8765     aView->Camera()->Copy (aCameraBack);
8766   }
8767
8768   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8769   if (aRecParams.FpsNum <= 0)
8770   {
8771     while (!anAnimation->IsStopped())
8772     {
8773       aCameraBack->Copy (aView->Camera());
8774       const Standard_Real aPts = anAnimation->UpdateTimer();
8775       if (isFreeCamera)
8776       {
8777         aView->Camera()->Copy (aCameraBack);
8778       }
8779
8780       if (aPts >= anUpperPts)
8781       {
8782         anAnimation->Pause();
8783         break;
8784       }
8785
8786       if (aView->IsInvalidated())
8787       {
8788         aView->Redraw();
8789       }
8790       else
8791       {
8792         aView->RedrawImmediate();
8793       }
8794
8795       if (!isLockLoop)
8796       {
8797         // handle user events
8798         theDI.Eval ("after 1 set waiter 1");
8799         theDI.Eval ("vwait waiter");
8800       }
8801       if (!TheIsAnimating)
8802       {
8803         anAnimation->Pause();
8804         theDI << aPts;
8805         break;
8806       }
8807     }
8808
8809     if (aView->IsInvalidated())
8810     {
8811       aView->Redraw();
8812     }
8813     else
8814     {
8815       aView->RedrawImmediate();
8816     }
8817   }
8818   else
8819   {
8820     OSD_Timer aPerfTimer;
8821     aPerfTimer.Start();
8822
8823     Handle(Image_VideoRecorder) aRecorder;
8824     ImageFlipper aFlipper;
8825     Handle(Draw_ProgressIndicator) aProgress;
8826     if (!aRecFile.IsEmpty())
8827     {
8828       if (aRecParams.Width  <= 0
8829        || aRecParams.Height <= 0)
8830       {
8831         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8832       }
8833
8834       aRecorder = new Image_VideoRecorder();
8835       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8836       {
8837         std::cout << "Error: failed to open video file for recording\n";
8838         return 0;
8839       }
8840
8841       aProgress = new Draw_ProgressIndicator (theDI, 1);
8842     }
8843
8844     // Manage frame-rated animation here
8845     Standard_Real aPts = aPlayStartTime;
8846     int64_t aNbFrames = 0;
8847     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
8848     Standard_Integer aSecondsProgress = 0;
8849     for (; aPts <= anUpperPts && aPSentry.More();)
8850     {
8851       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8852       aPts = aPlayStartTime + aRecPts;
8853       ++aNbFrames;
8854       if (!anAnimation->Update (aPts))
8855       {
8856         break;
8857       }
8858
8859       if (!aRecorder.IsNull())
8860       {
8861         V3d_ImageDumpOptions aDumpParams;
8862         aDumpParams.Width          = aRecParams.Width;
8863         aDumpParams.Height         = aRecParams.Height;
8864         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8865         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8866         aDumpParams.ToAdjustAspect = Standard_True;
8867         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8868         {
8869           std::cout << "Error: view dump is failed!\n";
8870           return 0;
8871         }
8872         aFlipper.FlipY (aRecorder->ChangeFrame());
8873         if (!aRecorder->PushFrame())
8874         {
8875           return 0;
8876         }
8877       }
8878       else
8879       {
8880         aView->Redraw();
8881       }
8882
8883       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8884       {
8885         aPSentry.Next();
8886         ++aSecondsProgress;
8887       }
8888     }
8889
8890     aPerfTimer.Stop();
8891     anAnimation->Stop();
8892     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8893     theDI << "Average FPS: " << aRecFps << "\n"
8894           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8895
8896     aView->Redraw();
8897   }
8898
8899   aView->SetImmediateUpdate (wasImmediateUpdate);
8900   TheIsAnimating = Standard_False;
8901   return 0;
8902 }
8903
8904
8905 //=======================================================================
8906 //function : VChangeSelected
8907 //purpose  : Adds the shape to selection or remove one from it
8908 //=======================================================================
8909 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8910                                 Standard_Integer argc,
8911                                 const char ** argv)
8912 {
8913   if(argc != 2)
8914   {
8915     di<<"Usage : " << argv[0] << " shape \n";
8916     return 1;
8917   }
8918   //get AIS_Shape:
8919   TCollection_AsciiString aName(argv[1]);
8920   Handle(AIS_InteractiveObject) anAISObject;
8921   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8922     || anAISObject.IsNull())
8923   {
8924     di<<"Use 'vdisplay' before";
8925     return 1;
8926   }
8927
8928   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8929   return 0;
8930 }
8931
8932 //=======================================================================
8933 //function : VNbSelected
8934 //purpose  : Returns number of selected objects
8935 //=======================================================================
8936 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8937                                 Standard_Integer argc,
8938                                 const char ** argv)
8939 {
8940   if(argc != 1)
8941   {
8942     di << "Usage : " << argv[0] << "\n";
8943     return 1;
8944   }
8945   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8946   if(aContext.IsNull())
8947   {
8948     di << "use 'vinit' command before " << argv[0] << "\n";
8949     return 1;
8950   }
8951   di << aContext->NbSelected() << "\n";
8952   return 0;
8953 }
8954
8955 //=======================================================================
8956 //function : VPurgeDisplay
8957 //purpose  : Switches altialiasing on or off
8958 //=======================================================================
8959 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8960                                 Standard_Integer argc,
8961                                 const char ** argv)
8962 {
8963   if (argc > 1)
8964   {
8965     di << "Usage : " << argv[0] << "\n";
8966     return 1;
8967   }
8968   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8969   if (aContext.IsNull())
8970   {
8971     di << "use 'vinit' command before " << argv[0] << "\n";
8972     return 1;
8973   }
8974
8975   di << aContext->PurgeDisplay() << "\n";
8976   return 0;
8977 }
8978
8979 //=======================================================================
8980 //function : VSetViewSize
8981 //purpose  :
8982 //=======================================================================
8983 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8984                                 Standard_Integer argc,
8985                                 const char ** argv)
8986 {
8987   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8988   if(aContext.IsNull())
8989   {
8990     di << "use 'vinit' command before " << argv[0] << "\n";
8991     return 1;
8992   }
8993   if(argc != 2)
8994   {
8995     di<<"Usage : " << argv[0] << " Size\n";
8996     return 1;
8997   }
8998   Standard_Real aSize = Draw::Atof (argv[1]);
8999   if (aSize <= 0.)
9000   {
9001     di<<"Bad Size value  : " << aSize << "\n";
9002     return 1;
9003   }
9004
9005   Handle(V3d_View) aView = ViewerTest::CurrentView();
9006   aView->SetSize(aSize);
9007   return 0;
9008 }
9009
9010 //=======================================================================
9011 //function : VMoveView
9012 //purpose  :
9013 //=======================================================================
9014 static Standard_Integer VMoveView (Draw_Interpretor& di,
9015                                 Standard_Integer argc,
9016                                 const char ** argv)
9017 {
9018   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9019   if(aContext.IsNull())
9020   {
9021     di << "use 'vinit' command before " << argv[0] << "\n";
9022     return 1;
9023   }
9024   if(argc < 4 || argc > 5)
9025   {
9026     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9027     return 1;
9028   }
9029   Standard_Real Dx = Draw::Atof (argv[1]);
9030   Standard_Real Dy = Draw::Atof (argv[2]);
9031   Standard_Real Dz = Draw::Atof (argv[3]);
9032   Standard_Boolean aStart = Standard_True;
9033   if (argc == 5)
9034   {
9035       aStart = (Draw::Atoi (argv[4]) > 0);
9036   }
9037
9038   Handle(V3d_View) aView = ViewerTest::CurrentView();
9039   aView->Move(Dx,Dy,Dz,aStart);
9040   return 0;
9041 }
9042
9043 //=======================================================================
9044 //function : VTranslateView
9045 //purpose  :
9046 //=======================================================================
9047 static Standard_Integer VTranslateView (Draw_Interpretor& di,
9048                                 Standard_Integer argc,
9049                                 const char ** argv)
9050 {
9051   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9052   if(aContext.IsNull())
9053   {
9054     di << "use 'vinit' command before " << argv[0] << "\n";
9055     return 1;
9056   }
9057   if(argc < 4 || argc > 5)
9058   {
9059     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9060     return 1;
9061   }
9062   Standard_Real Dx = Draw::Atof (argv[1]);
9063   Standard_Real Dy = Draw::Atof (argv[2]);
9064   Standard_Real Dz = Draw::Atof (argv[3]);
9065   Standard_Boolean aStart = Standard_True;
9066   if (argc == 5)
9067   {
9068       aStart = (Draw::Atoi (argv[4]) > 0);
9069   }
9070
9071   Handle(V3d_View) aView = ViewerTest::CurrentView();
9072   aView->Translate(Dx,Dy,Dz,aStart);
9073   return 0;
9074 }
9075
9076 //=======================================================================
9077 //function : VTurnView
9078 //purpose  :
9079 //=======================================================================
9080 static Standard_Integer VTurnView (Draw_Interpretor& di,
9081                                 Standard_Integer argc,
9082                                 const char ** argv)
9083 {
9084   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9085   if(aContext.IsNull()) {
9086     di << "use 'vinit' command before " << argv[0] << "\n";
9087     return 1;
9088   }
9089   if(argc < 4 || argc > 5){
9090     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
9091     return 1;
9092   }
9093   Standard_Real Ax = Draw::Atof (argv[1]);
9094   Standard_Real Ay = Draw::Atof (argv[2]);
9095   Standard_Real Az = Draw::Atof (argv[3]);
9096   Standard_Boolean aStart = Standard_True;
9097   if (argc == 5)
9098   {
9099       aStart = (Draw::Atoi (argv[4]) > 0);
9100   }
9101
9102   Handle(V3d_View) aView = ViewerTest::CurrentView();
9103   aView->Turn(Ax,Ay,Az,aStart);
9104   return 0;
9105 }
9106
9107 //==============================================================================
9108 //function : VTextureEnv
9109 //purpose  : ENables or disables environment mapping
9110 //==============================================================================
9111 class OCC_TextureEnv : public Graphic3d_TextureEnv
9112 {
9113 public:
9114   OCC_TextureEnv(const Standard_CString FileName);
9115   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
9116   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
9117                             const Standard_Boolean theModulateFlag,
9118                             const Graphic3d_TypeOfTextureFilter theFilter,
9119                             const Standard_ShortReal theXScale,
9120                             const Standard_ShortReal theYScale,
9121                             const Standard_ShortReal theXShift,
9122                             const Standard_ShortReal theYShift,
9123                             const Standard_ShortReal theAngle);
9124   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
9125 };
9126 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
9127
9128 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
9129   : Graphic3d_TextureEnv(theFileName)
9130 {
9131 }
9132
9133 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
9134   : Graphic3d_TextureEnv(theTexId)
9135 {
9136 }
9137
9138 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
9139                                           const Standard_Boolean theModulateFlag,
9140                                           const Graphic3d_TypeOfTextureFilter theFilter,
9141                                           const Standard_ShortReal theXScale,
9142                                           const Standard_ShortReal theYScale,
9143                                           const Standard_ShortReal theXShift,
9144                                           const Standard_ShortReal theYShift,
9145                                           const Standard_ShortReal theAngle)
9146 {
9147   myParams->SetRepeat     (theRepeatFlag);
9148   myParams->SetModulate   (theModulateFlag);
9149   myParams->SetFilter     (theFilter);
9150   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
9151   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
9152   myParams->SetRotation   (theAngle);
9153 }
9154
9155 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
9156 {
9157   // get the active view
9158   Handle(V3d_View) aView = ViewerTest::CurrentView();
9159   if (aView.IsNull())
9160   {
9161     std::cerr << "No active view. Please call vinit.\n";
9162     return 1;
9163   }
9164
9165   // Checking the input arguments
9166   Standard_Boolean anEnableFlag = Standard_False;
9167   Standard_Boolean isOk         = theArgNb >= 2;
9168   if (isOk)
9169   {
9170     TCollection_AsciiString anEnableOpt(theArgVec[1]);
9171     anEnableFlag = anEnableOpt.IsEqual("on");
9172     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
9173   }
9174   if (anEnableFlag)
9175   {
9176     isOk = (theArgNb == 3 || theArgNb == 11);
9177     if (isOk)
9178     {
9179       TCollection_AsciiString aTextureOpt(theArgVec[2]);
9180       isOk = (!aTextureOpt.IsIntegerValue() ||
9181              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
9182
9183       if (isOk && theArgNb == 11)
9184       {
9185         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
9186                                 aModulateOpt(theArgVec[4]),
9187                                 aFilterOpt  (theArgVec[5]),
9188                                 aSScaleOpt  (theArgVec[6]),
9189                                 aTScaleOpt  (theArgVec[7]),
9190                                 aSTransOpt  (theArgVec[8]),
9191                                 aTTransOpt  (theArgVec[9]),
9192                                 anAngleOpt  (theArgVec[10]);
9193         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
9194                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
9195                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
9196                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
9197                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
9198                 anAngleOpt.IsRealValue());
9199       }
9200     }
9201   }
9202
9203   if (!isOk)
9204   {
9205     std::cerr << "Usage :" << std::endl;
9206     std::cerr << theArgVec[0] << " off" << std::endl;
9207     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;
9208     return 1;
9209   }
9210
9211   if (anEnableFlag)
9212   {
9213     TCollection_AsciiString aTextureOpt(theArgVec[2]);
9214     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
9215                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
9216                                      new OCC_TextureEnv(theArgVec[2]);
9217
9218     if (theArgNb == 11)
9219     {
9220       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
9221       aTexEnv->SetTextureParameters(
9222         aRepeatOpt.  IsEqual("repeat"),
9223         aModulateOpt.IsEqual("modulate"),
9224         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
9225                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
9226                                                                            Graphic3d_TOTF_TRILINEAR,
9227         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
9228         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
9229         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
9230         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
9231         (Standard_ShortReal)Draw::Atof(theArgVec[10])
9232         );
9233     }
9234     aView->SetTextureEnv(aTexEnv);
9235   }
9236   else // Disabling environment mapping
9237   {
9238     Handle(Graphic3d_TextureEnv) aTexture;
9239     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
9240   }
9241
9242   aView->Redraw();
9243   return 0;
9244 }
9245
9246 namespace
9247 {
9248   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
9249
9250   //! Remove registered clipping plane from all views and objects.
9251   static void removePlane (MapOfPlanes& theRegPlanes,
9252                            const TCollection_AsciiString& theName)
9253   {
9254     Handle(Graphic3d_ClipPlane) aClipPlane;
9255     if (!theRegPlanes.Find (theName, aClipPlane))
9256     {
9257       std::cout << "Warning: no such plane.\n";
9258       return;
9259     }
9260
9261     theRegPlanes.UnBind (theName);
9262     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
9263          anIObjIt.More(); anIObjIt.Next())
9264     {
9265       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
9266       aPrs->RemoveClipPlane (aClipPlane);
9267     }
9268
9269     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
9270          aViewIt.More(); aViewIt.Next())
9271     {
9272       const Handle(V3d_View)& aView = aViewIt.Key2();
9273       aView->RemoveClipPlane(aClipPlane);
9274     }
9275
9276     ViewerTest::RedrawAllViews();
9277   }
9278 }
9279
9280 //===============================================================================================
9281 //function : VClipPlane
9282 //purpose  :
9283 //===============================================================================================
9284 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9285 {
9286   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9287   static MapOfPlanes aRegPlanes;
9288
9289   if (theArgsNb < 2)
9290   {
9291     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9292     {
9293       theDi << aPlaneIter.Key() << " ";
9294     }
9295     return 0;
9296   }
9297
9298   TCollection_AsciiString aCommand (theArgVec[1]);
9299   aCommand.LowerCase();
9300   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9301   if (anActiveView.IsNull())
9302   {
9303     std::cout << "Error: no active view.\n";
9304     return 1;
9305   }
9306
9307   // print maximum number of planes for current viewer
9308   if (aCommand == "-maxplanes"
9309    || aCommand == "maxplanes")
9310   {
9311     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9312           << " plane slots provided by driver.\n";
9313     return 0;
9314   }
9315
9316   // create / delete plane instance
9317   if (aCommand == "-create"
9318    || aCommand == "create"
9319    || aCommand == "-delete"
9320    || aCommand == "delete"
9321    || aCommand == "-clone"
9322    || aCommand == "clone")
9323   {
9324     if (theArgsNb < 3)
9325     {
9326       std::cout << "Syntax error: plane name is required.\n";
9327       return 1;
9328     }
9329
9330     Standard_Boolean toCreate = aCommand == "-create"
9331                              || aCommand == "create";
9332     Standard_Boolean toClone  = aCommand == "-clone"
9333                              || aCommand == "clone";
9334     Standard_Boolean toDelete = aCommand == "-delete"
9335                              || aCommand == "delete";
9336     TCollection_AsciiString aPlane (theArgVec[2]);
9337
9338     if (toCreate)
9339     {
9340       if (aRegPlanes.IsBound (aPlane))
9341       {
9342         std::cout << "Warning: existing plane has been overridden.\n";
9343         toDelete = true;
9344       }
9345       else
9346       {
9347         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9348         return 0;
9349       }
9350     }
9351     else if (toClone) // toClone
9352     {
9353       if (!aRegPlanes.IsBound (aPlane))
9354       {
9355         std::cout << "Error: no such plane.\n";
9356         return 1;
9357       }
9358       else if (theArgsNb < 4)
9359       {
9360         std::cout << "Syntax error: enter name for new plane.\n";
9361         return 1;
9362       }
9363
9364       TCollection_AsciiString aClone (theArgVec[3]);
9365       if (aRegPlanes.IsBound (aClone))
9366       {
9367         std::cout << "Error: plane name is in use.\n";
9368         return 1;
9369       }
9370
9371       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9372
9373       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9374       return 0;
9375     }
9376
9377     if (toDelete)
9378     {
9379       if (aPlane == "ALL"
9380        || aPlane == "all"
9381        || aPlane == "*")
9382       {
9383         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9384         {
9385           aPlane = aPlaneIter.Key();
9386           removePlane (aRegPlanes, aPlane);
9387           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9388         }
9389       }
9390       else
9391       {
9392         removePlane (aRegPlanes, aPlane);
9393       }
9394     }
9395
9396     if (toCreate)
9397     {
9398       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9399     }
9400     return 0;
9401   }
9402
9403   // set / unset plane command
9404   if (aCommand == "set"
9405    || aCommand == "unset")
9406   {
9407     if (theArgsNb < 5)
9408     {
9409       std::cout << "Syntax error: need more arguments.\n";
9410       return 1;
9411     }
9412
9413     // redirect to new syntax
9414     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9415     anArgVec.SetValue (1, theArgVec[0]);
9416     anArgVec.SetValue (2, theArgVec[2]);
9417     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9418     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9419     {
9420       anArgVec.SetValue (anIt, theArgVec[anIt]);
9421     }
9422
9423     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9424   }
9425
9426   // change plane command
9427   TCollection_AsciiString aPlaneName;
9428   Handle(Graphic3d_ClipPlane) aClipPlane;
9429   Standard_Integer anArgIter = 0;
9430   if (aCommand == "-change"
9431    || aCommand == "change")
9432   {
9433     // old syntax support
9434     if (theArgsNb < 3)
9435     {
9436       std::cout << "Syntax error: need more arguments.\n";
9437       return 1;
9438     }
9439
9440     anArgIter  = 3;
9441     aPlaneName = theArgVec[2];
9442     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9443     {
9444       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9445       return 1;
9446     }
9447   }
9448   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9449   {
9450     anArgIter  = 2;
9451     aPlaneName = theArgVec[1];
9452   }
9453   else
9454   {
9455     anArgIter  = 2;
9456     aPlaneName = theArgVec[1];
9457     aClipPlane = new Graphic3d_ClipPlane();
9458     aRegPlanes.Bind (aPlaneName, aClipPlane);
9459     theDi << "Created new plane " << aPlaneName << ".\n";
9460   }
9461
9462   if (theArgsNb - anArgIter < 1)
9463   {
9464     std::cout << "Syntax error: need more arguments.\n";
9465     return 1;
9466   }
9467
9468   for (; anArgIter < theArgsNb; ++anArgIter)
9469   {
9470     const char**     aChangeArgs   = theArgVec + anArgIter;
9471     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9472     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9473     aChangeArg.LowerCase();
9474
9475     Standard_Boolean toEnable = Standard_True;
9476     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9477     {
9478       aClipPlane->SetOn (toEnable);
9479     }
9480     else if (aChangeArg.StartsWith ("-equation")
9481           || aChangeArg.StartsWith ("equation"))
9482     {
9483       if (aNbChangeArgs < 5)
9484       {
9485         std::cout << "Syntax error: need more arguments.\n";
9486         return 1;
9487       }
9488
9489       Standard_Integer aSubIndex = 1;
9490       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9491       if (aPrefixLen < aChangeArg.Length())
9492       {
9493         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9494         if (!aSubStr.IsIntegerValue()
9495           || aSubStr.IntegerValue() <= 0)
9496         {
9497           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9498           return 1;
9499         }
9500         aSubIndex = aSubStr.IntegerValue();
9501       }
9502
9503       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9504       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9505       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9506       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9507       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9508       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9509       {
9510         if (aSubPln->ChainNextPlane().IsNull())
9511         {
9512           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9513         }
9514         aSubPln = aSubPln->ChainNextPlane();
9515       }
9516       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9517       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9518       anArgIter += 4;
9519     }
9520     else if ((aChangeArg == "-boxinterior"
9521            || aChangeArg == "-boxint"
9522            || aChangeArg == "-box")
9523             && aNbChangeArgs >= 7)
9524     {
9525       Graphic3d_BndBox3d aBndBox;
9526       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9527       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9528       anArgIter += 6;
9529
9530       Standard_Integer aNbSubPlanes = 6;
9531       const Graphic3d_Vec3d aDirArray[6] =
9532       {
9533         Graphic3d_Vec3d (-1, 0, 0),
9534         Graphic3d_Vec3d ( 1, 0, 0),
9535         Graphic3d_Vec3d ( 0,-1, 0),
9536         Graphic3d_Vec3d ( 0, 1, 0),
9537         Graphic3d_Vec3d ( 0, 0,-1),
9538         Graphic3d_Vec3d ( 0, 0, 1),
9539       };
9540       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9541       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9542       {
9543         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9544         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9545         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9546         if (aSubPlaneIter + 1 == aNbSubPlanes)
9547         {
9548           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9549         }
9550         else
9551         {
9552           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9553         }
9554         aSubPln = aSubPln->ChainNextPlane();
9555       }
9556     }
9557     else if (aChangeArg == "-capping"
9558           || aChangeArg == "capping")
9559     {
9560       if (aNbChangeArgs < 2)
9561       {
9562         std::cout << "Syntax error: need more arguments.\n";
9563         return 1;
9564       }
9565
9566       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9567       {
9568         aClipPlane->SetCapping (toEnable);
9569         anArgIter += 1;
9570       }
9571       else
9572       {
9573         // just skip otherwise (old syntax)
9574       }
9575     }
9576     else if (aChangeArg == "-useobjectmaterial"
9577           || aChangeArg == "-useobjectmat"
9578           || aChangeArg == "-useobjmat"
9579           || aChangeArg == "-useobjmaterial")
9580     {
9581       if (aNbChangeArgs < 2)
9582       {
9583         std::cout << "Syntax error: need more arguments.\n";
9584         return 1;
9585       }
9586
9587       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9588       {
9589         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9590         anArgIter += 1;
9591       }
9592     }
9593     else if (aChangeArg == "-useobjecttexture"
9594           || aChangeArg == "-useobjecttex"
9595           || aChangeArg == "-useobjtexture"
9596           || aChangeArg == "-useobjtex")
9597     {
9598       if (aNbChangeArgs < 2)
9599       {
9600         std::cout << "Syntax error: need more arguments.\n";
9601         return 1;
9602       }
9603
9604       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9605       {
9606         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9607         anArgIter += 1;
9608       }
9609     }
9610     else if (aChangeArg == "-useobjectshader"
9611           || aChangeArg == "-useobjshader")
9612     {
9613       if (aNbChangeArgs < 2)
9614       {
9615         std::cout << "Syntax error: need more arguments.\n";
9616         return 1;
9617       }
9618
9619       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9620       {
9621         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9622         anArgIter += 1;
9623       }
9624     }
9625     else if (aChangeArg == "-color"
9626           || aChangeArg == "color")
9627     {
9628       Quantity_Color aColor;
9629       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9630                                                            aChangeArgs + 1,
9631                                                            aColor);
9632       if (aNbParsed == 0)
9633       {
9634         std::cout << "Syntax error: need more arguments.\n";
9635         return 1;
9636       }
9637       aClipPlane->SetCappingColor (aColor);
9638       anArgIter += aNbParsed;
9639     }
9640     else if (aNbChangeArgs >= 1
9641           && (aChangeArg == "-material"
9642            || aChangeArg == "material"))
9643     {
9644       ++anArgIter;
9645       Graphic3d_NameOfMaterial aMatName;
9646       if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeArgs[1], aMatName))
9647       {
9648         std::cout << "Syntax error: unknown material '" << aChangeArgs[1] << "'.\n";
9649         return 1;
9650       }
9651       aClipPlane->SetCappingMaterial (aMatName);
9652     }
9653     else if ((aChangeArg == "-transparency"
9654            || aChangeArg == "-transp")
9655           && aNbChangeArgs >= 2)
9656     {
9657       TCollection_AsciiString aValStr (aChangeArgs[1]);
9658       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9659       if (aValStr.IsRealValue())
9660       {
9661         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9662         aMat.SetTransparency ((float )aValStr.RealValue());
9663         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9664         aClipPlane->SetCappingMaterial (aMat);
9665       }
9666       else
9667       {
9668         aValStr.LowerCase();
9669         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9670         if (aValStr == "opaque")
9671         {
9672           aMode = Graphic3d_AlphaMode_Opaque;
9673         }
9674         else if (aValStr == "mask")
9675         {
9676           aMode = Graphic3d_AlphaMode_Mask;
9677         }
9678         else if (aValStr == "blend")
9679         {
9680           aMode = Graphic3d_AlphaMode_Blend;
9681         }
9682         else if (aValStr == "blendauto")
9683         {
9684           aMode = Graphic3d_AlphaMode_BlendAuto;
9685         }
9686         else
9687         {
9688           std::cout << "Syntax error at '" << aValStr << "'\n";
9689           return 1;
9690         }
9691         anAspect->SetAlphaMode (aMode);
9692         aClipPlane->SetCappingAspect (anAspect);
9693       }
9694       anArgIter += 1;
9695     }
9696     else if (aChangeArg == "-texname"
9697           || aChangeArg == "texname")
9698     {
9699       if (aNbChangeArgs < 2)
9700       {
9701         std::cout << "Syntax error: need more arguments.\n";
9702         return 1;
9703       }
9704
9705       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9706       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9707       if (!aTexture->IsDone())
9708       {
9709         aClipPlane->SetCappingTexture (NULL);
9710       }
9711       else
9712       {
9713         aTexture->EnableModulate();
9714         aTexture->EnableRepeat();
9715         aClipPlane->SetCappingTexture (aTexture);
9716       }
9717       anArgIter += 1;
9718     }
9719     else if (aChangeArg == "-texscale"
9720           || aChangeArg == "texscale")
9721     {
9722       if (aClipPlane->CappingTexture().IsNull())
9723       {
9724         std::cout << "Error: no texture is set.\n";
9725         return 1;
9726       }
9727
9728       if (aNbChangeArgs < 3)
9729       {
9730         std::cout << "Syntax error: need more arguments.\n";
9731         return 1;
9732       }
9733
9734       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9735       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9736       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9737       anArgIter += 2;
9738     }
9739     else if (aChangeArg == "-texorigin"
9740           || aChangeArg == "texorigin") // texture origin
9741     {
9742       if (aClipPlane->CappingTexture().IsNull())
9743       {
9744         std::cout << "Error: no texture is set.\n";
9745         return 1;
9746       }
9747
9748       if (aNbChangeArgs < 3)
9749       {
9750         std::cout << "Syntax error: need more arguments.\n";
9751         return 1;
9752       }
9753
9754       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9755       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9756
9757       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9758       anArgIter += 2;
9759     }
9760     else if (aChangeArg == "-texrotate"
9761           || aChangeArg == "texrotate") // texture rotation
9762     {
9763       if (aClipPlane->CappingTexture().IsNull())
9764       {
9765         std::cout << "Error: no texture is set.\n";
9766         return 1;
9767       }
9768
9769       if (aNbChangeArgs < 2)
9770       {
9771         std::cout << "Syntax error: need more arguments.\n";
9772         return 1;
9773       }
9774
9775       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9776       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9777       anArgIter += 1;
9778     }
9779     else if (aChangeArg == "-hatch"
9780           || aChangeArg == "hatch")
9781     {
9782       if (aNbChangeArgs < 2)
9783       {
9784         std::cout << "Syntax error: need more arguments.\n";
9785         return 1;
9786       }
9787
9788       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9789       aHatchStr.LowerCase();
9790       if (aHatchStr == "on")
9791       {
9792         aClipPlane->SetCappingHatchOn();
9793       }
9794       else if (aHatchStr == "off")
9795       {
9796         aClipPlane->SetCappingHatchOff();
9797       }
9798       else
9799       {
9800         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9801       }
9802       anArgIter += 1;
9803     }
9804     else if (aChangeArg == "-delete"
9805           || aChangeArg == "delete")
9806     {
9807       removePlane (aRegPlanes, aPlaneName);
9808       return 0;
9809     }
9810     else if (aChangeArg == "-set"
9811           || aChangeArg == "-unset"
9812           || aChangeArg == "-setoverrideglobal")
9813     {
9814       // set / unset plane command
9815       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9816       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9817       Standard_Integer anIt = 1;
9818       for (; anIt < aNbChangeArgs; ++anIt)
9819       {
9820         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9821         if (anEntityName.IsEmpty()
9822          || anEntityName.Value (1) == '-')
9823         {
9824           break;
9825         }
9826         else if (!toOverrideGlobal
9827                && ViewerTest_myViews.IsBound1 (anEntityName))
9828         {
9829           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9830           if (toSet)
9831           {
9832             aView->AddClipPlane (aClipPlane);
9833           }
9834           else
9835           {
9836             aView->RemoveClipPlane (aClipPlane);
9837           }
9838           continue;
9839         }
9840         else if (GetMapOfAIS().IsBound2 (anEntityName))
9841         {
9842           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9843           if (toSet)
9844           {
9845             aIObj->AddClipPlane (aClipPlane);
9846           }
9847           else
9848           {
9849             aIObj->RemoveClipPlane (aClipPlane);
9850           }
9851           if (!aIObj->ClipPlanes().IsNull())
9852           {
9853             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9854           }
9855         }
9856         else
9857         {
9858           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9859           return 1;
9860         }
9861       }
9862
9863       if (anIt == 1)
9864       {
9865         // apply to active view
9866         if (toSet)
9867         {
9868           anActiveView->AddClipPlane (aClipPlane);
9869         }
9870         else
9871         {
9872           anActiveView->RemoveClipPlane (aClipPlane);
9873         }
9874       }
9875       else
9876       {
9877         anArgIter = anArgIter + anIt - 1;
9878       }
9879     }
9880     else
9881     {
9882       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9883       return 1;
9884     }
9885   }
9886
9887   ViewerTest::RedrawAllViews();
9888   return 0;
9889 }
9890
9891 //===============================================================================================
9892 //function : VZRange
9893 //purpose  :
9894 //===============================================================================================
9895 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9896 {
9897   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9898
9899   if (aCurrentView.IsNull())
9900   {
9901     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9902     return 1;
9903   }
9904
9905   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9906
9907   if (theArgsNb < 2)
9908   {
9909     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9910     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9911     return 0;
9912   }
9913
9914   if (theArgsNb == 3)
9915   {
9916     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9917     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9918
9919     if (aNewZNear >= aNewZFar)
9920     {
9921       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9922       return 1;
9923     }
9924
9925     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9926     {
9927       std::cout << theArgVec[0] << ": invalid arguments: ";
9928       std::cout << "znear, zfar should be positive for perspective camera.\n";
9929       return 1;
9930     }
9931
9932     aCamera->SetZRange (aNewZNear, aNewZFar);
9933   }
9934   else
9935   {
9936     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9937     return 1;
9938   }
9939
9940   aCurrentView->Redraw();
9941
9942   return 0;
9943 }
9944
9945 //===============================================================================================
9946 //function : VAutoZFit
9947 //purpose  :
9948 //===============================================================================================
9949 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9950 {
9951   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9952
9953   if (aCurrentView.IsNull())
9954   {
9955     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9956     return 1;
9957   }
9958
9959   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9960
9961   if (theArgsNb > 3)
9962   {
9963     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9964     return 1;
9965   }
9966
9967   if (theArgsNb < 2)
9968   {
9969     theDi << "Auto z-fit mode: \n"
9970           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9971           << "Scale: " << aScale << "\n";
9972     return 0;
9973   }
9974
9975   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9976
9977   if (theArgsNb >= 3)
9978   {
9979     aScale = Draw::Atoi (theArgVec[2]);
9980   }
9981
9982   aCurrentView->SetAutoZFitMode (isOn, aScale);
9983   aCurrentView->AutoZFit();
9984   aCurrentView->Redraw();
9985
9986   return 0;
9987 }
9988
9989 //! Auxiliary function to print projection type
9990 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9991 {
9992   switch (theProjType)
9993   {
9994     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9995     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9996     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9997     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9998     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9999   }
10000   return "UNKNOWN";
10001 }
10002
10003 //===============================================================================================
10004 //function : VCamera
10005 //purpose  :
10006 //===============================================================================================
10007 static int VCamera (Draw_Interpretor& theDI,
10008                     Standard_Integer  theArgsNb,
10009                     const char**      theArgVec)
10010 {
10011   Handle(V3d_View) aView = ViewerTest::CurrentView();
10012   if (aView.IsNull())
10013   {
10014     std::cout << "Error: no active view.\n";
10015     return 1;
10016   }
10017
10018   Handle(Graphic3d_Camera) aCamera = aView->Camera();
10019   if (theArgsNb < 2)
10020   {
10021     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
10022     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
10023     theDI << "Distance:   " << aCamera->Distance() << "\n";
10024     theDI << "IOD:        " << aCamera->IOD() << "\n";
10025     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
10026     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
10027     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
10028     return 0;
10029   }
10030
10031   TCollection_AsciiString aPrsName;
10032   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10033   {
10034     Standard_CString        anArg = theArgVec[anArgIter];
10035     TCollection_AsciiString anArgCase (anArg);
10036     anArgCase.LowerCase();
10037     if (anArgCase == "-proj"
10038      || anArgCase == "-projection"
10039      || anArgCase == "-projtype"
10040      || anArgCase == "-projectiontype")
10041     {
10042       theDI << projTypeName (aCamera->ProjectionType()) << " ";
10043     }
10044     else if (anArgCase == "-ortho"
10045           || anArgCase == "-orthographic")
10046     {
10047       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
10048     }
10049     else if (anArgCase == "-persp"
10050           || anArgCase == "-perspective"
10051           || anArgCase == "-perspmono"
10052           || anArgCase == "-perspectivemono"
10053           || anArgCase == "-mono")
10054     {
10055       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10056     }
10057     else if (anArgCase == "-stereo"
10058           || anArgCase == "-stereoscopic"
10059           || anArgCase == "-perspstereo"
10060           || anArgCase == "-perspectivestereo")
10061     {
10062       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10063     }
10064     else if (anArgCase == "-left"
10065           || anArgCase == "-lefteye"
10066           || anArgCase == "-monoleft"
10067           || anArgCase == "-monolefteye"
10068           || anArgCase == "-perpsleft"
10069           || anArgCase == "-perpslefteye")
10070     {
10071       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
10072     }
10073     else if (anArgCase == "-right"
10074           || anArgCase == "-righteye"
10075           || anArgCase == "-monoright"
10076           || anArgCase == "-monorighteye"
10077           || anArgCase == "-perpsright")
10078     {
10079       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
10080     }
10081     else if (anArgCase == "-dist"
10082           || anArgCase == "-distance")
10083     {
10084       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10085       if (anArgValue != NULL
10086       && *anArgValue != '-')
10087       {
10088         ++anArgIter;
10089         aCamera->SetDistance (Draw::Atof (anArgValue));
10090         continue;
10091       }
10092       theDI << aCamera->Distance() << " ";
10093     }
10094     else if (anArgCase == "-iod")
10095     {
10096       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10097       if (anArgValue != NULL
10098       && *anArgValue != '-')
10099       {
10100         ++anArgIter;
10101         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
10102         continue;
10103       }
10104       theDI << aCamera->IOD() << " ";
10105     }
10106     else if (anArgCase == "-iodtype")
10107     {
10108       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10109       TCollection_AsciiString anValueCase (anArgValue);
10110       anValueCase.LowerCase();
10111       if (anValueCase == "abs"
10112        || anValueCase == "absolute")
10113       {
10114         ++anArgIter;
10115         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
10116         continue;
10117       }
10118       else if (anValueCase == "rel"
10119             || anValueCase == "relative")
10120       {
10121         ++anArgIter;
10122         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
10123         continue;
10124       }
10125       else if (*anArgValue != '-')
10126       {
10127         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
10128         return 1;
10129       }
10130       switch (aCamera->GetIODType())
10131       {
10132         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
10133         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
10134       }
10135     }
10136     else if (anArgCase == "-zfocus")
10137     {
10138       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10139       if (anArgValue != NULL
10140       && *anArgValue != '-')
10141       {
10142         ++anArgIter;
10143         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
10144         continue;
10145       }
10146       theDI << aCamera->ZFocus() << " ";
10147     }
10148     else if (anArgCase == "-zfocustype")
10149     {
10150       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10151       TCollection_AsciiString anValueCase (anArgValue);
10152       anValueCase.LowerCase();
10153       if (anValueCase == "abs"
10154        || anValueCase == "absolute")
10155       {
10156         ++anArgIter;
10157         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
10158         continue;
10159       }
10160       else if (anValueCase == "rel"
10161             || anValueCase == "relative")
10162       {
10163         ++anArgIter;
10164         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
10165         continue;
10166       }
10167       else if (*anArgValue != '-')
10168       {
10169         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
10170         return 1;
10171       }
10172       switch (aCamera->ZFocusType())
10173       {
10174         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
10175         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
10176       }
10177     }
10178     else if (anArgCase == "-fov"
10179           || anArgCase == "-fovy")
10180     {
10181       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10182       if (anArgValue != NULL
10183       && *anArgValue != '-')
10184       {
10185         ++anArgIter;
10186         aCamera->SetFOVy (Draw::Atof (anArgValue));
10187         continue;
10188       }
10189       theDI << aCamera->FOVy() << " ";
10190     }
10191     else if (aPrsName.IsEmpty()
10192          && !anArgCase.StartsWith ("-"))
10193     {
10194       aPrsName = anArg;
10195     }
10196     else
10197     {
10198       std::cout << "Error: unknown argument '" << anArg << "'\n";
10199       return 1;
10200     }
10201   }
10202
10203   if (aPrsName.IsEmpty()
10204    || theArgsNb > 2)
10205   {
10206     aView->AutoZFit();
10207     aView->Redraw();
10208   }
10209
10210   if (!aPrsName.IsEmpty())
10211   {
10212     Handle(AIS_CameraFrustum) aCameraFrustum;
10213     if (GetMapOfAIS().IsBound2 (aPrsName))
10214     {
10215       // find existing object
10216       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
10217       if (aCameraFrustum.IsNull())
10218       {
10219         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
10220         return 1;
10221       }
10222     }
10223
10224     if (aCameraFrustum.IsNull())
10225     {
10226       aCameraFrustum = new AIS_CameraFrustum();
10227     }
10228     else
10229     {
10230       // not include displayed object of old camera frustum in the new one.
10231       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
10232       aView->ZFitAll();
10233     }
10234     aCameraFrustum->SetCameraFrustum (aView->Camera());
10235
10236     ViewerTest::Display (aPrsName, aCameraFrustum);
10237   }
10238
10239   return 0;
10240 }
10241
10242 //! Parse stereo output mode
10243 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
10244                                          Graphic3d_StereoMode& theMode)
10245 {
10246   TCollection_AsciiString aFlag (theArg);
10247   aFlag.LowerCase();
10248   if (aFlag == "quadbuffer")
10249   {
10250     theMode = Graphic3d_StereoMode_QuadBuffer;
10251   }
10252   else if (aFlag == "anaglyph")
10253   {
10254     theMode = Graphic3d_StereoMode_Anaglyph;
10255   }
10256   else if (aFlag == "row"
10257         || aFlag == "rowinterlaced")
10258   {
10259     theMode = Graphic3d_StereoMode_RowInterlaced;
10260   }
10261   else if (aFlag == "col"
10262         || aFlag == "colinterlaced"
10263         || aFlag == "columninterlaced")
10264   {
10265     theMode = Graphic3d_StereoMode_ColumnInterlaced;
10266   }
10267   else if (aFlag == "chess"
10268         || aFlag == "chessboard")
10269   {
10270     theMode = Graphic3d_StereoMode_ChessBoard;
10271   }
10272   else if (aFlag == "sbs"
10273         || aFlag == "sidebyside")
10274   {
10275     theMode = Graphic3d_StereoMode_SideBySide;
10276   }
10277   else if (aFlag == "ou"
10278         || aFlag == "overunder")
10279   {
10280     theMode = Graphic3d_StereoMode_OverUnder;
10281   }
10282   else if (aFlag == "pageflip"
10283         || aFlag == "softpageflip")
10284   {
10285     theMode = Graphic3d_StereoMode_SoftPageFlip;
10286   }
10287   else
10288   {
10289     return Standard_False;
10290   }
10291   return Standard_True;
10292 }
10293
10294 //! Parse anaglyph filter
10295 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10296                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10297 {
10298   TCollection_AsciiString aFlag (theArg);
10299   aFlag.LowerCase();
10300   if (aFlag == "redcyansimple")
10301   {
10302     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10303   }
10304   else if (aFlag == "redcyan"
10305         || aFlag == "redcyanoptimized")
10306   {
10307     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10308   }
10309   else if (aFlag == "yellowbluesimple")
10310   {
10311     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10312   }
10313   else if (aFlag == "yellowblue"
10314         || aFlag == "yellowblueoptimized")
10315   {
10316     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10317   }
10318   else if (aFlag == "greenmagenta"
10319         || aFlag == "greenmagentasimple")
10320   {
10321     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10322   }
10323   else
10324   {
10325     return Standard_False;
10326   }
10327   return Standard_True;
10328 }
10329
10330 //==============================================================================
10331 //function : VStereo
10332 //purpose  :
10333 //==============================================================================
10334
10335 static int VStereo (Draw_Interpretor& theDI,
10336                     Standard_Integer  theArgNb,
10337                     const char**      theArgVec)
10338 {
10339   Handle(V3d_View) aView = ViewerTest::CurrentView();
10340   if (theArgNb < 2)
10341   {
10342     if (aView.IsNull())
10343     {
10344       std::cout << "Error: no active viewer!\n";
10345       return 0;
10346     }
10347
10348     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10349     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10350     if (isActive)
10351     {
10352       TCollection_AsciiString aMode;
10353       switch (aView->RenderingParams().StereoMode)
10354       {
10355         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10356         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10357         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10358         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10359         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10360         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10361         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10362         case Graphic3d_StereoMode_Anaglyph  :
10363           aMode = "anaglyph";
10364           switch (aView->RenderingParams().AnaglyphFilter)
10365           {
10366             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10367             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10368             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10369             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10370             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10371             default: break;
10372           }
10373         default: break;
10374       }
10375       theDI << "Mode " << aMode << "\n";
10376     }
10377     return 0;
10378   }
10379
10380   Handle(Graphic3d_Camera) aCamera;
10381   Graphic3d_RenderingParams*   aParams   = NULL;
10382   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10383   if (!aView.IsNull())
10384   {
10385     aParams   = &aView->ChangeRenderingParams();
10386     aMode     = aParams->StereoMode;
10387     aCamera   = aView->Camera();
10388   }
10389
10390   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10391   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10392   {
10393     Standard_CString        anArg = theArgVec[anArgIter];
10394     TCollection_AsciiString aFlag (anArg);
10395     aFlag.LowerCase();
10396     if (anUpdateTool.parseRedrawMode (aFlag))
10397     {
10398       continue;
10399     }
10400     else if (aFlag == "0"
10401           || aFlag == "off")
10402     {
10403       if (++anArgIter < theArgNb)
10404       {
10405         std::cout << "Error: wrong number of arguments!\n";
10406         return 1;
10407       }
10408
10409       if (!aCamera.IsNull()
10410        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10411       {
10412         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10413       }
10414       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10415       return 0;
10416     }
10417     else if (aFlag == "1"
10418           || aFlag == "on")
10419     {
10420       if (++anArgIter < theArgNb)
10421       {
10422         std::cout << "Error: wrong number of arguments!\n";
10423         return 1;
10424       }
10425
10426       if (!aCamera.IsNull())
10427       {
10428         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10429       }
10430       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10431       return 0;
10432     }
10433     else if (aFlag == "-reverse"
10434           || aFlag == "-reversed"
10435           || aFlag == "-swap")
10436     {
10437       Standard_Boolean toEnable = Standard_True;
10438       if (++anArgIter < theArgNb
10439       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10440       {
10441         --anArgIter;
10442       }
10443       aParams->ToReverseStereo = toEnable;
10444     }
10445     else if (aFlag == "-noreverse"
10446           || aFlag == "-noswap")
10447     {
10448       Standard_Boolean toDisable = Standard_True;
10449       if (++anArgIter < theArgNb
10450       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10451       {
10452         --anArgIter;
10453       }
10454       aParams->ToReverseStereo = !toDisable;
10455     }
10456     else if (aFlag == "-mode"
10457           || aFlag == "-stereomode")
10458     {
10459       if (++anArgIter >= theArgNb
10460       || !parseStereoMode (theArgVec[anArgIter], aMode))
10461       {
10462         std::cout << "Error: syntax error at '" << anArg << "'\n";
10463         return 1;
10464       }
10465
10466       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10467       {
10468         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10469       }
10470     }
10471     else if (aFlag == "-anaglyph"
10472           || aFlag == "-anaglyphfilter")
10473     {
10474       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10475       if (++anArgIter >= theArgNb
10476       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10477       {
10478         std::cout << "Error: syntax error at '" << anArg << "'\n";
10479         return 1;
10480       }
10481
10482       aMode = Graphic3d_StereoMode_Anaglyph;
10483       aParams->AnaglyphFilter = aFilter;
10484     }
10485     else if (parseStereoMode (anArg, aMode)) // short syntax
10486     {
10487       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10488       {
10489         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10490       }
10491     }
10492     else
10493     {
10494       std::cout << "Error: syntax error at '" << anArg << "'\n";
10495       return 1;
10496     }
10497   }
10498
10499   if (!aView.IsNull())
10500   {
10501     aParams->StereoMode = aMode;
10502     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10503   }
10504   return 0;
10505 }
10506
10507 //===============================================================================================
10508 //function : VDefaults
10509 //purpose  :
10510 //===============================================================================================
10511 static int VDefaults (Draw_Interpretor& theDi,
10512                       Standard_Integer  theArgsNb,
10513                       const char**      theArgVec)
10514 {
10515   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10516   if (aCtx.IsNull())
10517   {
10518     std::cout << "Error: no active viewer\n";
10519     return 1;
10520   }
10521
10522   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10523   if (theArgsNb < 2)
10524   {
10525     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10526     {
10527       theDi << "DeflType:           relative\n"
10528             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10529     }
10530     else
10531     {
10532       theDi << "DeflType:           absolute\n"
10533             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10534     }
10535     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10536     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10537     return 0;
10538   }
10539
10540   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10541   {
10542     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10543     anArg.UpperCase();
10544     if (anArg == "-ABSDEFL"
10545      || anArg == "-ABSOLUTEDEFLECTION"
10546      || anArg == "-DEFL"
10547      || anArg == "-DEFLECTION")
10548     {
10549       if (++anArgIter >= theArgsNb)
10550       {
10551         std::cout << "Error: wrong syntax at " << anArg << "\n";
10552         return 1;
10553       }
10554       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10555       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10556     }
10557     else if (anArg == "-RELDEFL"
10558           || anArg == "-RELATIVEDEFLECTION"
10559           || anArg == "-DEVCOEFF"
10560           || anArg == "-DEVIATIONCOEFF"
10561           || anArg == "-DEVIATIONCOEFFICIENT")
10562     {
10563       if (++anArgIter >= theArgsNb)
10564       {
10565         std::cout << "Error: wrong syntax at " << anArg << "\n";
10566         return 1;
10567       }
10568       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10569       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10570     }
10571     else if (anArg == "-ANGDEFL"
10572           || anArg == "-ANGULARDEFL"
10573           || anArg == "-ANGULARDEFLECTION")
10574     {
10575       if (++anArgIter >= theArgsNb)
10576       {
10577         std::cout << "Error: wrong syntax at " << anArg << "\n";
10578         return 1;
10579       }
10580       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10581       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10582     }
10583     else if (anArg == "-AUTOTR"
10584           || anArg == "-AUTOTRIANG"
10585           || anArg == "-AUTOTRIANGULATION")
10586     {
10587       ++anArgIter;
10588       bool toTurnOn = true;
10589       if (anArgIter >= theArgsNb
10590       || !ViewerTest::ParseOnOff (theArgVec[anArgIter], toTurnOn))
10591       {
10592         std::cout << "Syntax error at '" << anArg << "'\n";
10593         return 1;
10594       }
10595       aDefParams->SetAutoTriangulation (toTurnOn);
10596     }
10597     else
10598     {
10599       std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
10600       return 1;
10601     }
10602   }
10603
10604   return 0;
10605 }
10606
10607 //! Auxiliary method
10608 inline void addLight (const Handle(V3d_Light)& theLightNew,
10609                       const Graphic3d_ZLayerId theLayer,
10610                       const Standard_Boolean   theIsGlobal)
10611 {
10612   if (theLightNew.IsNull())
10613   {
10614     return;
10615   }
10616
10617   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10618   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10619   {
10620     aViewer->AddLight (theLightNew);
10621     if (theIsGlobal)
10622     {
10623       aViewer->SetLightOn (theLightNew);
10624     }
10625     else
10626     {
10627       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10628     }
10629   }
10630   else
10631   {
10632     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10633     if (aSettings.Lights().IsNull())
10634     {
10635       aSettings.SetLights (new Graphic3d_LightSet());
10636     }
10637     aSettings.Lights()->Add (theLightNew);
10638     aViewer->SetZLayerSettings (theLayer, aSettings);
10639   }
10640 }
10641
10642 //! Auxiliary method
10643 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10644 {
10645   TCollection_AsciiString anArgNextCase (theArgNext);
10646   anArgNextCase.UpperCase();
10647   if (anArgNextCase.Length() > 5
10648    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10649   {
10650     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10651   }
10652   else
10653   {
10654     return theArgNext.IntegerValue();
10655   }
10656 }
10657
10658 //===============================================================================================
10659 //function : VLight
10660 //purpose  :
10661 //===============================================================================================
10662 static int VLight (Draw_Interpretor& theDi,
10663                    Standard_Integer  theArgsNb,
10664                    const char**      theArgVec)
10665 {
10666   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10667   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10668   if (aView.IsNull()
10669    || aViewer.IsNull())
10670   {
10671     std::cerr << "No active viewer!\n";
10672     return 1;
10673   }
10674
10675   Standard_Real anXYZ[3]   = {};
10676   Standard_Real anAtten[2] = {};
10677   if (theArgsNb < 2)
10678   {
10679     // print lights info
10680     Standard_Integer aLightId = 0;
10681     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10682     {
10683       Handle(V3d_Light) aLight = aLightIter.Value();
10684       const Quantity_Color aColor = aLight->Color();
10685       theDi << "Light #" << aLightId
10686             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10687             << " [" << aLight->GetId() << "]" << "\n";
10688       switch (aLight->Type())
10689       {
10690         case V3d_AMBIENT:
10691         {
10692           theDi << "  Type:       Ambient\n";
10693           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10694           break;
10695         }
10696         case V3d_DIRECTIONAL:
10697         {
10698           theDi << "  Type:       Directional\n";
10699           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10700           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10701           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10702           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10703           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10704           break;
10705         }
10706         case V3d_POSITIONAL:
10707         {
10708           theDi << "  Type:       Positional\n";
10709           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10710           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10711           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10712           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10713           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10714           aLight->Attenuation (anAtten[0], anAtten[1]);
10715           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10716           break;
10717         }
10718         case V3d_SPOT:
10719         {
10720           theDi << "  Type:       Spot\n";
10721           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10722           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10723           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10724           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10725           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10726           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10727           aLight->Attenuation (anAtten[0], anAtten[1]);
10728           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10729           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
10730           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
10731           break;
10732         }
10733         default:
10734         {
10735           theDi << "  Type:       UNKNOWN\n";
10736           break;
10737         }
10738       }
10739       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10740     }
10741   }
10742
10743   Handle(V3d_Light) aLightNew;
10744   Handle(V3d_Light) aLightOld;
10745   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10746   Standard_Boolean  isGlobal = Standard_True;
10747   Standard_Boolean  toCreate = Standard_False;
10748   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10749   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10750   {
10751     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10752
10753     TCollection_AsciiString aName, aValue;
10754     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10755     TCollection_AsciiString anArgCase (anArg);
10756     anArgCase.UpperCase();
10757     if (anUpdateTool.parseRedrawMode (anArg))
10758     {
10759       continue;
10760     }
10761
10762     if (anArgCase.IsEqual ("NEW")
10763      || anArgCase.IsEqual ("ADD")
10764      || anArgCase.IsEqual ("CREATE")
10765      || anArgCase.IsEqual ("-NEW")
10766      || anArgCase.IsEqual ("-ADD")
10767      || anArgCase.IsEqual ("-CREATE"))
10768     {
10769       toCreate = Standard_True;
10770     }
10771     else if (anArgCase.IsEqual ("-LAYER")
10772           || anArgCase.IsEqual ("-ZLAYER"))
10773     {
10774       if (++anArgIt >= theArgsNb)
10775       {
10776         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10777         return 1;
10778       }
10779
10780       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10781       aValStr.LowerCase();
10782       if (aValStr == "default"
10783        || aValStr == "def")
10784       {
10785         aLayer = Graphic3d_ZLayerId_Default;
10786       }
10787       else if (aValStr == "top")
10788       {
10789         aLayer = Graphic3d_ZLayerId_Top;
10790       }
10791       else if (aValStr == "topmost")
10792       {
10793         aLayer = Graphic3d_ZLayerId_Topmost;
10794       }
10795       else if (aValStr == "toposd"
10796             || aValStr == "osd")
10797       {
10798         aLayer = Graphic3d_ZLayerId_TopOSD;
10799       }
10800       else if (aValStr == "botosd"
10801             || aValStr == "bottom")
10802       {
10803         aLayer = Graphic3d_ZLayerId_BotOSD;
10804       }
10805       else if (aValStr.IsIntegerValue())
10806       {
10807         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10808       }
10809       else
10810       {
10811         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10812         return 1;
10813       }
10814     }
10815     else if (anArgCase.IsEqual ("GLOB")
10816           || anArgCase.IsEqual ("GLOBAL")
10817           || anArgCase.IsEqual ("-GLOB")
10818           || anArgCase.IsEqual ("-GLOBAL"))
10819     {
10820       isGlobal = Standard_True;
10821     }
10822     else if (anArgCase.IsEqual ("LOC")
10823           || anArgCase.IsEqual ("LOCAL")
10824           || anArgCase.IsEqual ("-LOC")
10825           || anArgCase.IsEqual ("-LOCAL"))
10826     {
10827       isGlobal = Standard_False;
10828     }
10829     else if (anArgCase.IsEqual ("DEF")
10830           || anArgCase.IsEqual ("DEFAULTS")
10831           || anArgCase.IsEqual ("-DEF")
10832           || anArgCase.IsEqual ("-DEFAULTS"))
10833     {
10834       toCreate = Standard_False;
10835       aViewer->SetDefaultLights();
10836     }
10837     else if (anArgCase.IsEqual ("CLR")
10838           || anArgCase.IsEqual ("CLEAR")
10839           || anArgCase.IsEqual ("-CLR")
10840           || anArgCase.IsEqual ("-CLEAR"))
10841     {
10842       toCreate = Standard_False;
10843
10844       TColStd_SequenceOfInteger aLayers;
10845       aViewer->GetAllZLayers (aLayers);
10846       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10847       {
10848         if (aLayeriter.Value() == aLayer
10849          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10850         {
10851           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10852           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10853           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10854           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10855           {
10856             break;
10857           }
10858         }
10859       }
10860
10861       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10862       {
10863         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10864         {
10865           Handle(V3d_Light) aLight = aLightIter.Value();
10866           aViewer->DelLight (aLight);
10867           aLightIter = aView->ActiveLightIterator();
10868         }
10869       }
10870     }
10871     else if (anArgCase.IsEqual ("AMB")
10872           || anArgCase.IsEqual ("AMBIENT")
10873           || anArgCase.IsEqual ("AMBLIGHT"))
10874     {
10875       if (!toCreate)
10876       {
10877         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10878         return 1;
10879       }
10880
10881       addLight (aLightNew, aLayer, isGlobal);
10882       toCreate  = Standard_False;
10883       aLightNew = new V3d_AmbientLight();
10884     }
10885     else if (anArgCase.IsEqual ("DIRECTIONAL")
10886           || anArgCase.IsEqual ("DIRLIGHT"))
10887     {
10888       if (!toCreate)
10889       {
10890         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10891         return 1;
10892       }
10893
10894       addLight (aLightNew, aLayer, isGlobal);
10895       toCreate  = Standard_False;
10896       aLightNew = new V3d_DirectionalLight();
10897     }
10898     else if (anArgCase.IsEqual ("SPOT")
10899           || anArgCase.IsEqual ("SPOTLIGHT"))
10900     {
10901       if (!toCreate)
10902       {
10903         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10904         return 1;
10905       }
10906
10907       addLight (aLightNew, aLayer, isGlobal);
10908       toCreate  = Standard_False;
10909       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10910     }
10911     else if (anArgCase.IsEqual ("POSLIGHT")
10912           || anArgCase.IsEqual ("POSITIONAL"))
10913     {
10914       if (!toCreate)
10915       {
10916         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10917         return 1;
10918       }
10919
10920       addLight (aLightNew, aLayer, isGlobal);
10921       toCreate  = Standard_False;
10922       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10923     }
10924     else if (anArgCase.IsEqual ("CHANGE")
10925           || anArgCase.IsEqual ("-CHANGE"))
10926     {
10927       if (++anArgIt >= theArgsNb)
10928       {
10929         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10930         return 1;
10931       }
10932
10933       addLight (aLightNew, aLayer, isGlobal);
10934       aLightNew.Nullify();
10935       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10936       Standard_Integer aLightIt = 0;
10937       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10938       {
10939         if (aLightIt == aLightId)
10940         {
10941           aLightOld = aLightIter.Value();
10942           break;
10943         }
10944       }
10945
10946       if (aLightOld.IsNull())
10947       {
10948         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10949         return 1;
10950       }
10951     }
10952     else if (anArgCase.IsEqual ("DEL")
10953           || anArgCase.IsEqual ("DELETE")
10954           || anArgCase.IsEqual ("-DEL")
10955           || anArgCase.IsEqual ("-DELETE"))
10956     {
10957       Handle(V3d_Light) aLightDel;
10958       if (++anArgIt >= theArgsNb)
10959       {
10960         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10961         return 1;
10962       }
10963
10964       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10965       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10966       Standard_Integer aLightIt = 0;
10967       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10968       {
10969         aLightDel = aLightIter.Value();
10970         if (aLightIt == aLightDelId)
10971         {
10972           break;
10973         }
10974       }
10975       if (aLightDel.IsNull())
10976       {
10977         continue;
10978       }
10979
10980       TColStd_SequenceOfInteger aLayers;
10981       aViewer->GetAllZLayers (aLayers);
10982       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10983       {
10984         if (aLayeriter.Value() == aLayer
10985          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10986         {
10987           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10988           if (!aSettings.Lights().IsNull())
10989           {
10990             aSettings.Lights()->Remove (aLightDel);
10991             if (aSettings.Lights()->IsEmpty())
10992             {
10993               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10994             }
10995           }
10996           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10997           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10998           {
10999             break;
11000           }
11001         }
11002       }
11003
11004       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
11005       {
11006         aViewer->DelLight (aLightDel);
11007       }
11008     }
11009     else if (anArgCase.IsEqual ("COLOR")
11010           || anArgCase.IsEqual ("COLOUR")
11011           || anArgCase.IsEqual ("-COLOR")
11012           || anArgCase.IsEqual ("-COLOUR"))
11013     {
11014       if (++anArgIt >= theArgsNb
11015        || aLightCurr.IsNull())
11016       {
11017         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11018         return 1;
11019       }
11020
11021       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
11022       anArgNext.UpperCase();
11023       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
11024       aLightCurr->SetColor (aColor);
11025     }
11026     else if (anArgCase.IsEqual ("POS")
11027           || anArgCase.IsEqual ("POSITION")
11028           || anArgCase.IsEqual ("-POS")
11029           || anArgCase.IsEqual ("-POSITION"))
11030     {
11031       if ((anArgIt + 3) >= theArgsNb
11032        || aLightCurr.IsNull()
11033        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11034         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11035       {
11036         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11037         return 1;
11038       }
11039
11040       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11041       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11042       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11043       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
11044     }
11045     else if (anArgCase.IsEqual ("DIR")
11046           || anArgCase.IsEqual ("DIRECTION")
11047           || anArgCase.IsEqual ("-DIR")
11048           || anArgCase.IsEqual ("-DIRECTION"))
11049     {
11050       if ((anArgIt + 3) >= theArgsNb
11051        || aLightCurr.IsNull()
11052        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
11053         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11054       {
11055         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11056         return 1;
11057       }
11058
11059       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11060       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11061       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11062       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
11063     }
11064     else if (anArgCase.IsEqual ("SM")
11065           || anArgCase.IsEqual ("SMOOTHNESS")
11066           || anArgCase.IsEqual ("-SM")
11067           || anArgCase.IsEqual ("-SMOOTHNESS"))
11068     {
11069       if (++anArgIt >= theArgsNb
11070        || aLightCurr.IsNull())
11071       {
11072         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11073         return 1;
11074       }
11075
11076       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11077       if (Abs (aSmoothness) <= ShortRealEpsilon())
11078       {
11079         aLightCurr->SetIntensity (1.f);
11080       }
11081       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
11082       {
11083         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
11084       }
11085       else
11086       {
11087         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
11088         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
11089       }
11090
11091       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
11092       {
11093         aLightCurr->SetSmoothRadius (aSmoothness);
11094       }
11095       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
11096       {
11097         aLightCurr->SetSmoothAngle (aSmoothness);
11098       }
11099     }
11100     else if (anArgCase.IsEqual ("INT")
11101           || anArgCase.IsEqual ("INTENSITY")
11102           || anArgCase.IsEqual ("-INT")
11103           || anArgCase.IsEqual ("-INTENSITY"))
11104     {
11105       if (++anArgIt >= theArgsNb
11106        || aLightCurr.IsNull())
11107       {
11108         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11109         return 1;
11110       }
11111
11112       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11113       aLightCurr->SetIntensity (aIntensity);
11114     }
11115     else if (anArgCase.IsEqual ("ANG")
11116           || anArgCase.IsEqual ("ANGLE")
11117           || anArgCase.IsEqual ("-ANG")
11118           || anArgCase.IsEqual ("-ANGLE"))
11119     {
11120       if (++anArgIt >= theArgsNb
11121        || aLightCurr.IsNull()
11122        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11123       {
11124         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11125         return 1;
11126       }
11127
11128       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11129       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
11130     }
11131     else if (anArgCase.IsEqual ("CONSTATTEN")
11132           || anArgCase.IsEqual ("CONSTATTENUATION")
11133           || anArgCase.IsEqual ("-CONSTATTEN")
11134           || anArgCase.IsEqual ("-CONSTATTENUATION"))
11135     {
11136       if (++anArgIt >= theArgsNb
11137        || aLightCurr.IsNull()
11138        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11139         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11140       {
11141         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11142         return 1;
11143       }
11144
11145       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11146       anAtten[0] = Atof (theArgVec[anArgIt]);
11147       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11148     }
11149     else if (anArgCase.IsEqual ("LINATTEN")
11150           || anArgCase.IsEqual ("LINEARATTEN")
11151           || anArgCase.IsEqual ("LINEARATTENUATION")
11152           || anArgCase.IsEqual ("-LINATTEN")
11153           || anArgCase.IsEqual ("-LINEARATTEN")
11154           || anArgCase.IsEqual ("-LINEARATTENUATION"))
11155     {
11156       if (++anArgIt >= theArgsNb
11157        || aLightCurr.IsNull()
11158        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11159         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11160       {
11161         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11162         return 1;
11163       }
11164
11165       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11166       anAtten[1] = Atof (theArgVec[anArgIt]);
11167       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11168     }
11169     else if (anArgCase.IsEqual ("EXP")
11170           || anArgCase.IsEqual ("EXPONENT")
11171           || anArgCase.IsEqual ("SPOTEXP")
11172           || anArgCase.IsEqual ("SPOTEXPONENT")
11173           || anArgCase.IsEqual ("-EXP")
11174           || anArgCase.IsEqual ("-EXPONENT")
11175           || anArgCase.IsEqual ("-SPOTEXP")
11176           || anArgCase.IsEqual ("-SPOTEXPONENT"))
11177     {
11178       if (++anArgIt >= theArgsNb
11179        || aLightCurr.IsNull()
11180        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11181       {
11182         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11183         return 1;
11184       }
11185
11186       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
11187     }
11188     else if (anArgCase.IsEqual ("HEAD")
11189           || anArgCase.IsEqual ("HEADLIGHT")
11190           || anArgCase.IsEqual ("-HEAD")
11191           || anArgCase.IsEqual ("-HEADLIGHT"))
11192     {
11193       if (aLightCurr.IsNull()
11194        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
11195       {
11196         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11197         return 1;
11198       }
11199
11200       Standard_Boolean isHeadLight = Standard_True;
11201       if (anArgIt + 1 < theArgsNb
11202        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
11203       {
11204         ++anArgIt;
11205       }
11206       aLightCurr->SetHeadlight (isHeadLight);
11207     }
11208     else
11209     {
11210       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
11211     }
11212   }
11213
11214   addLight (aLightNew, aLayer, isGlobal);
11215   return 0;
11216 }
11217
11218 //===============================================================================================
11219 //function : VPBREnvironment
11220 //purpose  :
11221 //===============================================================================================
11222 static int VPBREnvironment (Draw_Interpretor&,
11223                             Standard_Integer theArgsNb,
11224                             const char**     theArgVec)
11225 {
11226   if (theArgsNb > 2)
11227   {
11228     std::cerr << "Error: 'vpbrenv' command has only one argument\n";
11229     return 1;
11230   }
11231
11232   Handle(V3d_View) aView = ViewerTest::CurrentView();
11233   if (aView.IsNull())
11234   {
11235     std::cerr << "Error: no active viewer!\n";
11236     return 1;
11237   }
11238
11239   TCollection_AsciiString anArg = TCollection_AsciiString (theArgVec[1]);
11240   anArg.LowerCase();
11241
11242   if (anArg == "-generate"
11243    || anArg == "-gen")
11244   {
11245     aView->GeneratePBREnvironment (Standard_True);
11246   }
11247   else if (anArg == "-clear")
11248   {
11249     aView->ClearPBREnvironment (Standard_True);
11250   }
11251   else
11252   {
11253     std::cerr << "Error: unknown argument [" << theArgVec[1] << "] for 'vpbrenv' command\n";
11254     return 1;
11255   }
11256
11257   return 0;
11258 }
11259
11260 //! Read Graphic3d_RenderingParams::PerfCounters flag.
11261 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
11262                                             Standard_Boolean& theToReset,
11263                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
11264                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
11265 {
11266   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
11267   TCollection_AsciiString aVal = theValue;
11268   Standard_Boolean toReverse = Standard_False;
11269   if (aVal == "none")
11270   {
11271     theToReset = Standard_True;
11272     return Standard_True;
11273   }
11274   else if (aVal.StartsWith ("-"))
11275   {
11276     toReverse = Standard_True;
11277     aVal = aVal.SubString (2, aVal.Length());
11278   }
11279   else if (aVal.StartsWith ("no"))
11280   {
11281     toReverse = Standard_True;
11282     aVal = aVal.SubString (3, aVal.Length());
11283   }
11284   else if (aVal.StartsWith ("+"))
11285   {
11286     aVal = aVal.SubString (2, aVal.Length());
11287   }
11288   else
11289   {
11290     theToReset = Standard_True;
11291   }
11292
11293   if (     aVal == "fps"
11294         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11295   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
11296   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
11297   else if (aVal == "structs"
11298         || aVal == "structures"
11299         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
11300   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
11301   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11302   else if (aVal == "tris"
11303         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
11304   else if (aVal == "pnts"
11305         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
11306   else if (aVal == "mem"
11307         || aVal == "gpumem"
11308         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11309   else if (aVal == "skipimmediate"
11310         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
11311   else if (aVal == "frametime"
11312         || aVal == "frametimers"
11313         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11314   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
11315   else if (aVal == "extended"
11316         || aVal == "verbose"
11317         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
11318   else if (aVal == "full"
11319         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
11320   else
11321   {
11322     return Standard_False;
11323   }
11324
11325   if (toReverse)
11326   {
11327     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11328   }
11329   else
11330   {
11331     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11332   }
11333   return Standard_True;
11334 }
11335
11336 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11337 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11338                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11339 {
11340   TCollection_AsciiString aValue = theValue;
11341   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11342   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11343   Standard_Boolean toReset = Standard_False;
11344   for (;;)
11345   {
11346     Standard_Integer aSplitPos = aValue.Search ("|");
11347     if (aSplitPos <= 0)
11348     {
11349       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11350       {
11351         return Standard_False;
11352       }
11353       if (toReset)
11354       {
11355         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11356       }
11357       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11358       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11359       return Standard_True;
11360     }
11361
11362     if (aSplitPos > 1)
11363     {
11364       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11365       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11366       {
11367         return Standard_False;
11368       }
11369     }
11370     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11371   }
11372 }
11373
11374 //=======================================================================
11375 //function : VRenderParams
11376 //purpose  : Enables/disables rendering features
11377 //=======================================================================
11378
11379 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11380                                        Standard_Integer  theArgNb,
11381                                        const char**      theArgVec)
11382 {
11383   Handle(V3d_View) aView = ViewerTest::CurrentView();
11384   if (aView.IsNull())
11385   {
11386     std::cerr << "Error: no active viewer!\n";
11387     return 1;
11388   }
11389
11390   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11391   TCollection_AsciiString aCmdName (theArgVec[0]);
11392   aCmdName.LowerCase();
11393   if (aCmdName == "vraytrace")
11394   {
11395     if (theArgNb == 1)
11396     {
11397       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11398       return 0;
11399     }
11400     else if (theArgNb == 2)
11401     {
11402       TCollection_AsciiString aValue (theArgVec[1]);
11403       aValue.LowerCase();
11404       if (aValue == "on"
11405        || aValue == "1")
11406       {
11407         aParams.Method = Graphic3d_RM_RAYTRACING;
11408         aView->Redraw();
11409         return 0;
11410       }
11411       else if (aValue == "off"
11412             || aValue == "0")
11413       {
11414         aParams.Method = Graphic3d_RM_RASTERIZATION;
11415         aView->Redraw();
11416         return 0;
11417       }
11418       else
11419       {
11420         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11421         return 1;
11422       }
11423     }
11424     else
11425     {
11426       std::cout << "Error: wrong number of arguments\n";
11427       return 1;
11428     }
11429   }
11430
11431   if (theArgNb < 2)
11432   {
11433     theDI << "renderMode:  ";
11434     switch (aParams.Method)
11435     {
11436       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11437       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11438     }
11439     theDI << "\n";
11440     theDI << "transparency:  ";
11441     switch (aParams.TransparencyMethod)
11442     {
11443       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11444       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11445                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11446     }
11447     theDI << "\n";
11448     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11449     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11450     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11451     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11452     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11453     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11454     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11455     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11456     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11457     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11458     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11459     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11460     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11461     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11462     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11463     theDI << "shadingModel: ";
11464     switch (aView->ShadingModel())
11465     {
11466       case Graphic3d_TOSM_DEFAULT:   theDI << "default";   break;
11467       case Graphic3d_TOSM_UNLIT:     theDI << "unlit";     break;
11468       case Graphic3d_TOSM_FACET:     theDI << "flat";      break;
11469       case Graphic3d_TOSM_VERTEX:    theDI << "gouraud";   break;
11470       case Graphic3d_TOSM_FRAGMENT:  theDI << "phong";     break;
11471       case Graphic3d_TOSM_PBR:       theDI << "pbr";       break;
11472       case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
11473     }
11474     {
11475       theDI << "perfCounters:";
11476       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11477       {
11478         theDI << " fps";
11479       }
11480       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11481       {
11482         theDI << " cpu";
11483       }
11484       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11485       {
11486         theDI << " structs";
11487       }
11488       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11489       {
11490         theDI << " groups";
11491       }
11492       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11493       {
11494         theDI << " arrays";
11495       }
11496       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11497       {
11498         theDI << " tris";
11499       }
11500       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11501       {
11502         theDI << " pnts";
11503       }
11504       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11505       {
11506         theDI << " gpumem";
11507       }
11508       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11509       {
11510         theDI << " frameTime";
11511       }
11512       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11513       {
11514         theDI << " skipimmediate";
11515       }
11516       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11517       {
11518         theDI << " none";
11519       }
11520       theDI << "\n";
11521     }
11522     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11523     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11524     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11525                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11526                                                                                                                     "noUpdate") << "\n";
11527     theDI << "\n";
11528     return 0;
11529   }
11530
11531   Standard_Boolean toPrint = Standard_False;
11532   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11533   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11534   {
11535     Standard_CString        anArg (theArgVec[anArgIter]);
11536     TCollection_AsciiString aFlag (anArg);
11537     aFlag.LowerCase();
11538     if (anUpdateTool.parseRedrawMode (aFlag))
11539     {
11540       continue;
11541     }
11542     else if (aFlag == "-echo"
11543           || aFlag == "-print")
11544     {
11545       toPrint = Standard_True;
11546       anUpdateTool.Invalidate();
11547     }
11548     else if (aFlag == "-mode"
11549           || aFlag == "-rendermode"
11550           || aFlag == "-render_mode")
11551     {
11552       if (toPrint)
11553       {
11554         switch (aParams.Method)
11555         {
11556           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11557           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11558         }
11559         continue;
11560       }
11561       else
11562       {
11563         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11564         return 1;
11565       }
11566     }
11567     else if (aFlag == "-ray"
11568           || aFlag == "-raytrace")
11569     {
11570       if (toPrint)
11571       {
11572         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11573         continue;
11574       }
11575
11576       aParams.Method = Graphic3d_RM_RAYTRACING;
11577     }
11578     else if (aFlag == "-rast"
11579           || aFlag == "-raster"
11580           || aFlag == "-rasterization")
11581     {
11582       if (toPrint)
11583       {
11584         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11585         continue;
11586       }
11587
11588       aParams.Method = Graphic3d_RM_RASTERIZATION;
11589     }
11590     else if (aFlag == "-msaa")
11591     {
11592       if (toPrint)
11593       {
11594         theDI << aParams.NbMsaaSamples << " ";
11595         continue;
11596       }
11597       else if (++anArgIter >= theArgNb)
11598       {
11599         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11600         return 1;
11601       }
11602
11603       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11604       if (aNbSamples < 0)
11605       {
11606         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11607         return 1;
11608       }
11609       else
11610       {
11611         aParams.NbMsaaSamples = aNbSamples;
11612       }
11613     }
11614     else if (aFlag == "-linefeather"
11615           || aFlag == "-edgefeather"
11616           || aFlag == "-feather")
11617     {
11618       if (toPrint)
11619       {
11620         theDI << " " << aParams.LineFeather << " ";
11621         continue;
11622       }
11623       else if (++anArgIter >= theArgNb)
11624       {
11625         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11626         return 1;
11627       }
11628
11629       TCollection_AsciiString aParam = theArgVec[anArgIter];
11630       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11631       if (aFeather <= 0.0f)
11632       {
11633         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11634         return 1;
11635       }
11636       aParams.LineFeather = aFeather;
11637     }
11638     else if (aFlag == "-oit")
11639     {
11640       if (toPrint)
11641       {
11642         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11643         {
11644           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11645         }
11646         else
11647         {
11648           theDI << "off" << " ";
11649         }
11650         continue;
11651       }
11652       else if (++anArgIter >= theArgNb)
11653       {
11654         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11655         return 1;
11656       }
11657
11658       TCollection_AsciiString aParam = theArgVec[anArgIter];
11659       aParam.LowerCase();
11660       if (aParam.IsRealValue())
11661       {
11662         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11663         if (aWeight < 0.f || aWeight > 1.f)
11664         {
11665           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11666           return 1;
11667         }
11668
11669         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11670         aParams.OitDepthFactor     = aWeight;
11671       }
11672       else if (aParam == "off")
11673       {
11674         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11675       }
11676       else
11677       {
11678         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11679         return 1;
11680       }
11681     }
11682     else if (aFlag == "-depthprepass")
11683     {
11684       if (toPrint)
11685       {
11686         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11687         continue;
11688       }
11689       aParams.ToEnableDepthPrepass = Standard_True;
11690       if (anArgIter + 1 < theArgNb
11691        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11692       {
11693         ++anArgIter;
11694       }
11695     }
11696     else if (aFlag == "-samplealphatocoverage"
11697           || aFlag == "-alphatocoverage")
11698     {
11699       if (toPrint)
11700       {
11701         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11702         continue;
11703       }
11704       aParams.ToEnableAlphaToCoverage = Standard_True;
11705       if (anArgIter + 1 < theArgNb
11706        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11707       {
11708         ++anArgIter;
11709       }
11710     }
11711     else if (aFlag == "-rendscale"
11712           || aFlag == "-renderscale"
11713           || aFlag == "-renderresolutionscale")
11714     {
11715       if (toPrint)
11716       {
11717         theDI << aParams.RenderResolutionScale << " ";
11718         continue;
11719       }
11720       else if (++anArgIter >= theArgNb)
11721       {
11722         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11723         return 1;
11724       }
11725
11726       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11727       if (aScale < 0.01)
11728       {
11729         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11730         return 1;
11731       }
11732       else
11733       {
11734         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11735       }
11736     }
11737     else if (aFlag == "-raydepth"
11738           || aFlag == "-ray_depth")
11739     {
11740       if (toPrint)
11741       {
11742         theDI << aParams.RaytracingDepth << " ";
11743         continue;
11744       }
11745       else if (++anArgIter >= theArgNb)
11746       {
11747         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11748         return 1;
11749       }
11750
11751       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11752
11753       // We allow RaytracingDepth be more than 10 in case of GI enabled
11754       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11755       {
11756         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11757         return 1;
11758       }
11759       else
11760       {
11761         aParams.RaytracingDepth = aDepth;
11762       }
11763     }
11764     else if (aFlag == "-shad"
11765           || aFlag == "-shadows")
11766     {
11767       if (toPrint)
11768       {
11769         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11770         continue;
11771       }
11772
11773       Standard_Boolean toEnable = Standard_True;
11774       if (++anArgIter < theArgNb
11775       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11776       {
11777         --anArgIter;
11778       }
11779       aParams.IsShadowEnabled = toEnable;
11780     }
11781     else if (aFlag == "-refl"
11782           || aFlag == "-reflections")
11783     {
11784       if (toPrint)
11785       {
11786         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11787         continue;
11788       }
11789
11790       Standard_Boolean toEnable = Standard_True;
11791       if (++anArgIter < theArgNb
11792       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11793       {
11794         --anArgIter;
11795       }
11796       aParams.IsReflectionEnabled = toEnable;
11797     }
11798     else if (aFlag == "-fsaa")
11799     {
11800       if (toPrint)
11801       {
11802         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11803         continue;
11804       }
11805
11806       Standard_Boolean toEnable = Standard_True;
11807       if (++anArgIter < theArgNb
11808       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11809       {
11810         --anArgIter;
11811       }
11812       aParams.IsAntialiasingEnabled = toEnable;
11813     }
11814     else if (aFlag == "-gleam")
11815     {
11816       if (toPrint)
11817       {
11818         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11819         continue;
11820       }
11821
11822       Standard_Boolean toEnable = Standard_True;
11823       if (++anArgIter < theArgNb
11824       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11825       {
11826         --anArgIter;
11827       }
11828       aParams.IsTransparentShadowEnabled = toEnable;
11829     }
11830     else if (aFlag == "-gi")
11831     {
11832       if (toPrint)
11833       {
11834         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11835         continue;
11836       }
11837
11838       Standard_Boolean toEnable = Standard_True;
11839       if (++anArgIter < theArgNb
11840       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11841       {
11842         --anArgIter;
11843       }
11844       aParams.IsGlobalIlluminationEnabled = toEnable;
11845       if (!toEnable)
11846       {
11847         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11848       }
11849     }
11850     else if (aFlag == "-blockedrng"
11851           || aFlag == "-brng")
11852     {
11853       if (toPrint)
11854       {
11855         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11856         continue;
11857       }
11858
11859       Standard_Boolean toEnable = Standard_True;
11860       if (++anArgIter < theArgNb
11861         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11862       {
11863         --anArgIter;
11864       }
11865       aParams.CoherentPathTracingMode = toEnable;
11866     }
11867     else if (aFlag == "-maxrad")
11868     {
11869       if (toPrint)
11870       {
11871         theDI << aParams.RadianceClampingValue << " ";
11872         continue;
11873       }
11874       else if (++anArgIter >= theArgNb)
11875       {
11876         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11877         return 1;
11878       }
11879
11880       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11881       if (!aMaxRadStr.IsRealValue())
11882       {
11883         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11884         return 1;
11885       }
11886
11887       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11888       if (aMaxRadiance <= 0.0)
11889       {
11890         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11891         return 1;
11892       }
11893       else
11894       {
11895         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11896       }
11897     }
11898     else if (aFlag == "-iss")
11899     {
11900       if (toPrint)
11901       {
11902         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11903         continue;
11904       }
11905
11906       Standard_Boolean toEnable = Standard_True;
11907       if (++anArgIter < theArgNb
11908         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11909       {
11910         --anArgIter;
11911       }
11912       aParams.AdaptiveScreenSampling = toEnable;
11913     }
11914     else if (aFlag == "-issatomic")
11915     {
11916       if (toPrint)
11917       {
11918         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11919         continue;
11920       }
11921
11922       Standard_Boolean toEnable = Standard_True;
11923       if (++anArgIter < theArgNb
11924       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11925       {
11926         --anArgIter;
11927       }
11928       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11929     }
11930     else if (aFlag == "-issd")
11931     {
11932       if (toPrint)
11933       {
11934         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11935         continue;
11936       }
11937
11938       Standard_Boolean toEnable = Standard_True;
11939       if (++anArgIter < theArgNb
11940         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11941       {
11942         --anArgIter;
11943       }
11944       aParams.ShowSamplingTiles = toEnable;
11945     }
11946     else if (aFlag == "-tilesize")
11947     {
11948       if (toPrint)
11949       {
11950         theDI << aParams.RayTracingTileSize << " ";
11951         continue;
11952       }
11953       else if (++anArgIter >= theArgNb)
11954       {
11955         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11956         return 1;
11957       }
11958
11959       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11960       if (aTileSize < 1)
11961       {
11962         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11963         return 1;
11964       }
11965       aParams.RayTracingTileSize = aTileSize;
11966     }
11967     else if (aFlag == "-nbtiles")
11968     {
11969       if (toPrint)
11970       {
11971         theDI << aParams.NbRayTracingTiles << " ";
11972         continue;
11973       }
11974       else if (++anArgIter >= theArgNb)
11975       {
11976         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11977         return 1;
11978       }
11979
11980       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11981       if (aNbTiles < -1)
11982       {
11983         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11984         return 1;
11985       }
11986       else if (aNbTiles > 0
11987             && (aNbTiles < 64
11988              || aNbTiles > 1024))
11989       {
11990         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
11991       }
11992       aParams.NbRayTracingTiles = aNbTiles;
11993     }
11994     else if (aFlag == "-env")
11995     {
11996       if (toPrint)
11997       {
11998         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11999         continue;
12000       }
12001
12002       Standard_Boolean toEnable = Standard_True;
12003       if (++anArgIter < theArgNb
12004         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12005       {
12006         --anArgIter;
12007       }
12008       aParams.UseEnvironmentMapBackground = toEnable;
12009     }
12010     else if (aFlag == "-twoside")
12011     {
12012       if (toPrint)
12013       {
12014         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
12015         continue;
12016       }
12017
12018       Standard_Boolean toEnable = Standard_True;
12019       if (++anArgIter < theArgNb
12020         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12021       {
12022         --anArgIter;
12023       }
12024       aParams.TwoSidedBsdfModels = toEnable;
12025     }
12026     else if (aFlag == "-shademodel"
12027           || aFlag == "-shadingmodel"
12028           || aFlag == "-shading")
12029     {
12030       if (toPrint)
12031       {
12032         switch (aView->ShadingModel())
12033         {
12034           case Graphic3d_TOSM_DEFAULT:   theDI << "default";   break;
12035           case Graphic3d_TOSM_UNLIT:     theDI << "unlit ";    break;
12036           case Graphic3d_TOSM_FACET:     theDI << "flat ";     break;
12037           case Graphic3d_TOSM_VERTEX:    theDI << "gouraud ";  break;
12038           case Graphic3d_TOSM_FRAGMENT:  theDI << "phong ";    break;
12039           case Graphic3d_TOSM_PBR:       theDI << "pbr";       break;
12040           case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
12041         }
12042         continue;
12043       }
12044
12045       if (++anArgIter >= theArgNb)
12046       {
12047         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12048       }
12049
12050       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
12051       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
12052        && aModel != Graphic3d_TOSM_DEFAULT)
12053       {
12054         aView->SetShadingModel (aModel);
12055       }
12056       else
12057       {
12058         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
12059         return 1;
12060       }
12061     }
12062     else if (aFlag == "-pbrenvpow2size"
12063           || aFlag == "-pbrenvp2s"
12064           || aFlag == "-pep2s")
12065     {
12066       if (++anArgIter >= theArgNb)
12067       {
12068         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12069         return 1;
12070       }
12071
12072       const Standard_Integer aPbrEnvPow2Size = Draw::Atoi (theArgVec[anArgIter]);
12073       if (aPbrEnvPow2Size < 1)
12074       {
12075         std::cout << "Error: 'Pow2Size' of PBR Environment has to be greater or equal 1\n";
12076         return 1;
12077       }
12078       aParams.PbrEnvPow2Size = aPbrEnvPow2Size;
12079     }
12080     else if (aFlag == "-pbrenvspecmaplevelsnumber"
12081           || aFlag == "-pbrenvspecmapnblevels"
12082           || aFlag == "-pbrenvspecmaplevels"
12083           || aFlag == "-pbrenvsmln"
12084           || aFlag == "-pesmln")
12085     {
12086       if (++anArgIter >= theArgNb)
12087       {
12088         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12089         return 1;
12090       }
12091
12092       const Standard_Integer aPbrEnvSpecMapNbLevels = Draw::Atoi (theArgVec[anArgIter]);
12093       if (aPbrEnvSpecMapNbLevels < 2)
12094       {
12095         std::cout << "Error: 'SpecMapLevelsNumber' of PBR Environment has to be greater or equal 2\n";
12096         return 1;
12097       }
12098       aParams.PbrEnvSpecMapNbLevels = aPbrEnvSpecMapNbLevels;
12099     }
12100     else if (aFlag == "-pbrenvbakngdiffsamplesnumber"
12101           || aFlag == "-pbrenvbakingdiffsamples"
12102           || aFlag == "-pbrenvbdsn")
12103     {
12104       if (++anArgIter >= theArgNb)
12105       {
12106         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12107         return 1;
12108       }
12109
12110       const Standard_Integer aPbrEnvBakingDiffNbSamples = Draw::Atoi (theArgVec[anArgIter]);
12111       if (aPbrEnvBakingDiffNbSamples < 1)
12112       {
12113         std::cout << "Error: 'BakingDiffSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
12114         return 1;
12115       }
12116       aParams.PbrEnvBakingDiffNbSamples = aPbrEnvBakingDiffNbSamples;
12117     }
12118     else if (aFlag == "-pbrenvbakngspecsamplesnumber"
12119           || aFlag == "-pbrenvbakingspecsamples"
12120           || aFlag == "-pbrenvbssn")
12121     {
12122     if (++anArgIter >= theArgNb)
12123     {
12124       std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12125       return 1;
12126     }
12127
12128     const Standard_Integer aPbrEnvBakingSpecNbSamples = Draw::Atoi(theArgVec[anArgIter]);
12129     if (aPbrEnvBakingSpecNbSamples < 1)
12130     {
12131       std::cout << "Error: 'BakingSpecSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
12132       return 1;
12133     }
12134     aParams.PbrEnvBakingSpecNbSamples = aPbrEnvBakingSpecNbSamples;
12135     }
12136     else if (aFlag == "-pbrenvbakingprobability"
12137           || aFlag == "-pbrenvbp")
12138     {
12139       if (++anArgIter >= theArgNb)
12140       {
12141         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12142         return 1;
12143       }
12144       const Standard_ShortReal aPbrEnvBakingProbability = static_cast<Standard_ShortReal>(Draw::Atof (theArgVec[anArgIter]));
12145       if (aPbrEnvBakingProbability < 0.f
12146        || aPbrEnvBakingProbability > 1.f)
12147       {
12148         std::cout << "Error: 'BakingProbability' of PBR Environtment has to be in range of [0, 1]\n";
12149         return 1;
12150       }
12151       aParams.PbrEnvBakingProbability = aPbrEnvBakingProbability;
12152     }
12153     else if (aFlag == "-resolution")
12154     {
12155       if (++anArgIter >= theArgNb)
12156       {
12157         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12158         return 1;
12159       }
12160
12161       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
12162       if (aResolution.IsIntegerValue())
12163       {
12164         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
12165       }
12166       else
12167       {
12168         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12169         return 1;
12170       }
12171     }
12172     else if (aFlag == "-rebuildglsl"
12173           || aFlag == "-rebuild")
12174     {
12175       if (toPrint)
12176       {
12177         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
12178         continue;
12179       }
12180
12181       Standard_Boolean toEnable = Standard_True;
12182       if (++anArgIter < theArgNb
12183           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12184       {
12185         --anArgIter;
12186       }
12187       aParams.RebuildRayTracingShaders = toEnable;
12188     }
12189     else if (aFlag == "-focal")
12190     {
12191       if (++anArgIter >= theArgNb)
12192       {
12193         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12194         return 1;
12195       }
12196
12197       TCollection_AsciiString aParam (theArgVec[anArgIter]);
12198       if (aParam.IsRealValue())
12199       {
12200         float aFocalDist = static_cast<float> (aParam.RealValue());
12201         if (aFocalDist < 0)
12202         {
12203           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12204           return 1;
12205         }
12206         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
12207       }
12208       else
12209       {
12210         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12211         return 1;
12212       }
12213     }
12214     else if (aFlag == "-aperture")
12215     {
12216       if (++anArgIter >= theArgNb)
12217       {
12218         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12219         return 1;
12220       }
12221
12222       TCollection_AsciiString aParam(theArgVec[anArgIter]);
12223       if (aParam.IsRealValue())
12224       {
12225         float aApertureSize = static_cast<float> (aParam.RealValue());
12226         if (aApertureSize < 0)
12227         {
12228           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12229           return 1;
12230         }
12231         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
12232       }
12233       else
12234       {
12235         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12236         return 1;
12237       }
12238     }
12239     else if (aFlag == "-exposure")
12240     {
12241       if (++anArgIter >= theArgNb)
12242       {
12243         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12244         return 1;
12245       }
12246
12247       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
12248       if (anExposure.IsRealValue())
12249       {
12250         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
12251       }
12252       else
12253       {
12254         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12255         return 1;
12256       }
12257     }
12258     else if (aFlag == "-whitepoint")
12259     {
12260       if (++anArgIter >= theArgNb)
12261       {
12262         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12263         return 1;
12264       }
12265
12266       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
12267       if (aWhitePoint.IsRealValue())
12268       {
12269         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
12270       }
12271       else
12272       {
12273         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12274         return 1;
12275       }
12276     }
12277     else if (aFlag == "-tonemapping")
12278     {
12279       if (++anArgIter >= theArgNb)
12280       {
12281         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12282         return 1;
12283       }
12284
12285       TCollection_AsciiString aMode (theArgVec[anArgIter]);
12286       aMode.LowerCase();
12287
12288       if (aMode == "disabled")
12289       {
12290         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
12291       }
12292       else if (aMode == "filmic")
12293       {
12294         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
12295       }
12296       else
12297       {
12298         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12299         return 1;
12300       }
12301     }
12302     else if (aFlag == "-performancestats"
12303           || aFlag == "-performancecounters"
12304           || aFlag == "-perfstats"
12305           || aFlag == "-perfcounters"
12306           || aFlag == "-stats")
12307     {
12308       if (++anArgIter >= theArgNb)
12309       {
12310         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12311         return 1;
12312       }
12313
12314       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
12315       aFlagsStr.LowerCase();
12316       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
12317       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
12318       {
12319         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12320         return 1;
12321       }
12322       aView->ChangeRenderingParams().CollectedStats = aFlags;
12323       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
12324     }
12325     else if (aFlag == "-perfupdateinterval"
12326           || aFlag == "-statsupdateinterval")
12327     {
12328       if (++anArgIter >= theArgNb)
12329       {
12330         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12331         return 1;
12332       }
12333       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12334     }
12335     else if (aFlag == "-perfchart"
12336           || aFlag == "-statschart")
12337     {
12338       if (++anArgIter >= theArgNb)
12339       {
12340         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12341         return 1;
12342       }
12343       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
12344     }
12345     else if (aFlag == "-perfchartmax"
12346           || aFlag == "-statschartmax")
12347     {
12348       if (++anArgIter >= theArgNb)
12349       {
12350         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12351         return 1;
12352       }
12353       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12354     }
12355     else if (aFlag == "-frustumculling"
12356           || aFlag == "-culling")
12357     {
12358       if (toPrint)
12359       {
12360         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
12361                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
12362                                                                                                    "noUpdate") << " ";
12363         continue;
12364       }
12365
12366       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
12367       if (++anArgIter < theArgNb)
12368       {
12369         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
12370         aStateStr.LowerCase();
12371         bool toEnable = true;
12372         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
12373         {
12374           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
12375         }
12376         else if (aStateStr == "noupdate"
12377               || aStateStr == "freeze")
12378         {
12379           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
12380         }
12381         else
12382         {
12383           --anArgIter;
12384         }
12385       }
12386       aParams.FrustumCullingState = aState;
12387     }
12388     else
12389     {
12390       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
12391       return 1;
12392     }
12393   }
12394
12395   return 0;
12396 }
12397
12398 //=======================================================================
12399 //function : searchInfo
12400 //purpose  :
12401 //=======================================================================
12402 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12403                                            const TCollection_AsciiString&              theKey)
12404 {
12405   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12406   {
12407     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12408     {
12409       return anIter.Value();
12410     }
12411   }
12412   return TCollection_AsciiString();
12413 }
12414
12415 //=======================================================================
12416 //function : VStatProfiler
12417 //purpose  :
12418 //=======================================================================
12419 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12420                                        Standard_Integer  theArgNb,
12421                                        const char**      theArgVec)
12422 {
12423   Handle(V3d_View) aView = ViewerTest::CurrentView();
12424   if (aView.IsNull())
12425   {
12426     std::cerr << "Error: no active viewer!\n";
12427     return 1;
12428   }
12429
12430   Standard_Boolean toRedraw = Standard_True;
12431   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12432   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12433   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12434   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12435   {
12436     Standard_CString        anArg (theArgVec[anArgIter]);
12437     TCollection_AsciiString aFlag (anArg);
12438     aFlag.LowerCase();
12439     if (aFlag == "-noredraw")
12440     {
12441       toRedraw = Standard_False;
12442     }
12443     else
12444     {
12445       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12446       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12447       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12448       else if (aFlag == "alllayers"
12449             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12450       else if (aFlag == "allstructs"
12451             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12452       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12453       else if (aFlag == "allarrays"
12454             || aFlag == "fillarrays"
12455             || aFlag == "linearrays"
12456             || aFlag == "pointarrays"
12457             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12458       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12459       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12460       else if (aFlag == "geommem"
12461             || aFlag == "texturemem"
12462             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12463       else if (aFlag == "elapsedframe"
12464             || aFlag == "cpuframeaverage"
12465             || aFlag == "cpupickingaverage"
12466             || aFlag == "cpucullingaverage"
12467             || aFlag == "cpudynaverage"
12468             || aFlag == "cpuframemax"
12469             || aFlag == "cpupickingmax"
12470             || aFlag == "cpucullingmax"
12471             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12472       else
12473       {
12474         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12475         continue;
12476       }
12477
12478       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12479     }
12480   }
12481
12482   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12483   {
12484     aView->ChangeRenderingParams().CollectedStats =
12485       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12486
12487     if (toRedraw)
12488     {
12489       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12490       aView->Redraw();
12491       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12492     }
12493
12494     TColStd_IndexedDataMapOfStringString aDict;
12495     aView->StatisticInformation (aDict);
12496
12497     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12498
12499     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12500     {
12501       Standard_CString        anArg(theArgVec[anArgIter]);
12502       TCollection_AsciiString aFlag(anArg);
12503       aFlag.LowerCase();
12504       if (aFlag == "fps")
12505       {
12506         theDI << searchInfo (aDict, "FPS") << " ";
12507       }
12508       else if (aFlag == "cpu")
12509       {
12510         theDI << searchInfo (aDict, "CPU FPS") << " ";
12511       }
12512       else if (aFlag == "alllayers")
12513       {
12514         theDI << searchInfo (aDict, "Layers") << " ";
12515       }
12516       else if (aFlag == "layers")
12517       {
12518         theDI << searchInfo (aDict, "Rendered layers") << " ";
12519       }
12520       else if (aFlag == "allstructs")
12521       {
12522         theDI << searchInfo (aDict, "Structs") << " ";
12523       }
12524       else if (aFlag == "structs")
12525       {
12526         theDI << searchInfo (aDict, "Rendered structs") << " ";
12527       }
12528       else if (aFlag == "groups")
12529       {
12530         theDI << searchInfo (aDict, "Rendered groups") << " ";
12531       }
12532       else if (aFlag == "allarrays")
12533       {
12534         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12535       }
12536       else if (aFlag == "fillarrays")
12537       {
12538         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12539       }
12540       else if (aFlag == "linearrays")
12541       {
12542         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12543       }
12544       else if (aFlag == "pointarrays")
12545       {
12546         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12547       }
12548       else if (aFlag == "textarrays")
12549       {
12550         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12551       }
12552       else if (aFlag == "triangles")
12553       {
12554         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12555       }
12556       else if (aFlag == "points")
12557       {
12558         theDI << searchInfo (aDict, "Rendered points") << " ";
12559       }
12560       else if (aFlag == "geommem")
12561       {
12562         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12563       }
12564       else if (aFlag == "texturemem")
12565       {
12566         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12567       }
12568       else if (aFlag == "framemem")
12569       {
12570         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12571       }
12572       else if (aFlag == "elapsedframe")
12573       {
12574         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12575       }
12576       else if (aFlag == "cpuframe_average")
12577       {
12578         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12579       }
12580       else if (aFlag == "cpupicking_average")
12581       {
12582         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12583       }
12584       else if (aFlag == "cpuculling_average")
12585       {
12586         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12587       }
12588       else if (aFlag == "cpudyn_average")
12589       {
12590         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12591       }
12592       else if (aFlag == "cpuframe_max")
12593       {
12594         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12595       }
12596       else if (aFlag == "cpupicking_max")
12597       {
12598         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12599       }
12600       else if (aFlag == "cpuculling_max")
12601       {
12602         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12603       }
12604       else if (aFlag == "cpudyn_max")
12605       {
12606         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12607       }
12608     }
12609   }
12610   else
12611   {
12612     if (toRedraw)
12613     {
12614       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12615       aView->Redraw();
12616       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12617     }
12618     theDI << "Statistic info:\n" << aView->StatisticInformation();
12619   }
12620   return 0;
12621 }
12622
12623 //=======================================================================
12624 //function : VXRotate
12625 //purpose  :
12626 //=======================================================================
12627 static Standard_Integer VXRotate (Draw_Interpretor& di,
12628                                    Standard_Integer argc,
12629                                    const char ** argv)
12630 {
12631   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12632   if (aContext.IsNull())
12633   {
12634     di << argv[0] << "ERROR : use 'vinit' command before \n";
12635     return 1;
12636   }
12637
12638   if (argc != 3)
12639   {
12640     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12641     return 1;
12642   }
12643
12644   TCollection_AsciiString aName (argv[1]);
12645   Standard_Real anAngle = Draw::Atof (argv[2]);
12646
12647   // find object
12648   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12649   Handle(AIS_InteractiveObject) anIObj;
12650   if (!aMap.Find2 (aName, anIObj))
12651   {
12652     di << "Use 'vdisplay' before\n";
12653     return 1;
12654   }
12655
12656   gp_Trsf aTransform;
12657   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12658   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12659
12660   aContext->SetLocation (anIObj, aTransform);
12661   aContext->UpdateCurrentViewer();
12662   return 0;
12663 }
12664
12665 //===============================================================================================
12666 //function : VManipulator
12667 //purpose  :
12668 //===============================================================================================
12669 static int VManipulator (Draw_Interpretor& theDi,
12670                          Standard_Integer  theArgsNb,
12671                          const char**      theArgVec)
12672 {
12673   Handle(V3d_View)   aCurrentView   = ViewerTest::CurrentView();
12674   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12675   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12676   if (aCurrentView.IsNull()
12677    || aViewer.IsNull())
12678   {
12679     std::cerr << "No active viewer!\n";
12680     return 1;
12681   }
12682
12683   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12684   Standard_Integer anArgIter = 1;
12685   for (; anArgIter < theArgsNb; ++anArgIter)
12686   {
12687     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12688   }
12689
12690   ViewerTest_CmdParser aCmd;
12691   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12692   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12693   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12694   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12695   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12696   aCmd.AddOption ("view",           "... {active | [view name]} - define view in which manipulator will be displayed, 'all' by default");
12697   aCmd.AddOption ("detach",         "...       - detach manipulator");
12698
12699   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12700   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12701   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12702
12703   aCmd.AddOption ("move",   "... x y z - move object");
12704   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
12705   aCmd.AddOption ("scale",  "... factor - scale object");
12706
12707   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12708   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12709   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12710   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12711   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12712   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12713   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
12714   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12715   aCmd.AddOption ("size",              "... size - set size of manipulator");
12716   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12717
12718   aCmd.Parse (theArgsNb, theArgVec);
12719
12720   if (aCmd.HasOption ("help"))
12721   {
12722     theDi.PrintHelp (theArgVec[0]);
12723     return 0;
12724   }
12725
12726   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12727
12728   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
12729
12730   if (aName.IsEmpty())
12731   {
12732     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12733     return 1;
12734   }
12735
12736   // ----------------------------------
12737   // detach existing manipulator object
12738   // ----------------------------------
12739
12740   if (aCmd.HasOption ("detach"))
12741   {
12742     if (!aMapAIS.IsBound2 (aName))
12743     {
12744       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12745       return 1;
12746     }
12747
12748     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12749     if (aManipulator.IsNull())
12750     {
12751       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12752       return 1;
12753     }
12754
12755     aManipulator->Detach();
12756     aMapAIS.UnBind2 (aName);
12757     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12758
12759     return 0;
12760   }
12761
12762   // -----------------------------------------------
12763   // find or create manipulator if it does not exist
12764   // -----------------------------------------------
12765
12766   Handle(AIS_Manipulator) aManipulator;
12767   if (!aMapAIS.IsBound2 (aName))
12768   {
12769     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12770
12771     aManipulator = new AIS_Manipulator();
12772     aManipulator->SetModeActivationOnDetection (true);
12773     aMapAIS.Bind (aManipulator, aName);
12774   }
12775   else
12776   {
12777     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12778     if (aManipulator.IsNull())
12779     {
12780       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12781       return 1;
12782     }
12783   }
12784
12785   // -----------------------------------------
12786   // change properties of manipulator instance
12787   // -----------------------------------------
12788
12789   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12790   {
12791     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12792   }
12793   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12794   {
12795     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12796   }
12797   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12798   {
12799     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12800   }
12801   if (aCmd.HasOption("followDragging", 1, Standard_True))
12802   {
12803     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12804   }
12805   if (aCmd.HasOption ("gap", 1, Standard_True))
12806   {
12807     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12808   }
12809   if (aCmd.HasOption ("part", 3, Standard_True))
12810   {
12811     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12812     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12813     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12814     if (aMode < 1 || aMode > 4)
12815     {
12816       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12817       return 1;
12818     }
12819
12820     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12821   }
12822   if (aCmd.HasOption("parts", 2, Standard_True))
12823   {
12824     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
12825     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
12826     if (aMode < 1 || aMode > 4)
12827     {
12828       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12829       return 1;
12830     }
12831
12832     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
12833   }
12834   if (aCmd.HasOption ("pos", 3, Standard_True))
12835   {
12836     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12837     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12838     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12839
12840     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12841   }
12842   if (aCmd.HasOption ("size", 1, Standard_True))
12843   {
12844     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12845   }
12846   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12847   {
12848     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12849
12850     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12851     {
12852       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12853       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12854     }
12855   }
12856
12857   // ---------------------------------------------------
12858   // attach, detach or access manipulator from an object
12859   // ---------------------------------------------------
12860
12861   if (aCmd.HasOption ("attach"))
12862   {
12863     // Find an object and attach manipulator to it
12864     if (!aCmd.HasOption ("attach", 1, Standard_True))
12865     {
12866       return 1;
12867     }
12868
12869     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12870     Handle(AIS_InteractiveObject) anObject;
12871     if (!aMapAIS.Find2 (anObjName, anObject))
12872     {
12873       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12874       return 1;
12875     }
12876
12877     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (aMapAIS);
12878          anIter.More(); anIter.Next())
12879     {
12880       Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (anIter.Key1());
12881       if (!aManip.IsNull()
12882        && aManip->IsAttached()
12883        && aManip->Object() == anObject)
12884       {
12885         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12886         return 1;
12887       }
12888     }
12889
12890     AIS_Manipulator::OptionsForAttach anOptions;
12891     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12892     {
12893       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12894     }
12895     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12896     {
12897       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12898     }
12899     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12900     {
12901       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12902     }
12903
12904     aManipulator->Attach (anObject, anOptions);
12905
12906     // Check view option
12907     if (aCmd.HasOption ("view"))
12908     {
12909       if (!aCmd.HasOption ("view", 1, Standard_True))
12910       {
12911         return 1;
12912       }
12913       TCollection_AsciiString aViewString (aCmd.Arg ("view", 0).c_str());
12914       Handle(V3d_View) aView;
12915       if (aViewString.IsEqual ("active"))
12916       {
12917         aView = ViewerTest::CurrentView();
12918       }
12919       else // Check view name
12920       {
12921         ViewerTest_Names aViewNames (aViewString);
12922         if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
12923         {
12924           std::cerr << theArgVec[0] << " error: wrong view name '" << aViewString << "'\n";
12925           return 1;
12926         }
12927         aView = ViewerTest_myViews.Find1 (aViewNames.GetViewName());
12928         if (aView.IsNull())
12929         {
12930           std::cerr << theArgVec[0] << " error: cannot find view with name '" << aViewString << "'\n";
12931           return 1;
12932         }
12933       }
12934       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
12935         anIter (ViewerTest_myViews); anIter.More(); anIter.Next())
12936       {
12937         ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, anIter.Value(), Standard_False);
12938       }
12939       ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, aView, Standard_True);
12940     }
12941   }
12942
12943   // --------------------------------------
12944   // apply transformation using manipulator
12945   // --------------------------------------
12946
12947   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12948   {
12949     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12950   }
12951   if (aCmd.HasOption ("transform", 2, Standard_True))
12952   {
12953     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
12954   }
12955   if (aCmd.HasOption ("stopTransform"))
12956   {
12957     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
12958
12959     aManipulator->StopTransform (toApply);
12960   }
12961
12962   gp_Trsf aT;
12963   if (aCmd.HasOption ("move", 3, Standard_True))
12964   {
12965     aT.SetTranslationPart (aCmd.ArgVec ("move"));
12966   }
12967   if (aCmd.HasOption ("rotate", 7, Standard_True))
12968   {
12969     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
12970   }
12971   if (aCmd.HasOption ("scale", 1))
12972   {
12973     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
12974   }
12975
12976   if (aT.Form() != gp_Identity)
12977   {
12978     aManipulator->Transform (aT);
12979   }
12980
12981   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
12982
12983   return 0;
12984 }
12985
12986 //===============================================================================================
12987 //function : VSelectionProperties
12988 //purpose  :
12989 //===============================================================================================
12990 static int VSelectionProperties (Draw_Interpretor& theDi,
12991                                  Standard_Integer  theArgsNb,
12992                                  const char**      theArgVec)
12993 {
12994   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12995   if (aCtx.IsNull())
12996   {
12997     std::cerr << "No active viewer!\n";
12998     return 1;
12999   }
13000
13001   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
13002   {
13003     // handle obsolete alias
13004     bool toEnable = true;
13005     if (theArgsNb < 2)
13006     {
13007       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
13008       return 0;
13009     }
13010     else if (theArgsNb != 2
13011          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
13012     {
13013       std::cout << "Syntax error: wrong number of parameters.";
13014       return 1;
13015     }
13016     if (toEnable != aCtx->ToHilightSelected())
13017     {
13018       aCtx->ClearDetected();
13019       aCtx->SetToHilightSelected (toEnable);
13020     }
13021     return 0;
13022   }
13023
13024   Standard_Boolean toPrint  = theArgsNb == 1;
13025   Standard_Boolean toRedraw = Standard_False;
13026   Standard_Integer anArgIter = 1;
13027   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
13028   if (anArgIter < theArgsNb)
13029   {
13030     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
13031     anArgFirst.LowerCase();
13032     ++anArgIter;
13033     if (anArgFirst == "dynhighlight"
13034      || anArgFirst == "dynhilight"
13035      || anArgFirst == "dynamichighlight"
13036      || anArgFirst == "dynamichilight")
13037     {
13038       aType = Prs3d_TypeOfHighlight_Dynamic;
13039     }
13040     else if (anArgFirst == "localdynhighlight"
13041           || anArgFirst == "localdynhilight"
13042           || anArgFirst == "localdynamichighlight"
13043           || anArgFirst == "localdynamichilight")
13044     {
13045       aType = Prs3d_TypeOfHighlight_LocalDynamic;
13046     }
13047     else if (anArgFirst == "selhighlight"
13048           || anArgFirst == "selhilight"
13049           || anArgFirst == "selectedhighlight"
13050           || anArgFirst == "selectedhilight")
13051     {
13052       aType = Prs3d_TypeOfHighlight_Selected;
13053     }
13054     else if (anArgFirst == "localselhighlight"
13055           || anArgFirst == "localselhilight"
13056           || anArgFirst == "localselectedhighlight"
13057           || anArgFirst == "localselectedhilight")
13058     {
13059       aType = Prs3d_TypeOfHighlight_LocalSelected;
13060     }
13061     else
13062     {
13063       --anArgIter;
13064     }
13065   }
13066   for (; anArgIter < theArgsNb; ++anArgIter)
13067   {
13068     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13069     anArg.LowerCase();
13070     if (anArg == "-help")
13071     {
13072       theDi.PrintHelp (theArgVec[0]);
13073       return 0;
13074     }
13075     else if (anArg == "-print")
13076     {
13077       toPrint = Standard_True;
13078     }
13079     else if (anArg == "-autoactivate")
13080     {
13081       Standard_Boolean toEnable = Standard_True;
13082       if (anArgIter + 1 < theArgsNb
13083        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13084       {
13085         ++anArgIter;
13086       }
13087       aCtx->SetAutoActivateSelection (toEnable);
13088     }
13089     else if (anArg == "-automatichighlight"
13090           || anArg == "-automatichilight"
13091           || anArg == "-autohighlight"
13092           || anArg == "-autohilight")
13093     {
13094       Standard_Boolean toEnable = Standard_True;
13095       if (anArgIter + 1 < theArgsNb
13096        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13097       {
13098         ++anArgIter;
13099       }
13100       aCtx->ClearSelected (false);
13101       aCtx->ClearDetected();
13102       aCtx->SetAutomaticHilight (toEnable);
13103       toRedraw = true;
13104     }
13105     else if (anArg == "-highlightselected"
13106           || anArg == "-hilightselected")
13107     {
13108       Standard_Boolean toEnable = Standard_True;
13109       if (anArgIter + 1 < theArgsNb
13110        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13111       {
13112         ++anArgIter;
13113       }
13114       aCtx->ClearDetected();
13115       aCtx->SetToHilightSelected (toEnable);
13116       toRedraw = true;
13117     }
13118     else if (anArg == "-pickstrategy"
13119           || anArg == "-pickingstrategy")
13120     {
13121       if (++anArgIter >= theArgsNb)
13122       {
13123         std::cout << "Syntax error: type of highlighting is undefined\n";
13124         return 1;
13125       }
13126
13127       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13128       TCollection_AsciiString aVal (theArgVec[anArgIter]);
13129       aVal.LowerCase();
13130       if (aVal == "first"
13131        || aVal == "firstaccepted"
13132        || aVal == "firstacceptable")
13133       {
13134         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13135       }
13136       else if (aVal == "topmost"
13137             || aVal == "onlyTopmost")
13138       {
13139         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
13140       }
13141       else
13142       {
13143         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
13144         return 1;
13145       }
13146
13147       aCtx->SetPickingStrategy (aStrategy);
13148     }
13149     else if (anArg == "-pixtol"
13150           && anArgIter + 1 < theArgsNb)
13151     {
13152       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
13153     }
13154     else if ((anArg == "-mode"
13155            || anArg == "-dispmode")
13156           && anArgIter + 1 < theArgsNb)
13157     {
13158       if (aType == Prs3d_TypeOfHighlight_None)
13159       {
13160         std::cout << "Syntax error: type of highlighting is undefined\n";
13161         return 1;
13162       }
13163
13164       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
13165       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13166       aStyle->SetDisplayMode (aDispMode);
13167       toRedraw = Standard_True;
13168     }
13169     else if (anArg == "-layer"
13170           && anArgIter + 1 < theArgsNb)
13171     {
13172       if (aType == Prs3d_TypeOfHighlight_None)
13173       {
13174         std::cout << "Syntax error: type of highlighting is undefined\n";
13175         return 1;
13176       }
13177
13178       ++anArgIter;
13179       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
13180       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
13181       {
13182         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
13183         return 1;
13184       }
13185
13186       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13187       aStyle->SetZLayer (aNewLayer);
13188       toRedraw = Standard_True;
13189     }
13190     else if (anArg == "-hicolor"
13191           || anArg == "-selcolor"
13192           || anArg == "-color")
13193     {
13194       if (anArg.StartsWith ("-hi"))
13195       {
13196         aType = Prs3d_TypeOfHighlight_Dynamic;
13197       }
13198       else if (anArg.StartsWith ("-sel"))
13199       {
13200         aType = Prs3d_TypeOfHighlight_Selected;
13201       }
13202       else if (aType == Prs3d_TypeOfHighlight_None)
13203       {
13204         std::cout << "Syntax error: type of highlighting is undefined\n";
13205         return 1;
13206       }
13207
13208       Quantity_Color aColor;
13209       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
13210                                                            theArgVec + anArgIter + 1,
13211                                                            aColor);
13212       if (aNbParsed == 0)
13213       {
13214         std::cout << "Syntax error: need more arguments.\n";
13215         return 1;
13216       }
13217       anArgIter += aNbParsed;
13218
13219       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13220       aStyle->SetColor (aColor);
13221       toRedraw = Standard_True;
13222     }
13223     else if ((anArg == "-transp"
13224            || anArg == "-transparency"
13225            || anArg == "-hitransp"
13226            || anArg == "-seltransp"
13227            || anArg == "-hitransplocal"
13228            || anArg == "-seltransplocal")
13229           && anArgIter + 1 < theArgsNb)
13230     {
13231       if (anArg.StartsWith ("-hi"))
13232       {
13233         aType = Prs3d_TypeOfHighlight_Dynamic;
13234       }
13235       else if (anArg.StartsWith ("-sel"))
13236       {
13237         aType = Prs3d_TypeOfHighlight_Selected;
13238       }
13239       else if (aType == Prs3d_TypeOfHighlight_None)
13240       {
13241         std::cout << "Syntax error: type of highlighting is undefined\n";
13242         return 1;
13243       }
13244
13245       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
13246       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13247       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
13248       toRedraw = Standard_True;
13249     }
13250     else if ((anArg == "-mat"
13251            || anArg == "-material")
13252           && anArgIter + 1 < theArgsNb)
13253     {
13254       if (aType == Prs3d_TypeOfHighlight_None)
13255       {
13256         std::cout << "Syntax error: type of highlighting is undefined\n";
13257         return 1;
13258       }
13259
13260       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13261       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
13262       if (aMatName != Graphic3d_NOM_DEFAULT)
13263       {
13264         ++anArgIter;
13265         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
13266         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
13267         Graphic3d_MaterialAspect aMat (aMatName);
13268         aMat.SetColor (aStyle->Color());
13269         aMat.SetTransparency (aStyle->Transparency());
13270         anAspect->SetFrontMaterial (aMat);
13271         anAspect->SetInteriorColor (aStyle->Color());
13272         aStyle->SetBasicFillAreaAspect (anAspect);
13273       }
13274       else
13275       {
13276         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
13277       }
13278       toRedraw = Standard_True;
13279     }
13280     else
13281     {
13282       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
13283     }
13284   }
13285
13286   if (toPrint)
13287   {
13288     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
13289     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
13290     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
13291     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
13292     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
13293     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
13294     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
13295     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
13296     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
13297     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
13298     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
13299     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
13300     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
13301     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
13302   }
13303
13304   if (aCtx->NbSelected() != 0 && toRedraw)
13305   {
13306     aCtx->HilightSelected (Standard_True);
13307   }
13308
13309   return 0;
13310 }
13311
13312 //===============================================================================================
13313 //function : VDumpSelectionImage
13314 //purpose  :
13315 //===============================================================================================
13316 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
13317                                 Standard_Integer  theArgsNb,
13318                                 const char**      theArgVec)
13319 {
13320   if (theArgsNb < 2)
13321   {
13322     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
13323     return 1;
13324   }
13325
13326   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13327   if (aContext.IsNull())
13328   {
13329     std::cout << "Error: no active view.\n";
13330     return 1;
13331   }
13332
13333   TCollection_AsciiString aFile;
13334   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13335   Image_Format anImgFormat = Image_Format_BGR;
13336   Standard_Integer aPickedIndex = 1;
13337   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13338   {
13339     TCollection_AsciiString aParam (theArgVec[anArgIter]);
13340     aParam.LowerCase();
13341     if (aParam == "-type")
13342     {
13343       if (++anArgIter >= theArgsNb)
13344       {
13345         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
13346         return 1;
13347       }
13348
13349       TCollection_AsciiString aValue (theArgVec[anArgIter]);
13350       aValue.LowerCase();
13351       if (aValue == "depth"
13352        || aValue == "normdepth"
13353        || aValue == "normalizeddepth")
13354       {
13355         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13356         anImgFormat = Image_Format_GrayF;
13357       }
13358       if (aValue == "depthinverted"
13359        || aValue == "normdepthinverted"
13360        || aValue == "normalizeddepthinverted"
13361        || aValue == "inverted")
13362       {
13363         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
13364         anImgFormat = Image_Format_GrayF;
13365       }
13366       else if (aValue == "unnormdepth"
13367             || aValue == "unnormalizeddepth")
13368       {
13369         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
13370         anImgFormat = Image_Format_GrayF;
13371       }
13372       else if (aValue == "objectcolor"
13373             || aValue == "object"
13374             || aValue == "color")
13375       {
13376         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13377       }
13378       else if (aValue == "entitycolor"
13379             || aValue == "entity")
13380       {
13381         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13382       }
13383       else if (aValue == "ownercolor"
13384             || aValue == "owner")
13385       {
13386         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13387       }
13388       else if (aValue == "selectionmodecolor"
13389             || aValue == "selectionmode"
13390             || aValue == "selmodecolor"
13391             || aValue == "selmode")
13392       {
13393         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13394       }
13395     }
13396     else if (aParam == "-picked"
13397           || aParam == "-pickeddepth"
13398           || aParam == "-pickedindex")
13399     {
13400       if (++anArgIter >= theArgsNb)
13401       {
13402         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13403         return 1;
13404       }
13405
13406       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13407     }
13408     else if (aFile.IsEmpty())
13409     {
13410       aFile = theArgVec[anArgIter];
13411     }
13412     else
13413     {
13414       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13415       return 1;
13416     }
13417   }
13418   if (aFile.IsEmpty())
13419   {
13420     std::cout << "Syntax error: image file name is missing.\n";
13421     return 1;
13422   }
13423
13424   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13425   Standard_Integer aWidth = 0, aHeight = 0;
13426   aView->Window()->Size (aWidth, aHeight);
13427
13428   Image_AlienPixMap aPixMap;
13429   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13430   {
13431     std::cout << "Error: can't allocate image.\n";
13432     return 1;
13433   }
13434   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13435   {
13436     std::cout << "Error: can't generate selection image.\n";
13437     return 1;
13438   }
13439   if (!aPixMap.Save (aFile))
13440   {
13441     std::cout << "Error: can't save selection image.\n";
13442     return 0;
13443   }
13444   return 0;
13445 }
13446
13447 //===============================================================================================
13448 //function : VViewCube
13449 //purpose  :
13450 //===============================================================================================
13451 static int VViewCube (Draw_Interpretor& ,
13452                       Standard_Integer  theNbArgs,
13453                       const char**      theArgVec)
13454 {
13455   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13456   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13457   if (aContext.IsNull() || aView.IsNull())
13458   {
13459     std::cout << "Error: no active view.\n";
13460     return 1;
13461   }
13462   else if (theNbArgs < 2)
13463   {
13464     std::cout << "Syntax error: wrong number arguments\n";
13465     return 1;
13466   }
13467
13468   Handle(AIS_ViewCube) aViewCube;
13469   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
13470   Quantity_Color aColorRgb;
13471   TCollection_AsciiString aName;
13472   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
13473   {
13474     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13475     anArg.LowerCase();
13476     if (anUpdateTool.parseRedrawMode (anArg))
13477     {
13478       //
13479     }
13480     else if (aViewCube.IsNull())
13481     {
13482       aName = theArgVec[anArgIter];
13483       if (aName.StartsWith ("-"))
13484       {
13485         std::cout << "Syntax error: object name should be specified.\n";
13486         return 1;
13487       }
13488       Handle(AIS_InteractiveObject) aPrs;
13489       GetMapOfAIS().Find2 (aName, aPrs);
13490       aViewCube = Handle(AIS_ViewCube)::DownCast (aPrs);
13491       if (aViewCube.IsNull())
13492       {
13493         aViewCube = new AIS_ViewCube();
13494         aViewCube->SetBoxColor (Quantity_NOC_GRAY50);
13495         aViewCube->SetViewAnimation (ViewerTest::CurrentEventManager()->ViewAnimation());
13496         aViewCube->SetFixedAnimationLoop (false);
13497       }
13498     }
13499     else if (anArg == "-reset")
13500     {
13501       aViewCube->ResetStyles();
13502     }
13503     else if (anArg == "-color"
13504           || anArg == "-boxcolor"
13505           || anArg == "-boxsidecolor"
13506           || anArg == "-sidecolor"
13507           || anArg == "-boxedgecolor"
13508           || anArg == "-edgecolor"
13509           || anArg == "-boxcornercolor"
13510           || anArg == "-cornercolor"
13511           || anArg == "-innercolor"
13512           || anArg == "-textcolor")
13513     {
13514       Standard_Integer aNbParsed = ViewerTest::ParseColor (theNbArgs - anArgIter - 1,
13515                                                            theArgVec + anArgIter + 1,
13516                                                            aColorRgb);
13517       if (aNbParsed == 0)
13518       {
13519         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
13520         return 1;
13521       }
13522       anArgIter += aNbParsed;
13523       if (anArg == "-boxcolor")
13524       {
13525         aViewCube->SetBoxColor (aColorRgb);
13526       }
13527       else if (anArg == "-boxsidecolor"
13528             || anArg == "-sidecolor")
13529       {
13530         aViewCube->BoxSideStyle()->SetColor (aColorRgb);
13531         aViewCube->SynchronizeAspects();
13532       }
13533       else if (anArg == "-boxedgecolor"
13534             || anArg == "-edgecolor")
13535       {
13536         aViewCube->BoxEdgeStyle()->SetColor (aColorRgb);
13537         aViewCube->SynchronizeAspects();
13538       }
13539       else if (anArg == "-boxcornercolor"
13540             || anArg == "-cornercolor")
13541       {
13542         aViewCube->BoxCornerStyle()->SetColor (aColorRgb);
13543         aViewCube->SynchronizeAspects();
13544       }
13545       else if (anArg == "-innercolor")
13546       {
13547         aViewCube->SetInnerColor (aColorRgb);
13548       }
13549       else if (anArg == "-textcolor")
13550       {
13551         aViewCube->SetTextColor (aColorRgb);
13552       }
13553       else
13554       {
13555         aViewCube->SetColor (aColorRgb);
13556       }
13557     }
13558     else if (anArgIter + 1 < theNbArgs
13559           && (anArg == "-transparency"
13560            || anArg == "-boxtransparency"))
13561     {
13562       const Standard_Real aValue = Draw::Atof (theArgVec[++anArgIter]);
13563       if (aValue < 0.0 || aValue > 1.0)
13564       {
13565         std::cout << "Syntax error: invalid transparency value " << theArgVec[anArgIter] << "\n";
13566         return 1;
13567       }
13568
13569       if (anArg == "-boxtransparency")
13570       {
13571         aViewCube->SetBoxTransparency (aValue);
13572       }
13573       else
13574       {
13575         aViewCube->SetTransparency (aValue);
13576       }
13577     }
13578     else if (anArg == "-axes"
13579           || anArg == "-edges"
13580           || anArg == "-vertices"
13581           || anArg == "-vertexes"
13582           || anArg == "-fixedanimation")
13583     {
13584       bool toShow = true;
13585       if (anArgIter + 1 < theNbArgs
13586        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toShow))
13587       {
13588         ++anArgIter;
13589       }
13590       if (anArg == "-fixedanimation")
13591       {
13592         aViewCube->SetFixedAnimationLoop (toShow);
13593       }
13594       else if (anArg == "-axes")
13595       {
13596         aViewCube->SetDrawAxes (toShow);
13597       }
13598       else if (anArg == "-edges")
13599       {
13600         aViewCube->SetDrawEdges (toShow);
13601       }
13602       else
13603       {
13604         aViewCube->SetDrawVertices (toShow);
13605       }
13606     }
13607     else if (anArg == "-yup"
13608           || anArg == "-zup")
13609     {
13610       bool isOn = true;
13611       if (anArgIter + 1 < theNbArgs
13612        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isOn))
13613       {
13614         ++anArgIter;
13615       }
13616       if (anArg == "-yup")
13617       {
13618         aViewCube->SetYup (isOn);
13619       }
13620       else
13621       {
13622         aViewCube->SetYup (!isOn);
13623       }
13624     }
13625     else if (anArgIter + 1 < theNbArgs
13626           && anArg == "-font")
13627     {
13628       aViewCube->SetFont (theArgVec[++anArgIter]);
13629     }
13630     else if (anArgIter + 1 < theNbArgs
13631           && anArg == "-fontheight")
13632     {
13633       aViewCube->SetFontHeight (Draw::Atof (theArgVec[++anArgIter]));
13634     }
13635     else if (anArgIter + 1 < theNbArgs
13636           && (anArg == "-size"
13637            || anArg == "-boxsize"))
13638     {
13639       aViewCube->SetSize (Draw::Atof (theArgVec[++anArgIter]),
13640                           anArg != "-boxsize");
13641     }
13642     else if (anArgIter + 1 < theNbArgs
13643           && (anArg == "-boxfacet"
13644            || anArg == "-boxfacetextension"
13645            || anArg == "-facetextension"
13646            || anArg == "-extension"))
13647     {
13648       aViewCube->SetBoxFacetExtension (Draw::Atof (theArgVec[++anArgIter]));
13649     }
13650     else if (anArgIter + 1 < theNbArgs
13651           && (anArg == "-boxedgegap"
13652            || anArg == "-edgegap"))
13653     {
13654       aViewCube->SetBoxEdgeGap (Draw::Atof (theArgVec[++anArgIter]));
13655     }
13656     else if (anArgIter + 1 < theNbArgs
13657           && (anArg == "-boxedgeminsize"
13658            || anArg == "-edgeminsize"))
13659     {
13660       aViewCube->SetBoxEdgeMinSize (Draw::Atof (theArgVec[++anArgIter]));
13661     }
13662     else if (anArgIter + 1 < theNbArgs
13663           && (anArg == "-boxcornerminsize"
13664            || anArg == "-cornerminsize"))
13665     {
13666       aViewCube->SetBoxCornerMinSize (Draw::Atof (theArgVec[++anArgIter]));
13667     }
13668     else if (anArgIter + 1 < theNbArgs
13669           && anArg == "-axespadding")
13670     {
13671       aViewCube->SetAxesPadding (Draw::Atof (theArgVec[++anArgIter]));
13672     }
13673     else if (anArgIter + 1 < theNbArgs
13674           && anArg == "-roundradius")
13675     {
13676       aViewCube->SetRoundRadius (Draw::Atof (theArgVec[++anArgIter]));
13677     }
13678     else if (anArgIter + 1 < theNbArgs
13679           && anArg == "-duration")
13680     {
13681       aViewCube->SetDuration (Draw::Atof (theArgVec[++anArgIter]));
13682     }
13683     else
13684     {
13685       std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
13686       return 1;
13687     }
13688   }
13689   if (aViewCube.IsNull())
13690   {
13691     std::cout << "Syntax error: wrong number of arguments\n";
13692     return 1;
13693   }
13694
13695   ViewerTest::Display (aName, aViewCube, false);
13696   return 0;
13697 }
13698
13699 //=======================================================================
13700 //function : ViewerCommands
13701 //purpose  :
13702 //=======================================================================
13703
13704 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13705 {
13706
13707   const char *group = "ZeViewer";
13708   theCommands.Add("vinit",
13709           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13710     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13711   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13712     "\n\t\t:     [-display displayName]"
13713   #endif
13714     "\n\t\t: Creates new View window with specified name viewName."
13715     "\n\t\t: By default the new view is created in the viewer and in"
13716     "\n\t\t: graphic driver shared with active view."
13717     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13718     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13719     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13720 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13721     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13722     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13723 #endif
13724     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13725     "\n\t\t:  -width, -height width and heigth of window respectively."
13726     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13727     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13728     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13729     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13730     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13731     __FILE__,VInit,group);
13732   theCommands.Add("vclose" ,
13733     "[view_id [keep_context=0|1]]\n"
13734     "or vclose ALL - to remove all created views\n"
13735     " - removes view(viewer window) defined by its view_id.\n"
13736     " - keep_context: by default 0; if 1 and the last view is deleted"
13737     " the current context is not removed.",
13738     __FILE__,VClose,group);
13739   theCommands.Add("vactivate" ,
13740     "vactivate view_id [-noUpdate]"
13741     " - activates view(viewer window) defined by its view_id",
13742     __FILE__,VActivate,group);
13743   theCommands.Add("vviewlist",
13744     "vviewlist [format={tree, long}]"
13745     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13746     " - format: format of result output, if tree the output is a tree view;"
13747     "otherwise it's a list of full view names. By default format = tree",
13748     __FILE__,VViewList,group);
13749   theCommands.Add("vhelp" ,
13750     "vhelp            : display help on the viewer commands",
13751     __FILE__,VHelp,group);
13752   theCommands.Add("vviewproj",
13753           "vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]"
13754     "\n\t\t:         [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]"
13755     "\n\t\t: Setup view direction"
13756     "\n\t\t:   -Yup      use Y-up convention instead of Zup (which is default)."
13757     "\n\t\t:   +-X+-Y+-Z define direction as combination of DX, DY and DZ;"
13758     "\n\t\t:             for example '+Z' will show front of the model,"
13759     "\n\t\t:             '-X-Y+Z' will define left axonometrical view."
13760     "\n\t\t:   -frame    define camera Up and Right directions (regardless Up convention);"
13761     "\n\t\t:             for example '+X+Z' will show front of the model with Z-up."
13762     __FILE__,VViewProj,group);
13763   theCommands.Add("vtop" ,
13764     "vtop or <T>      : Top view. Orientation +X+Y" ,
13765     __FILE__,VViewProj,group);
13766   theCommands.Add("vbottom" ,
13767     "vbottom          : Bottom view. Orientation +X-Y" ,
13768     __FILE__,VViewProj,group);
13769   theCommands.Add("vleft" ,
13770     "vleft            : Left view. Orientation -Y+Z" ,
13771     __FILE__,VViewProj,group);
13772   theCommands.Add("vright" ,
13773     "vright           : Right view. Orientation +Y+Z" ,
13774     __FILE__,VViewProj,group);
13775   theCommands.Add("vaxo" ,
13776     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13777     __FILE__,VViewProj,group);
13778   theCommands.Add("vfront" ,
13779     "vfront           : Front view. Orientation +X+Z" ,
13780     __FILE__,VViewProj,group);
13781   theCommands.Add("vback" ,
13782     "vback            : Back view. Orientation -X+Z" ,
13783     __FILE__,VViewProj,group);
13784   theCommands.Add("vpick" ,
13785     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13786     VPick,group);
13787   theCommands.Add("vfit",
13788     "vfit or <F> [-selected] [-noupdate]"
13789     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13790     __FILE__,VFit,group);
13791   theCommands.Add ("vfitarea",
13792     "vfitarea x1 y1 x2 y2"
13793     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13794     "\n\t\t: Fit view to show area located between two points"
13795     "\n\t\t: given in world 2D or 3D corrdinates.",
13796     __FILE__, VFitArea, group);
13797   theCommands.Add ("vzfit", "vzfit [scale]\n"
13798     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13799     "   \"scale\" - specifies factor to scale computed z range.\n",
13800     __FILE__, VZFit, group);
13801   theCommands.Add("vrepaint",
13802             "vrepaint [-immediate] [-continuous FPS]"
13803     "\n\t\t: force redraw of active View"
13804     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13805     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13806     "\n\t\t:                0 means no continuous rendering,"
13807     "\n\t\t:               -1 means non-stop redraws,"
13808     "\n\t\t:               >0 specifies target framerate,",
13809     __FILE__,VRepaint,group);
13810   theCommands.Add("vclear",
13811     "vclear          : vclear"
13812     "\n\t\t: remove all the object from the viewer",
13813     __FILE__,VClear,group);
13814   theCommands.Add (
13815     "vbackground",
13816     "Changes background or some background settings.\n"
13817     "\n"
13818     "Usage:\n"
13819     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13820     "  vbackground -imageMode FillType\n"
13821     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13822     "  vbackground -gradientMode FillMethod\n"
13823     "  vbackground -cubemap CubemapFile1 [CubeMapFiles2-5] [-order TilesIndexes1-6] [-invertedz]\n"
13824     "  vbackground -color Color\n"
13825     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13826     "  vbackground -default -color Color\n"
13827     "  vbackground -help\n"
13828     "\n"
13829     "Options:\n"
13830     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13831     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13832     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13833     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13834     "  -cubemap      (-cmap, -cm):                         sets environmet cubemap as background\n"
13835     "  -invertedz    (-invz, -iz):                         sets inversion of Z axis for background cubemap rendering\n"
13836     "  -order        (-o):                                 defines order of tiles in one image cubemap\n"
13837     "                                                      (has no effect in case of multi image cubemaps)\n"
13838     "  -color        (-col):                               sets background color\n"
13839     "  -default      (-def):                               sets background default gradient or color\n"
13840     "  -help         (-h):                                 outputs short help message\n"
13841     "\n"
13842     "Arguments:\n"
13843     "  Color:        Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13844     "                                  or reals within the range [0.0, 1.0]\n"
13845     "                ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13846     "                #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13847     "  FillMethod:   one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13848     "CORNER4\n"
13849     "  FillType:     one of CENTERED, TILED, STRETCH, NONE\n"
13850     "  ImageFile:    a name of the file with the image used as a background\n"
13851     "  CubemapFilei: a name of the file with one image packed cubemap or names of separate files with every cubemap side\n"
13852     "  TileIndexi:   a cubemap side index in range [0, 5] for i tile of one image packed cubemap\n",
13853     __FILE__,
13854     vbackground,
13855     group);
13856   theCommands.Add ("vsetbg",
13857                    "Loads image as background."
13858                    "\n\t\t: vsetbg ImageFile [FillType]"
13859                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13860                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13861                    __FILE__,
13862                    vbackground,
13863                    group);
13864   theCommands.Add ("vsetbgmode",
13865                    "Changes background image fill type."
13866                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13867                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13868                    __FILE__,
13869                    vbackground,
13870                    group);
13871   theCommands.Add ("vsetgradientbg",
13872                    "Mounts gradient background."
13873                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13874                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13875                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13876                    __FILE__,
13877                    vbackground,
13878                    group);
13879   theCommands.Add ("vsetgrbgmode",
13880                    "Changes gradient background fill method."
13881                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13882                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13883                    __FILE__,
13884                    vbackground,
13885                    group);
13886   theCommands.Add ("vsetcolorbg",
13887                    "Sets background color."
13888                    "\n\t\t: vsetcolorbg [-color] Color."
13889                    "\n\t\t: Alias for 'vbackground -color Color'.",
13890                    __FILE__,
13891                    vbackground,
13892                    group);
13893   theCommands.Add ("vsetdefaultbg",
13894                    "Sets default viewer background fill color (flat/gradient)."
13895                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13896                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13897                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13898                    "\n\t\t: vsetdefaultbg [-color] Color"
13899                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13900                    __FILE__,
13901                    vbackground,
13902                    group);
13903   theCommands.Add("vscale",
13904     "vscale          : vscale X Y Z",
13905     __FILE__,VScale,group);
13906   theCommands.Add("vzbufftrihedron",
13907             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13908     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13909     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13910     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13911     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13912     "\n\t\t: Displays a trihedron",
13913     __FILE__,VZBuffTrihedron,group);
13914   theCommands.Add("vrotate",
13915     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13916     "\n                : Option -mouseStart starts rotation according to the mouse position"
13917     "\n                : Option -mouseMove continues rotation with angle computed"
13918     "\n                : from last and new mouse position."
13919     "\n                : vrotate AX AY AZ [X Y Z]",
13920     __FILE__,VRotate,group);
13921   theCommands.Add("vzoom",
13922     "vzoom           : vzoom coef",
13923     __FILE__,VZoom,group);
13924   theCommands.Add("vpan",
13925     "vpan            : vpan dx dy",
13926     __FILE__,VPan,group);
13927   theCommands.Add("vcolorscale",
13928     "vcolorscale name [-noupdate|-update] [-demo]"
13929     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13930     "\n\t\t:       [-font HeightFont=20]"
13931     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13932     "\n\t\t:       [-smoothTransition {on|off}=off]"
13933     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13934     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13935     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13936     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13937     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13938     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13939     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13940     "\n\t\t:       [-xy Left=0 Bottom=0]"
13941     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13942     "\n\t\t:  -colors   - set colors for all intervals"
13943     "\n\t\t:  -color    - set color for specific interval"
13944     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
13945     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
13946     "\n\t\t:              at border means the value inbetween neighbor intervals,"
13947     "\n\t\t:              at center means the center value within current interval"
13948     "\n\t\t:  -labels   - set labels for all intervals"
13949     "\n\t\t:  -freeLabels - same as -labels but does not require"
13950     "\n\t\t:              matching the number of intervals"
13951     "\n\t\t:  -label    - set label for specific interval"
13952     "\n\t\t:  -title    - set title"
13953     "\n\t\t:  -reversed - setup smooth color transition between intervals"
13954     "\n\t\t:  -smoothTransition - swap colorscale direction"
13955     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
13956     __FILE__, VColorScale, group);
13957   theCommands.Add("vgraduatedtrihedron",
13958     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
13959     "\t[-namefont Name] [-valuesfont Name]\n"
13960     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
13961     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
13962     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
13963     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
13964     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
13965     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
13966     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
13967     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
13968     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
13969     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
13970     " - Displays or erases graduated trihedron"
13971     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
13972     " - namefont - font of axes names. Default: Arial\n"
13973     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
13974     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
13975     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
13976     " - valuesfont - font of axes values. Default: Arial\n"
13977     " - xcolor, ycolor, zcolor - color of axis and values\n"
13978     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
13979     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
13980     __FILE__,VGraduatedTrihedron,group);
13981   theCommands.Add("vtile" ,
13982             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
13983     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
13984     "\n\t\t:  -totalSize the size of virtual bigger viewport"
13985     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
13986     "\n\t\t:  -lowerLeft tile offset as lower left corner"
13987     "\n\t\t:  -upperLeft tile offset as upper left corner",
13988     __FILE__, VTile, group);
13989   theCommands.Add("vzlayer",
13990               "vzlayer [layerId]"
13991       "\n\t\t:         [-add|-delete|-get|-settings] [-insertBefore AnotherLayer] [-insertAfter AnotherLayer]"
13992       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
13993       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
13994       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv|rayTracing}]"
13995       "\n\t\t: ZLayer list management:"
13996       "\n\t\t:   -add      add new z layer to viewer and print its id"
13997       "\n\t\t:   -insertBefore add new z layer and insert it before existing one"
13998       "\n\t\t:   -insertAfter  add new z layer and insert it after  existing one"
13999       "\n\t\t:   -delete   delete z layer"
14000       "\n\t\t:   -get      print sequence of z layers"
14001       "\n\t\t:   -settings print status of z layer settings"
14002       "\n\t\t:   -disable  disables given setting"
14003       "\n\t\t:   -enable   enables  given setting",
14004     __FILE__,VZLayer,group);
14005   theCommands.Add("vlayerline",
14006     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
14007     __FILE__,VLayerLine,group);
14008   theCommands.Add("vgrid",
14009               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
14010       "\n\t\t:       [-step X Y] [-size DX DY]"
14011       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
14012     __FILE__, VGrid, group);
14013   theCommands.Add ("vpriviledgedplane",
14014     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
14015     "\n\t\t:   Ox, Oy, Oz - plane origin"
14016     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
14017     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
14018     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
14019     __FILE__, VPriviledgedPlane, group);
14020   theCommands.Add ("vconvert",
14021     "vconvert v [Mode={window|view}]"
14022     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
14023     "\n\t\t: vconvert x y z [Mode={window|grid}]"
14024     "\n\t\t:   window - convert to window coordinates, pixels"
14025     "\n\t\t:   view   - convert to view projection plane"
14026     "\n\t\t:   grid   - convert to model coordinates, given on grid"
14027     "\n\t\t:   ray    - convert projection ray to model coordiantes"
14028     "\n\t\t: - vconvert v window : convert view to window;"
14029     "\n\t\t: - vconvert v view   : convert window to view;"
14030     "\n\t\t: - vconvert x y window : convert view to window;"
14031     "\n\t\t: - vconvert x y view : convert window to view;"
14032     "\n\t\t: - vconvert x y : convert window to model;"
14033     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
14034     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
14035     "\n\t\t: - vconvert x y z window : convert model to window;"
14036     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
14037     "\n\t\t: Converts the given coordinates to window/view/model space.",
14038     __FILE__, VConvert, group);
14039   theCommands.Add ("vfps",
14040     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
14041     __FILE__, VFps, group);
14042   theCommands.Add ("vgldebug",
14043             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
14044     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
14045     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
14046     "\n\t\t: Debug context can be requested only on Windows"
14047     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
14048     "\n\t\t:  -sync     - request synchronized debug GL context"
14049     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
14050     "\n\t\t:              which are suppressed by default,"
14051     "\n\t\t:  -glslCode - log GLSL program source code,"
14052     "\n\t\t:              which are suppressed by default,"
14053     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
14054     "\n\t\t:              which are suppressed by default",
14055     __FILE__, VGlDebug, group);
14056   theCommands.Add ("vvbo",
14057     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
14058     __FILE__, VVbo, group);
14059   theCommands.Add ("vstereo",
14060             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
14061     "\n\t\t:         [-anaglyph Filter]"
14062     "\n\t\t: Control stereo output mode. Available modes for -mode:"
14063     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
14064     "\n\t\t:                     requires driver support."
14065     "\n\t\t:                     Should be called BEFORE vinit!"
14066     "\n\t\t:  anaglyph         - Anaglyph glasses"
14067     "\n\t\t:  rowInterlaced    - row-interlaced display"
14068     "\n\t\t:  columnInterlaced - column-interlaced display"
14069     "\n\t\t:  chessBoard       - chess-board output"
14070     "\n\t\t:  sideBySide       - horizontal pair"
14071     "\n\t\t:  overUnder        - vertical   pair"
14072     "\n\t\t: Available Anaglyph filters for -anaglyph:"
14073     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
14074     "\n\t\t:  greenMagentaSimple",
14075     __FILE__, VStereo, group);
14076   theCommands.Add ("vcaps",
14077             "vcaps [-sRGB {0|1}] [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
14078     "\n\t\t:       [-compatibleProfile {0|1}]"
14079     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
14080     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
14081     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
14082     "\n\t\t:       [-noExtensions {0|1}] [-maxVersion Major Minor]"
14083     "\n\t\t: Modify particular graphic driver options:"
14084     "\n\t\t:  sRGB     - enable/disable sRGB rendering"
14085     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
14086     "\n\t\t:             built-in GLSL programs"
14087     "\n\t\t:            (requires compatible profile)"
14088     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
14089     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
14090     "\n\t\t:             arrays to GPU memory)"
14091     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
14092     "\n\t\t:  vsync    - switch VSync on or off"
14093     "\n\t\t:  winBuffer - allow using window buffer for rendering"
14094     "\n\t\t: Context creation options:"
14095     "\n\t\t:  softMode          - software OpenGL implementation"
14096     "\n\t\t:  compatibleProfile - backward-compatible profile"
14097     "\n\t\t:  quadbuffer        - QuadBuffer"
14098     "\n\t\t:  noExtensions      - disallow usage of extensions"
14099     "\n\t\t:  maxVersion        - force upper OpenGL version to be used"
14100     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
14101     "\n\t\t: rendering paths producing the same visual result when"
14102     "\n\t\t: possible."
14103     "\n\t\t: Command is intended for testing old hardware compatibility.",
14104     __FILE__, VCaps, group);
14105   theCommands.Add ("vmemgpu",
14106     "vmemgpu [f]: print system-dependent GPU memory information if available;"
14107     " with f option returns free memory in bytes",
14108     __FILE__, VMemGpu, group);
14109   theCommands.Add ("vreadpixel",
14110     "vreadpixel xPixel yPixel [{rgb|rgba|sRGB|sRGBa|depth|hls|rgbf|rgbaf}=rgba] [-name|-hex]"
14111     " : Read pixel value for active view",
14112     __FILE__, VReadPixel, group);
14113   theCommands.Add("diffimage",
14114             "diffimage imageFile1 imageFile2 [diffImageFile]"
14115     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
14116     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
14117     "\n\t\t: Compare two images by content and generate difference image."
14118     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
14119     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
14120     __FILE__, VDiffImage, group);
14121   theCommands.Add ("vselect",
14122     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
14123     "- emulates different types of selection:\n"
14124     "- 1) single click selection\n"
14125     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
14126     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
14127     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
14128     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
14129     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
14130     " (partial inclusion - overlap - is not allowed by default)\n"
14131     "- 5) any of these selections with shift button pressed",
14132     __FILE__, VSelect, group);
14133   theCommands.Add ("vmoveto",
14134     "vmoveto [x y] [-reset]"
14135     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
14136     "\n\t\t:   -reset resets current highlighting",
14137     __FILE__, VMoveTo, group);
14138   theCommands.Add ("vviewparams",
14139               "vviewparams [-args] [-scale [s]]"
14140       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
14141       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
14142       "\n\t\t: Manage current view parameters or prints all"
14143       "\n\t\t: current values when called without argument."
14144       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
14145       "\n\t\t:   -eye  [x y z] prints or sets eye location"
14146       "\n\t\t:   -at   [x y z] prints or sets center of look"
14147       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
14148       "\n\t\t:   -proj [x y z] prints or sets direction of look"
14149       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
14150       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
14151       "\n\t\t:                 or changes the size of its maximum dimension"
14152       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
14153     __FILE__, VViewParams, group);
14154
14155   theCommands.Add("v2dmode",
14156     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
14157     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
14158     "\n\t\t:   mode   - switches On/Off rotation mode"
14159     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
14160     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
14161     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
14162     "\n\t\t: View camera position might be changed only by commands.",
14163     __FILE__, V2DMode, group);
14164
14165   theCommands.Add("vanimation", "Alias for vanim",
14166     __FILE__, VAnimation, group);
14167
14168   theCommands.Add("vanim",
14169             "List existing animations:"
14170     "\n\t\t:  vanim"
14171     "\n\t\t: Animation playback:"
14172     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
14173     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
14174     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
14175     "\n\t\t:   -freeLook skip camera animations"
14176     "\n\t\t:   -lockLoop disable any interactions"
14177     "\n\t\t:"
14178     "\n\t\t: Animation definition:"
14179     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
14180     "\n\t\t:        [start TimeSec] [duration TimeSec]"
14181     "\n\t\t:"
14182     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
14183     "\n\t\t: specifies nested animations."
14184     "\n\t\t: There is no syntax to explicitly add new animation,"
14185     "\n\t\t: and all non-existing animations within the name will be"
14186     "\n\t\t: implicitly created on first use (including parents)."
14187     "\n\t\t:"
14188     "\n\t\t: Each animation might define the SINGLE action (see below),"
14189     "\n\t\t: like camera transition, object transformation or custom callback."
14190     "\n\t\t: Child animations can be used for defining concurrent actions."
14191     "\n\t\t:"
14192     "\n\t\t: Camera animation:"
14193     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
14194     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
14195     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
14196     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
14197     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
14198     "\n\t\t:   -atX    camera Center positions pair"
14199     "\n\t\t:   -upX    camera Up directions pair"
14200     "\n\t\t:   -scaleX camera Scale factors pair"
14201     "\n\t\t: Object animation:"
14202     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
14203     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
14204     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
14205     "\n\t\t:   -locX   object Location points pair (translation)"
14206     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
14207     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
14208     "\n\t\t: Custom callback:"
14209     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
14210     "\n\t\t:   %Pts        overall animation presentation timestamp"
14211     "\n\t\t:   %LocalPts   local animation timestamp"
14212     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
14213     "\n\t\t:"
14214     "\n\t\t: Video recording:"
14215     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
14216     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
14217     "\n\t\t:             [-crf Value] [-preset Preset]"
14218     "\n\t\t:   -fps     video framerate"
14219     "\n\t\t:   -format  file format, container (matroska, etc.)"
14220     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
14221     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
14222     "\n\t\t:   -crf     constant rate factor (specific to codec)"
14223     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
14224     __FILE__, VAnimation, group);
14225
14226   theCommands.Add("vchangeselected",
14227     "vchangeselected shape"
14228     "- adds to shape to selection or remove one from it",
14229                 __FILE__, VChangeSelected, group);
14230   theCommands.Add ("vnbselected",
14231     "vnbselected"
14232     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
14233   theCommands.Add ("vcamera",
14234               "vcamera [PrsName] [-ortho] [-projtype]"
14235       "\n\t\t:         [-persp]"
14236       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
14237       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
14238       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
14239       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
14240       "\n\t\t: Manages camera parameters."
14241       "\n\t\t: Displays frustum when presntation name PrsName is specified."
14242       "\n\t\t: Prints current value when option called without argument."
14243       "\n\t\t: Orthographic camera:"
14244       "\n\t\t:   -ortho      activate orthographic projection"
14245       "\n\t\t: Perspective camera:"
14246       "\n\t\t:   -persp      activate perspective  projection (mono)"
14247       "\n\t\t:   -fovy       field of view in y axis, in degrees"
14248       "\n\t\t:   -distance   distance of eye from camera center"
14249       "\n\t\t: Stereoscopic camera:"
14250       "\n\t\t:   -stereo     perspective  projection (stereo)"
14251       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
14252       "\n\t\t:   -rightEye   perspective  projection (right eye)"
14253       "\n\t\t:   -iod        intraocular distance value"
14254       "\n\t\t:   -iodType    distance type, absolute or relative"
14255       "\n\t\t:   -zfocus     stereographic focus value"
14256       "\n\t\t:   -zfocusType focus type, absolute or relative",
14257     __FILE__, VCamera, group);
14258   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
14259     "- vautozfit [on={1|0}] [scale]\n"
14260     "    Prints or changes parameters of automatic z-fit mode:\n"
14261     "   \"on\" - turns automatic z-fit on or off\n"
14262     "   \"scale\" - specifies factor to scale computed z range.\n",
14263     __FILE__, VAutoZFit, group);
14264   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
14265     "   vzrange                - without parameters shows current values\n"
14266     "   vzrange [znear] [zfar] - applies provided values to view",
14267     __FILE__,VZRange, group);
14268   theCommands.Add ("vpurgedisplay",
14269     "vpurgedisplay"
14270     "- removes structures which don't belong to objects displayed in neutral point",
14271     __FILE__, VPurgeDisplay, group);
14272   theCommands.Add("vsetviewsize",
14273     "vsetviewsize size",
14274     __FILE__,VSetViewSize,group);
14275   theCommands.Add("vmoveview",
14276     "vmoveview Dx Dy Dz [Start = 1|0]",
14277     __FILE__,VMoveView,group);
14278   theCommands.Add("vtranslateview",
14279     "vtranslateview Dx Dy Dz [Start = 1|0)]",
14280     __FILE__,VTranslateView,group);
14281   theCommands.Add("vturnview",
14282     "vturnview Ax Ay Az [Start = 1|0]",
14283     __FILE__,VTurnView,group);
14284   theCommands.Add("vtextureenv",
14285     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
14286     "or user-defined file and optionally applying texture mapping parameters\n"
14287     "                  Usage:\n"
14288     "                  vtextureenv off - disables environment mapping\n"
14289     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
14290     "                              std_texture = (0..7)\n"
14291     "                              rep         = {clamp|repeat}\n"
14292     "                              mod         = {decal|modulate}\n"
14293     "                              flt         = {nearest|bilinear|trilinear}\n"
14294     "                              ss, st      - scale factors for s and t texture coordinates\n"
14295     "                              ts, tt      - translation for s and t texture coordinates\n"
14296     "                              rot         - texture rotation angle in degrees",
14297     __FILE__, VTextureEnv, group);
14298   theCommands.Add("vhlr",
14299             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
14300       "\n\t\t: Hidden Line Removal algorithm."
14301       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
14302       "\n\t\t:   -algoType   type of HLR algorithm.\n",
14303     __FILE__,VHLR,group);
14304   theCommands.Add("vhlrtype",
14305               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
14306       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
14307       "\n\t\t:   'algo' - exact HLR algorithm is applied"
14308       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
14309       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
14310     __FILE__,VHLRType,group);
14311   theCommands.Add("vclipplane",
14312               "vclipplane planeName [{0|1}]"
14313       "\n\t\t:   [-equation1 A B C D]"
14314       "\n\t\t:   [-equation2 A B C D]"
14315       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
14316       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
14317       "\n\t\t:   [-maxPlanes]"
14318       "\n\t\t:   [-capping {0|1}]"
14319       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
14320       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
14321       "\n\t\t:       [-texRotate Angle]"
14322       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
14323       "\n\t\t:       [-useObjShader {0|1}]"
14324       "\n\t\t: Clipping planes management:"
14325       "\n\t\t:   -maxPlanes   print plane limit for view"
14326       "\n\t\t:   -delete      delete plane with given name"
14327       "\n\t\t:   {off|on|0|1} turn clipping on/off"
14328       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
14329       "\n\t\t:                applied to active View when list is omitted"
14330       "\n\t\t:   -equation A B C D change plane equation"
14331       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
14332       "\n\t\t: Capping options:"
14333       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
14334       "\n\t\t:   -color R G B          set capping color"
14335       "\n\t\t:   -transparency Value   set capping transparency 0..1"
14336       "\n\t\t:   -texName Texture      set capping texture"
14337       "\n\t\t:   -texScale SX SY       set capping tex scale"
14338       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
14339       "\n\t\t:   -texRotate Angle      set capping tex rotation"
14340       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
14341       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
14342       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
14343       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
14344       __FILE__, VClipPlane, group);
14345   theCommands.Add("vdefaults",
14346                "vdefaults [-absDefl value]"
14347        "\n\t\t:           [-devCoeff value]"
14348        "\n\t\t:           [-angDefl value]"
14349        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
14350     , __FILE__, VDefaults, group);
14351   theCommands.Add("vlight",
14352     "tool to manage light sources, without arguments shows list of lights."
14353     "\n    Main commands: "
14354     "\n      '-clear' to clear lights"
14355     "\n      '-{def}aults' to load deafault lights"
14356     "\n      '-add' <type> to add any light source"
14357     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
14358     "\n      'change' <lightId> to edit light source with specified lightId"
14359     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
14360     "\n        -layer Id"
14361     "\n        -{pos}ition X Y Z"
14362     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
14363     "\n        -color colorName"
14364     "\n        -{head}light 0|1"
14365     "\n        -{sm}oothness value"
14366     "\n        -{int}ensity value"
14367     "\n        -{constAtten}uation value"
14368     "\n        -{linearAtten}uation value"
14369     "\n        -angle angleDeg"
14370     "\n        -{spotexp}onent value"
14371     "\n        -local|-global"
14372     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
14373     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
14374     __FILE__, VLight, group);
14375   theCommands.Add("vpbrenv",
14376     "vpbrenv -clear|-generate"
14377     "\n\t\t: Clears or generates PBR environment map of active view."
14378     "\n\t\t:  -clear clears PBR environment (fills by white color)"
14379     "\n\t\t:  -generate generates PBR environment from current background cubemap",
14380     __FILE__, VPBREnvironment, group);
14381   theCommands.Add("vraytrace",
14382             "vraytrace [0|1]"
14383     "\n\t\t: Turns on/off ray-tracing renderer."
14384     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
14385     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
14386     __FILE__, VRenderParams, group);
14387   theCommands.Add("vrenderparams",
14388     "\n    Manages rendering parameters: "
14389     "\n      '-raster'                   Disables GPU ray-tracing"
14390     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
14391     "\n      '-lineFeather  > 0'         Sets line feather factor"
14392     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
14393     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
14394     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
14395     "\n      '-rendScale    value        Rendering resolution scale factor"
14396     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
14397     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
14398     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
14399     "\n      '-reflections  on|off'      Enables/disables specular reflections"
14400     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
14401     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
14402     "\n      '-gi           on|off'      Enables/disables global illumination effects"
14403     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
14404     "\n      '-env          on|off'      Enables/disables environment map background"
14405     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
14406     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
14407     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
14408     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
14409     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
14410     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
14411     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
14412     "\n      '-shadingModel model'       Controls shading model from enumeration"
14413     "\n                                  unlit, flat, gouraud, phong"
14414     "\n      '-pbrEnvPow2size > 0'       Controls size of IBL maps (real size can be calculates as 2^pbrenvpow2size)"
14415     "\n      '-pbrEnvSMLN > 1'           Controls number of mipmap levels used in specular IBL map"
14416     "\n      '-pbrEnvBDSN > 0'           Controls number of samples in Monte-Carlo integration during diffuse IBL map's sherical harmonics calculation"
14417     "\n      '-pbrEnvBSSN > 0'           Controls maximum number of samples per mipmap level in Monte-Carlo integration during specular IBL maps generation"
14418     "\n      '-pbrEnvBP [0, 1]'          Controls strength of samples number reducing during specular IBL maps generation (1 disables reducing)"
14419     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
14420     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
14421     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
14422     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
14423     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
14424     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
14425     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
14426     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
14427     "\n                                  Show/hide performance counters (flags can be combined)"
14428     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
14429     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
14430     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
14431     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
14432     "\n                                        set state to check structures culled previously."
14433     "\n    Unlike vcaps, these parameters dramatically change visual properties."
14434     "\n    Command is intended to control presentation quality depending on"
14435     "\n    hardware capabilities and performance.",
14436     __FILE__, VRenderParams, group);
14437   theCommands.Add("vstatprofiler",
14438     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
14439     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
14440     "\n                |triagles|points|geomMem|textureMem|frameMem"
14441     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
14442     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
14443     "\n                [-noredraw]"
14444     "\n\t\t: Prints rendering statistics."
14445     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
14446     "\n\t\t:   else - print all performance counters set previously."
14447     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
14448     __FILE__, VStatProfiler, group);
14449   theCommands.Add ("vplace",
14450             "vplace dx dy"
14451     "\n\t\t: Places the point (in pixels) at the center of the window",
14452     __FILE__, VPlace, group);
14453   theCommands.Add("vxrotate",
14454     "vxrotate",
14455     __FILE__,VXRotate,group);
14456
14457     theCommands.Add("vmanipulator",
14458       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
14459       "\n    tool to create and manage AIS manipulators."
14460       "\n    Options: "
14461       "\n      '-attach AISObject'                 attach manipulator to AISObject"
14462       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
14463       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
14464       "\n      '-enableModes    {0|1}'             enable modes when attaching"
14465       "\n      '-view  {active | [name of view]}'  display manipulator only in defined view,"
14466       "\n                                          by default it is displayed in all views of the current viewer"
14467       "\n      '-detach'                           detach manipulator"
14468       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
14469       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
14470       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
14471       "\n      '-move x y z'                     - move attached object"
14472       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
14473       "\n      '-scale factor'                   - scale attached object"
14474       "\n      '-autoActivate      {0|1}'        - set activation on detection"
14475       "\n      '-followTranslation {0|1}'        - set following translation transform"
14476       "\n      '-followRotation    {0|1}'        - set following rotation transform"
14477       "\n      '-followDragging    {0|1}'        - set following dragging transform"
14478       "\n      '-gap value'                      - set gap between sub-parts"
14479       "\n      '-part axis mode    {0|1}'        - set visual part"
14480       "\n      '-parts axis mode   {0|1}'        - set visual part"
14481       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
14482       "\n      '-size value'                     - set size of manipulator"
14483       "\n      '-zoomable {0|1}'                 - set zoom persistence",
14484     __FILE__, VManipulator, group);
14485
14486   theCommands.Add("vselprops",
14487     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
14488     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
14489     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
14490     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
14491     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
14492     "\n    -pickStrategy {first|topmost} : defines picking strategy"
14493     "\n                            'first'   to pick first acceptable (default)"
14494     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
14495     "\n    -pixTol    value        : sets up pixel tolerance"
14496     "\n    -dispMode  dispMode     : sets display mode for highlighting"
14497     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
14498     "\n    -color     {name|r g b} : sets highlight color"
14499     "\n    -transp    value        : sets transparency coefficient for highlight"
14500     "\n    -material  material     : sets highlight material"
14501     "\n    -print                  : prints current state of all mentioned parameters",
14502     __FILE__, VSelectionProperties, group);
14503   theCommands.Add ("vhighlightselected",
14504                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
14505                    __FILE__, VSelectionProperties, group);
14506
14507   theCommands.Add ("vseldump",
14508                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
14509                    "\n\t\t: Generate an image based on detection results:"
14510                    "\n\t\t:   depth       normalized depth values"
14511                    "\n\t\t:   unnormDepth unnormalized depth values"
14512                    "\n\t\t:   object      color of detected object"
14513                    "\n\t\t:   owner       color of detected owner"
14514                    "\n\t\t:   selMode     color of selection mode"
14515                    "\n\t\t:   entity      color of etected entity",
14516                    __FILE__, VDumpSelectionImage, group);
14517
14518   theCommands.Add ("vviewcube",
14519                    "vviewcube name"
14520                    "\n\t\t: Displays interactive view manipualtion object."
14521                    "\n\t\t: Options: "
14522                    "\n\t\t:   -reset                   reset geomertical and visual attributes'"
14523                    "\n\t\t:   -size Size               adapted size of View Cube"
14524                    "\n\t\t:   -boxSize Size            box size"
14525                    "\n\t\t:   -axes {0|1 }             show/hide axes (trihedron)"
14526                    "\n\t\t:   -edges {0|1}             show/hide edges of View Cube"
14527                    "\n\t\t:   -vertices {0|1}          show/hide vertices of View Cube"
14528                    "\n\t\t:   -Yup {0|1} -Zup {0|1}    set Y-up or Z-up view orientation"
14529                    "\n\t\t:   -color Color             color of View Cube"
14530                    "\n\t\t:   -boxColor Color          box color"
14531                    "\n\t\t:   -boxSideColor Color      box sides color"
14532                    "\n\t\t:   -boxEdgeColor Color      box edges color"
14533                    "\n\t\t:   -boxCornerColor Color    box corner color"
14534                    "\n\t\t:   -textColor Color         color of side text of view cube"
14535                    "\n\t\t:   -innerColor Color        inner box color"
14536                    "\n\t\t:   -transparency Value      transparency of object within [0, 1] range"
14537                    "\n\t\t:   -boxTransparency Value   transparency of box    within [0, 1] range"
14538                    "\n\t\t:   -font Name               font name"
14539                    "\n\t\t:   -fontHeight Value        font height"
14540                    "\n\t\t:   -boxFacetExtension Value box facet extension"
14541                    "\n\t\t:   -boxEdgeGap Value        gap between box edges and box sides"
14542                    "\n\t\t:   -boxEdgeMinSize Value    minimal box edge size"
14543                    "\n\t\t:   -boxCornerMinSize Value  minimal box corner size"
14544                    "\n\t\t:   -axesPadding Value       padding between box and arrows"
14545                    "\n\t\t:   -roundRadius Value       relative radius of corners of sides within [0.0, 0.5] range"
14546                    "\n\t\t:   -fixedanimation {0|1}    uninterruptible animation loop"
14547                    "\n\t\t:   -duration Seconds        animation duration in seconds",
14548     __FILE__, VViewCube, group);
14549
14550 }