c2d8b0f594243979dce24d03ca3305706a4e08f1
[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(WNT_WClass)& ViewerTest::WClass()
1401 {
1402   static Handle(WNT_WClass) 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(), WClass(),
1943                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
1944                                     aPxLeft, aPxTop,
1945                                     aPxWidth, aPxHeight,
1946                                     Quantity_NOC_BLACK);
1947 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1948   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1949                                      aPxLeft, aPxTop,
1950                                      aPxWidth, aPxHeight);
1951   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
1952 #else
1953   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1954                                   aTitle.ToCString(),
1955                                   aPxLeft, aPxTop,
1956                                   aPxWidth, aPxHeight);
1957 #endif
1958   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
1959
1960   // View setup
1961   Handle(V3d_View) aView;
1962   if (!theViewToClone.IsNull())
1963   {
1964     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
1965   }
1966   else
1967   {
1968     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
1969   }
1970
1971   aView->SetWindow (VT_GetWindow());
1972   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
1973
1974   ViewerTest::CurrentView(aView);
1975   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
1976
1977   // Setup for X11 or NT
1978   OSWindowSetup();
1979
1980   // Set parameters for V3d_View and V3d_Viewer
1981   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1982   aV3dView->SetComputedMode(Standard_False);
1983
1984   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1985   if (toCreateViewer)
1986   {
1987     a3DViewer->SetDefaultLights();
1988     a3DViewer->SetLightOn();
1989   }
1990
1991 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1992   if (isNewDriver)
1993   {
1994     ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1995     Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1996   }
1997 #endif
1998
1999   VT_GetWindow()->Map();
2000
2001   // Set the handle of created view in the event manager
2002   ViewerTest::ResetEventManager();
2003
2004   ViewerTest::CurrentView()->Redraw();
2005
2006   aView.Nullify();
2007   a3DViewer.Nullify();
2008
2009   return aViewNames.GetViewName();
2010 }
2011
2012 //==============================================================================
2013 //function : RedrawAllViews
2014 //purpose  : Redraw all created views
2015 //==============================================================================
2016 void ViewerTest::RedrawAllViews()
2017 {
2018   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
2019   for (; aViewIt.More(); aViewIt.Next())
2020   {
2021     const Handle(V3d_View)& aView = aViewIt.Key2();
2022     aView->Redraw();
2023   }
2024 }
2025
2026 //==============================================================================
2027 //function : Vinit
2028 //purpose  : Create the window viewer and initialize all the global variable
2029 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
2030 //==============================================================================
2031
2032 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2033 {
2034   TCollection_AsciiString aViewName, aDisplayName;
2035   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
2036   Handle(V3d_View) aCopyFrom;
2037   TCollection_AsciiString aName, aValue;
2038   int is2dMode = -1;
2039   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
2040   {
2041     const TCollection_AsciiString anArg = theArgVec[anArgIt];
2042     TCollection_AsciiString anArgCase = anArg;
2043     anArgCase.LowerCase();
2044     if (anArgIt + 1 < theArgsNb
2045      && anArgCase == "-name")
2046     {
2047       aViewName = theArgVec[++anArgIt];
2048     }
2049     else if (anArgIt + 1 < theArgsNb
2050           && (anArgCase == "-left"
2051            || anArgCase == "-l"))
2052     {
2053       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2054     }
2055     else if (anArgIt + 1 < theArgsNb
2056           && (anArgCase == "-top"
2057            || anArgCase == "-t"))
2058     {
2059       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2060     }
2061     else if (anArgIt + 1 < theArgsNb
2062           && (anArgCase == "-width"
2063            || anArgCase == "-w"))
2064     {
2065       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2066     }
2067     else if (anArgIt + 1 < theArgsNb
2068           && (anArgCase == "-height"
2069            || anArgCase == "-h"))
2070     {
2071       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2072     }
2073     else if (anArgCase == "-exitonclose")
2074     {
2075       ViewerTest_EventManager::ToExitOnCloseView() = true;
2076       if (anArgIt + 1 < theArgsNb
2077        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
2078       {
2079         ++anArgIt;
2080       }
2081     }
2082     else if (anArgCase == "-closeonescape"
2083           || anArgCase == "-closeonesc")
2084     {
2085       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
2086       if (anArgIt + 1 < theArgsNb
2087        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
2088       {
2089         ++anArgIt;
2090       }
2091     }
2092     else if (anArgCase == "-2d_mode"
2093           || anArgCase == "-2dmode"
2094           || anArgCase == "-2d")
2095     {
2096       bool toEnable = true;
2097       if (anArgIt + 1 < theArgsNb
2098        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2099       {
2100         ++anArgIt;
2101       }
2102       is2dMode = toEnable ? 1 : 0;
2103     }
2104     else if (anArgIt + 1 < theArgsNb
2105           && (anArgCase == "-disp"
2106            || anArgCase == "-display"))
2107     {
2108       aDisplayName = theArgVec[++anArgIt];
2109     }
2110     else if (!ViewerTest::CurrentView().IsNull()
2111           &&  aCopyFrom.IsNull()
2112           && (anArgCase == "-copy"
2113            || anArgCase == "-clone"
2114            || anArgCase == "-cloneactive"
2115            || anArgCase == "-cloneactiveview"))
2116     {
2117       aCopyFrom = ViewerTest::CurrentView();
2118     }
2119     // old syntax
2120     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2121     {
2122       aName.LowerCase();
2123       if (aName == "name")
2124       {
2125         aViewName = aValue;
2126       }
2127       else if (aName == "l"
2128             || aName == "left")
2129       {
2130         aPxLeft = aValue.IntegerValue();
2131       }
2132       else if (aName == "t"
2133             || aName == "top")
2134       {
2135         aPxTop = aValue.IntegerValue();
2136       }
2137       else if (aName == "disp"
2138             || aName == "display")
2139       {
2140         aDisplayName = aValue;
2141       }
2142       else if (aName == "w"
2143             || aName == "width")
2144       {
2145         aPxWidth = aValue.IntegerValue();
2146       }
2147       else if (aName == "h"
2148             || aName == "height")
2149       {
2150         aPxHeight = aValue.IntegerValue();
2151       }
2152       else
2153       {
2154         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2155         return 1;
2156       }
2157     }
2158     else if (aViewName.IsEmpty())
2159     {
2160       aViewName = anArg;
2161     }
2162     else
2163     {
2164       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2165       return 1;
2166     }
2167   }
2168
2169 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2170   if (!aDisplayName.IsEmpty())
2171   {
2172     aDisplayName.Clear();
2173     std::cout << "Warning: display parameter will be ignored.\n";
2174   }
2175 #endif
2176
2177   ViewerTest_Names aViewNames (aViewName);
2178   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
2179   {
2180     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2181     theDi.Eval (aCommand.ToCString());
2182     if (is2dMode != -1)
2183     {
2184       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2185     }
2186     return 0;
2187   }
2188
2189   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
2190                                                             aViewName, aDisplayName, aCopyFrom);
2191   if (is2dMode != -1)
2192   {
2193     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2194   }
2195   theDi << aViewId;
2196   return 0;
2197 }
2198
2199 //! Parse HLR algo type.
2200 static Standard_Boolean parseHlrAlgoType (const char* theName,
2201                                           Prs3d_TypeOfHLR& theType)
2202 {
2203   TCollection_AsciiString aName (theName);
2204   aName.LowerCase();
2205   if (aName == "polyalgo")
2206   {
2207     theType = Prs3d_TOH_PolyAlgo;
2208   }
2209   else if (aName == "algo")
2210   {
2211     theType = Prs3d_TOH_Algo;
2212   }
2213   else
2214   {
2215     return Standard_False;
2216   }
2217   return Standard_True;
2218 }
2219
2220 //==============================================================================
2221 //function : VHLR
2222 //purpose  : hidden lines removal algorithm
2223 //==============================================================================
2224
2225 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2226 {
2227   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2228   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2229   if (aView.IsNull())
2230   {
2231     std::cerr << "Error: No opened viewer!\n";
2232     return 1;
2233   }
2234
2235   Standard_Boolean hasHlrOnArg = Standard_False;
2236   Standard_Boolean hasShowHiddenArg = Standard_False;
2237   Standard_Boolean isHLROn = Standard_False;
2238   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2239   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
2240   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2241   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2242   {
2243     TCollection_AsciiString anArg (argv[anArgIter]);
2244     anArg.LowerCase();
2245     if (anUpdateTool.parseRedrawMode (anArg))
2246     {
2247       continue;
2248     }
2249     else if (anArg == "-showhidden"
2250           && anArgIter + 1 < argc
2251           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2252     {
2253       ++anArgIter;
2254       hasShowHiddenArg = Standard_True;
2255       continue;
2256     }
2257     else if ((anArg == "-type"
2258            || anArg == "-algo"
2259            || anArg == "-algotype")
2260           && anArgIter + 1 < argc
2261           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2262     {
2263       ++anArgIter;
2264       continue;
2265     }
2266     else if (!hasHlrOnArg
2267           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2268     {
2269       hasHlrOnArg = Standard_True;
2270       continue;
2271     }
2272     // old syntax
2273     else if (!hasShowHiddenArg
2274           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2275     {
2276       hasShowHiddenArg = Standard_True;
2277       continue;
2278     }
2279     else
2280     {
2281       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2282       return 1;
2283     }
2284   }
2285   if (!hasHlrOnArg)
2286   {
2287     di << "HLR:        " << aView->ComputedMode() << "\n";
2288     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2289     di << "HlrAlgo:    ";
2290     switch (aCtx->DefaultDrawer()->TypeOfHLR())
2291     {
2292       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
2293       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2294       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
2295     }
2296     anUpdateTool.Invalidate();
2297     return 0;
2298   }
2299
2300   Standard_Boolean toRecompute = Standard_False;
2301   if (aTypeOfHLR != Prs3d_TOH_NotSet
2302    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
2303   {
2304     toRecompute = Standard_True;
2305     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2306   }
2307   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2308   {
2309     toRecompute = Standard_True;
2310     if (toShowHidden)
2311     {
2312       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
2313     }
2314     else
2315     {
2316       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
2317     }
2318   }
2319
2320   // redisplay shapes
2321   if (aView->ComputedMode() && isHLROn && toRecompute)
2322   {
2323     AIS_ListOfInteractive aListOfShapes;
2324     aCtx->DisplayedObjects (aListOfShapes);
2325     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
2326     {
2327       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
2328       {
2329         aCtx->Redisplay (aShape, Standard_False);
2330       }
2331     }
2332   }
2333
2334   aView->SetComputedMode (isHLROn);
2335   return 0;
2336 }
2337
2338 //==============================================================================
2339 //function : VHLRType
2340 //purpose  : change type of using HLR algorithm
2341 //==============================================================================
2342
2343 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
2344 {
2345   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2346   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2347   if (aView.IsNull())
2348   {
2349     std::cerr << "Error: No opened viewer!\n";
2350     return 1;
2351   }
2352
2353   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2354   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2355   AIS_ListOfInteractive aListOfShapes;
2356   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2357   {
2358     TCollection_AsciiString anArg (argv[anArgIter]);
2359     anArg.LowerCase();
2360     if (anUpdateTool.parseRedrawMode (anArg))
2361     {
2362       continue;
2363     }
2364     else if ((anArg == "-type"
2365            || anArg == "-algo"
2366            || anArg == "-algotype")
2367           && anArgIter + 1 < argc
2368           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2369     {
2370       ++anArgIter;
2371       continue;
2372     }
2373     // old syntax
2374     else if (aTypeOfHLR == Prs3d_TOH_NotSet
2375           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2376     {
2377       continue;
2378     }
2379     else
2380     {
2381       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
2382       TCollection_AsciiString aName (argv[anArgIter]);
2383       if (!aMap.IsBound2 (aName))
2384       {
2385         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2386         return 1;
2387       }
2388
2389       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2390       if (aShape.IsNull())
2391       {
2392         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2393         return 1;
2394       }
2395       aListOfShapes.Append (aShape);
2396       continue;
2397     }
2398   }
2399   if (aTypeOfHLR == Prs3d_TOH_NotSet)
2400   {
2401     std::cout << "Syntax error: wrong number of arguments!\n";
2402     return 1;
2403   }
2404
2405   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2406   if (isGlobal)
2407   {
2408     aCtx->DisplayedObjects (aListOfShapes);
2409     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2410   }
2411
2412   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2413   {
2414     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2415     if (aShape.IsNull())
2416     {
2417       continue;
2418     }
2419
2420     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2421                             && aView->ComputedMode();
2422     if (!isGlobal
2423      || aShape->TypeOfHLR() != aTypeOfHLR)
2424     {
2425       aShape->SetTypeOfHLR (aTypeOfHLR);
2426     }
2427     if (toUpdateShape)
2428     {
2429       aCtx->Redisplay (aShape, Standard_False);
2430     }
2431   }
2432   return 0;
2433 }
2434
2435 //==============================================================================
2436 //function : FindViewIdByWindowHandle
2437 //purpose  : Find theView Id in the map of views by window handle
2438 //==============================================================================
2439 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2440 TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
2441 {
2442   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2443        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2444   {
2445     Aspect_Drawable aWindowHandle = anIter.Value()->Window()->NativeHandle();
2446     if (aWindowHandle == theWindowHandle)
2447       return anIter.Key1();
2448   }
2449   return TCollection_AsciiString("");
2450 }
2451 #endif
2452
2453 //! Make the view active
2454 void ActivateView (const TCollection_AsciiString& theViewName,
2455                    Standard_Boolean theToUpdate = Standard_True)
2456 {
2457   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2458   if (aView.IsNull())
2459   {
2460     return;
2461   }
2462
2463   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2464   if (!anAISContext.IsNull())
2465   {
2466     if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
2467     {
2468       aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
2469     }
2470
2471     ViewerTest::CurrentView (aView);
2472     ViewerTest::SetAISContext (anAISContext);
2473     aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
2474 #if defined(_WIN32)
2475     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
2476 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
2477     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
2478 #else
2479     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
2480 #endif
2481     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2482     if (theToUpdate)
2483     {
2484       ViewerTest::CurrentView()->Redraw();
2485     }
2486   }
2487 }
2488
2489 //==============================================================================
2490 //function : RemoveView
2491 //purpose  :
2492 //==============================================================================
2493 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2494                              const Standard_Boolean  theToRemoveContext)
2495 {
2496   if (!ViewerTest_myViews.IsBound2 (theView))
2497   {
2498     return;
2499   }
2500
2501   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2502   RemoveView (aViewName, theToRemoveContext);
2503 }
2504
2505 //==============================================================================
2506 //function : RemoveView
2507 //purpose  : Close and remove view from display, clear maps if neccessary
2508 //==============================================================================
2509 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2510 {
2511   if (!ViewerTest_myViews.IsBound1(theViewName))
2512   {
2513     std::cout << "Wrong view name\n";
2514     return;
2515   }
2516
2517   // Activate another view if it's active now
2518   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2519   {
2520     if (ViewerTest_myViews.Extent() > 1)
2521     {
2522       TCollection_AsciiString aNewViewName;
2523       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2524            anIter.More(); anIter.Next())
2525       {
2526         if (anIter.Key1() != theViewName)
2527         {
2528           aNewViewName = anIter.Key1();
2529           break;
2530         }
2531       }
2532       ActivateView (aNewViewName);
2533     }
2534     else
2535     {
2536       VT_GetWindow().Nullify();
2537       ViewerTest::CurrentView (Handle(V3d_View)());
2538       if (isContextRemoved)
2539       {
2540         Handle(AIS_InteractiveContext) anEmptyContext;
2541         ViewerTest::SetAISContext(anEmptyContext);
2542       }
2543     }
2544   }
2545
2546   // Delete view
2547   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2548   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
2549   ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2550   aRedrawer.Stop (aView->Window());
2551
2552   // Remove view resources
2553   ViewerTest_myViews.UnBind1(theViewName);
2554   aView->Window()->Unmap();
2555   aView->Remove();
2556
2557 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2558   XFlush (GetDisplayConnection()->GetDisplay());
2559 #endif
2560
2561   // Keep context opened only if the closed view is last to avoid
2562   // unused empty contexts
2563   if (!aCurrentContext.IsNull())
2564   {
2565     // Check if there are more difined views in the viewer
2566     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1)
2567      && aCurrentContext->CurrentViewer()->DefinedViews().IsEmpty())
2568     {
2569       // Remove driver if there is no viewers that use it
2570       Standard_Boolean isRemoveDriver = Standard_True;
2571       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2572           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2573       {
2574         if (aCurrentContext != anIter.Key2() &&
2575           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2576         {
2577           isRemoveDriver = Standard_False;
2578           break;
2579         }
2580       }
2581
2582       aCurrentContext->RemoveAll (Standard_False);
2583       if(isRemoveDriver)
2584       {
2585         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2586       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2587         Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
2588       #endif
2589       }
2590
2591       ViewerTest_myContexts.UnBind2(aCurrentContext);
2592     }
2593   }
2594   std::cout << "3D View - " << theViewName << " was deleted.\n";
2595   if (ViewerTest_EventManager::ToExitOnCloseView())
2596   {
2597     Draw_Interprete ("exit");
2598   }
2599 }
2600
2601 //==============================================================================
2602 //function : VClose
2603 //purpose  : Remove the view defined by its name
2604 //==============================================================================
2605
2606 static int VClose (Draw_Interpretor& /*theDi*/,
2607                    Standard_Integer  theArgsNb,
2608                    const char**      theArgVec)
2609 {
2610   NCollection_List<TCollection_AsciiString> aViewList;
2611   if (theArgsNb > 1)
2612   {
2613     TCollection_AsciiString anArg (theArgVec[1]);
2614     anArg.UpperCase();
2615     if (anArg.IsEqual ("ALL")
2616      || anArg.IsEqual ("*"))
2617     {
2618       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2619            anIter.More(); anIter.Next())
2620       {
2621         aViewList.Append (anIter.Key1());
2622       }
2623       if (aViewList.IsEmpty())
2624       {
2625         std::cout << "No view to close\n";
2626         return 0;
2627       }
2628     }
2629     else
2630     {
2631       ViewerTest_Names aViewName (theArgVec[1]);
2632       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2633       {
2634         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2635         return 1;
2636       }
2637       aViewList.Append (aViewName.GetViewName());
2638     }
2639   }
2640   else
2641   {
2642     // close active view
2643     if (ViewerTest::CurrentView().IsNull())
2644     {
2645       std::cerr << "No active view!\n";
2646       return 1;
2647     }
2648     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2649   }
2650
2651   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
2652   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2653        anIter.More(); anIter.Next())
2654   {
2655     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
2656   }
2657
2658   return 0;
2659 }
2660
2661 //==============================================================================
2662 //function : VActivate
2663 //purpose  : Activate the view defined by its ID
2664 //==============================================================================
2665
2666 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2667 {
2668   if (theArgsNb == 1)
2669   {
2670     theDi.Eval("vviewlist");
2671     return 0;
2672   }
2673
2674   TCollection_AsciiString aNameString;
2675   Standard_Boolean toUpdate = Standard_True;
2676   Standard_Boolean toActivate = Standard_True;
2677   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
2678   {
2679     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2680     anArg.LowerCase();
2681     if (toUpdate
2682      && anArg == "-noupdate")
2683     {
2684       toUpdate = Standard_False;
2685     }
2686     else if (toActivate
2687           && aNameString.IsEmpty()
2688           && anArg == "none")
2689     {
2690       ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2691       VT_GetWindow().Nullify();
2692       ViewerTest::CurrentView (Handle(V3d_View)());
2693       ViewerTest::ResetEventManager();
2694       theDi << theArgVec[0] << ": all views are inactive\n";
2695       toActivate = Standard_False;
2696     }
2697     else if (toActivate
2698           && aNameString.IsEmpty())
2699     {
2700       aNameString = theArgVec[anArgIter];
2701     }
2702     else
2703     {
2704       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2705       return 1;
2706     }
2707   }
2708
2709   if (!toActivate)
2710   {
2711     return 0;
2712   }
2713   else if (aNameString.IsEmpty())
2714   {
2715     std::cout << "Syntax error: wrong number of arguments\n";
2716     return 1;
2717   }
2718
2719   // Check if this view exists in the viewer with the driver
2720   ViewerTest_Names aViewNames (aNameString);
2721   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2722   {
2723     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
2724     return 1;
2725   }
2726
2727   // Check if it is active already
2728   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2729   {
2730     theDi << theArgVec[0] << ": the view is active already\n";
2731     return 0;
2732   }
2733
2734   ActivateView (aViewNames.GetViewName(), toUpdate);
2735   return 0;
2736 }
2737
2738 //==============================================================================
2739 //function : VViewList
2740 //purpose  : Print current list of views per viewer and graphic driver ID
2741 //           shared between viewers
2742 //==============================================================================
2743
2744 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2745 {
2746   if (theArgsNb > 2)
2747   {
2748     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
2749           << "Usage: " << theArgVec[0] << " name";
2750     return 1;
2751   }
2752   if (ViewerTest_myContexts.Size() < 1)
2753     return 0;
2754
2755   Standard_Boolean isTreeView =
2756     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
2757
2758   if (isTreeView)
2759   {
2760     theDi << theArgVec[0] <<":\n";
2761   }
2762
2763   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2764        aDriverIter.More(); aDriverIter.Next())
2765   {
2766     if (isTreeView)
2767       theDi << aDriverIter.Key1() << ":\n";
2768
2769     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2770       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2771     {
2772       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
2773       {
2774         if (isTreeView)
2775         {
2776           TCollection_AsciiString aContextName(aContextIter.Key1());
2777           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2778         }
2779
2780         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2781              aViewIter.More(); aViewIter.Next())
2782         {
2783           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
2784           {
2785             TCollection_AsciiString aViewName(aViewIter.Key1());
2786             if (isTreeView)
2787             {
2788               if (aViewIter.Value() == ViewerTest::CurrentView())
2789                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
2790               else
2791                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2792             }
2793             else
2794             {
2795               theDi << aViewName << " ";
2796             }
2797           }
2798         }
2799       }
2800     }
2801   }
2802   return 0;
2803 }
2804
2805 //==============================================================================
2806 //function : GetMousePosition
2807 //purpose  :
2808 //==============================================================================
2809 void ViewerTest::GetMousePosition (Standard_Integer& theX,
2810                                    Standard_Integer& theY)
2811 {
2812   if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
2813   {
2814     theX = aViewCtrl->LastMousePosition().x();
2815     theY = aViewCtrl->LastMousePosition().y();
2816   }
2817 }
2818
2819 //==============================================================================
2820 //function : VViewProj
2821 //purpose  : Switch view projection
2822 //==============================================================================
2823 static int VViewProj (Draw_Interpretor& ,
2824                       Standard_Integer theNbArgs,
2825                       const char** theArgVec)
2826 {
2827   static Standard_Boolean isYup = Standard_False;
2828   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2829   if (aView.IsNull())
2830   {
2831     std::cout << "Error: no active view\n";
2832     return 1;
2833   }
2834
2835   TCollection_AsciiString aCmdName (theArgVec[0]);
2836   Standard_Boolean isGeneralCmd = Standard_False;
2837   if (aCmdName == "vfront")
2838   {
2839     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2840   }
2841   else if (aCmdName == "vback")
2842   {
2843     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2844   }
2845   else if (aCmdName == "vtop")
2846   {
2847     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2848   }
2849   else if (aCmdName == "vbottom")
2850   {
2851     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2852   }
2853   else if (aCmdName == "vleft")
2854   {
2855     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2856   }
2857   else if (aCmdName == "vright")
2858   {
2859     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2860   }
2861   else if (aCmdName == "vaxo")
2862   {
2863     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2864   }
2865   else
2866   {
2867     isGeneralCmd = Standard_True;
2868     for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2869     {
2870       TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2871       anArgCase.LowerCase();
2872       if (anArgCase == "-zup")
2873       {
2874         isYup = Standard_False;
2875       }
2876       else if (anArgCase == "-yup")
2877       {
2878         isYup = Standard_True;
2879       }
2880       else if (anArgCase == "-front"
2881             || anArgCase == "front"
2882             || anArgCase == "-f"
2883             || anArgCase == "f")
2884       {
2885         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2886       }
2887       else if (anArgCase == "-back"
2888             || anArgCase == "back"
2889             || anArgCase == "-b"
2890             || anArgCase == "b")
2891       {
2892         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2893       }
2894       else if (anArgCase == "-top"
2895             || anArgCase == "top"
2896             || anArgCase == "-t"
2897             || anArgCase == "t")
2898       {
2899         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2900       }
2901       else if (anArgCase == "-bottom"
2902             || anArgCase == "bottom"
2903             || anArgCase == "-bot"
2904             || anArgCase == "bot"
2905             || anArgCase == "-b"
2906             || anArgCase == "b")
2907       {
2908         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2909       }
2910       else if (anArgCase == "-left"
2911             || anArgCase == "left"
2912             || anArgCase == "-l"
2913             || anArgCase == "l")
2914       {
2915         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2916       }
2917       else if (anArgCase == "-right"
2918             || anArgCase == "right"
2919             || anArgCase == "-r"
2920             || anArgCase == "r")
2921       {
2922         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2923       }
2924       else if (anArgCase == "-axoleft"
2925             || anArgCase == "-leftaxo"
2926             || anArgCase == "axoleft"
2927             || anArgCase == "leftaxo")
2928       {
2929         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
2930       }
2931       else if (anArgCase == "-axo"
2932             || anArgCase == "axo"
2933             || anArgCase == "-a"
2934             || anArgCase == "a"
2935             || anArgCase == "-axoright"
2936             || anArgCase == "-rightaxo"
2937             || anArgCase == "axoright"
2938             || anArgCase == "rightaxo")
2939       {
2940         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2941       }
2942       else if (anArgCase == "+x")
2943       {
2944         aView->SetProj (V3d_Xpos, isYup);
2945       }
2946       else if (anArgCase == "-x")
2947       {
2948         aView->SetProj (V3d_Xneg, isYup);
2949       }
2950       else if (anArgCase == "+y")
2951       {
2952         aView->SetProj (V3d_Ypos, isYup);
2953       }
2954       else if (anArgCase == "-y")
2955       {
2956         aView->SetProj (V3d_Yneg, isYup);
2957       }
2958       else if (anArgCase == "+z")
2959       {
2960         aView->SetProj (V3d_Zpos, isYup);
2961       }
2962       else if (anArgCase == "-z")
2963       {
2964         aView->SetProj (V3d_Zneg, isYup);
2965       }
2966       else if (anArgCase == "+x+y+z")
2967       {
2968         aView->SetProj (V3d_XposYposZpos, isYup);
2969       }
2970       else if (anArgCase == "+x+y-z")
2971       {
2972         aView->SetProj (V3d_XposYposZneg, isYup);
2973       }
2974       else if (anArgCase == "+x-y+z")
2975       {
2976         aView->SetProj (V3d_XposYnegZpos, isYup);
2977       }
2978       else if (anArgCase == "+x-y-z")
2979       {
2980         aView->SetProj (V3d_XposYnegZneg, isYup);
2981       }
2982       else if (anArgCase == "-x+y+z")
2983       {
2984         aView->SetProj (V3d_XnegYposZpos, isYup);
2985       }
2986       else if (anArgCase == "-x+y-z")
2987       {
2988         aView->SetProj (V3d_XnegYposZneg, isYup);
2989       }
2990       else if (anArgCase == "-x-y+z")
2991       {
2992         aView->SetProj (V3d_XnegYnegZpos, isYup);
2993       }
2994       else if (anArgCase == "-x-y-z")
2995       {
2996         aView->SetProj (V3d_XnegYnegZneg, isYup);
2997       }
2998       else if (anArgCase == "+x+y")
2999       {
3000         aView->SetProj (V3d_XposYpos, isYup);
3001       }
3002       else if (anArgCase == "+x-y")
3003       {
3004         aView->SetProj (V3d_XposYneg, isYup);
3005       }
3006       else if (anArgCase == "-x+y")
3007       {
3008         aView->SetProj (V3d_XnegYpos, isYup);
3009       }
3010       else if (anArgCase == "-x-y")
3011       {
3012         aView->SetProj (V3d_XnegYneg, isYup);
3013       }
3014       else if (anArgCase == "+x+z")
3015       {
3016         aView->SetProj (V3d_XposZpos, isYup);
3017       }
3018       else if (anArgCase == "+x-z")
3019       {
3020         aView->SetProj (V3d_XposZneg, isYup);
3021       }
3022       else if (anArgCase == "-x+z")
3023       {
3024         aView->SetProj (V3d_XnegZpos, isYup);
3025       }
3026       else if (anArgCase == "-x-z")
3027       {
3028         aView->SetProj (V3d_XnegZneg, isYup);
3029       }
3030       else if (anArgCase == "+y+z")
3031       {
3032         aView->SetProj (V3d_YposZpos, isYup);
3033       }
3034       else if (anArgCase == "+y-z")
3035       {
3036         aView->SetProj (V3d_YposZneg, isYup);
3037       }
3038       else if (anArgCase == "-y+z")
3039       {
3040         aView->SetProj (V3d_YnegZpos, isYup);
3041       }
3042       else if (anArgCase == "-y-z")
3043       {
3044         aView->SetProj (V3d_YnegZneg, isYup);
3045       }
3046       else if (anArgIter + 1 < theNbArgs
3047             && anArgCase == "-frame"
3048             && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
3049       {
3050         TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
3051         aFrameDef.LowerCase();
3052         gp_Dir aRight, anUp;
3053         if (aFrameDef.Value (2) == aFrameDef.Value (4))
3054         {
3055           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3056           return 1;
3057         }
3058
3059         if (aFrameDef.Value (2) == 'x')
3060         {
3061           aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
3062         }
3063         else if (aFrameDef.Value (2) == 'y')
3064         {
3065           aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
3066         }
3067         else if (aFrameDef.Value (2) == 'z')
3068         {
3069           aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
3070         }
3071         else
3072         {
3073           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3074           return 1;
3075         }
3076
3077         if (aFrameDef.Value (4) == 'x')
3078         {
3079           anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
3080         }
3081         else if (aFrameDef.Value (4) == 'y')
3082         {
3083           anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
3084         }
3085         else if (aFrameDef.Value (4) == 'z')
3086         {
3087           anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
3088         }
3089         else
3090         {
3091           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3092           return 1;
3093         }
3094
3095         const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
3096         const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
3097         const gp_Dir aDir = anUp.Crossed (aRight);
3098         aCamera->SetCenter (gp_Pnt (0, 0, 0));
3099         aCamera->SetDirection (aDir);
3100         aCamera->SetUp (anUp);
3101         aCamera->OrthogonalizeUp();
3102
3103         aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
3104         aView->Update();
3105       }
3106       else
3107       {
3108         std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3109         return 1;
3110       }
3111     }
3112   }
3113
3114   if (!isGeneralCmd
3115     && theNbArgs != 1)
3116   {
3117     std::cout << "Syntax error: wrong number of arguments\n";
3118     return 1;
3119   }
3120   return 0;
3121 }
3122
3123 //==============================================================================
3124 //function : VHelp
3125 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
3126 //Draw arg : No args
3127 //==============================================================================
3128
3129 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3130 {
3131   di << "=========================\n";
3132   di << "F : FitAll\n";
3133   di << "T : TopView\n";
3134   di << "B : BottomView\n";
3135   di << "R : RightView\n";
3136   di << "L : LeftView\n";
3137   di << "A : AxonometricView\n";
3138   di << "D : ResetView\n";
3139
3140   di << "=========================\n";
3141   di << "S : Shading\n";
3142   di << "W : Wireframe\n";
3143   di << "H : HiddenLineRemoval\n";
3144   di << "U : Unset display mode\n";
3145   di << "Delete : Remove selection from viewer\n";
3146
3147   di << "=========================\n";
3148   di << "Selection mode \n";
3149   di << "0 : Shape\n";
3150   di << "1 : Vertex\n";
3151   di << "2 : Edge\n";
3152   di << "3 : Wire\n";
3153   di << "4 : Face\n";
3154   di << "5 : Shell\n";
3155   di << "6 : Solid\n";
3156   di << "7 : Compound\n";
3157
3158   di << "=========================\n";
3159   di << "< : Hilight next detected\n";
3160   di << "> : Hilight previous detected\n";
3161
3162   return 0;
3163 }
3164
3165 #ifdef _WIN32
3166
3167 static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
3168                                            UINT theMsg,
3169                                            WPARAM wParam,
3170                                            LPARAM lParam )
3171 {
3172   if (ViewerTest_myViews.IsEmpty())
3173   {
3174     return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3175   }
3176
3177   switch (theMsg)
3178   {
3179     case WM_CLOSE:
3180     {
3181       // Delete view from map of views
3182       ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
3183       return 0;
3184     }
3185     case WM_ACTIVATE:
3186     {
3187       if (LOWORD(wParam) == WA_CLICKACTIVE
3188        || LOWORD(wParam) == WA_ACTIVE
3189        || ViewerTest::CurrentView().IsNull())
3190       {
3191         // Activate inactive window
3192         if (VT_GetWindow().IsNull()
3193          || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3194         {
3195           ActivateView (FindViewIdByWindowHandle (theWinHandle));
3196         }
3197       }
3198       break;
3199     }
3200     default:
3201     {
3202       return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3203     }
3204   }
3205   return 0;
3206 }
3207
3208 static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
3209                                         UINT theMsg,
3210                                         WPARAM wParam,
3211                                         LPARAM lParam)
3212 {
3213   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3214   if (aView.IsNull())
3215   {
3216     return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3217   }
3218
3219   switch (theMsg)
3220   {
3221     case WM_PAINT:
3222     {
3223       PAINTSTRUCT aPaint;
3224       BeginPaint(theWinHandle, &aPaint);
3225       EndPaint  (theWinHandle, &aPaint);
3226       ViewerTest::CurrentEventManager()->ProcessExpose();
3227       break;
3228     }
3229     case WM_SIZE:
3230     {
3231       ViewerTest::CurrentEventManager()->ProcessConfigure();
3232       break;
3233     }
3234     case WM_MOVE:
3235     case WM_MOVING:
3236     case WM_SIZING:
3237     {
3238       switch (aView->RenderingParams().StereoMode)
3239       {
3240         case Graphic3d_StereoMode_RowInterlaced:
3241         case Graphic3d_StereoMode_ColumnInterlaced:
3242         case Graphic3d_StereoMode_ChessBoard:
3243         {
3244           // track window moves to reverse stereo pair
3245           aView->MustBeResized();
3246           aView->Update();
3247           break;
3248         }
3249         default:
3250           break;
3251       }
3252       break;
3253     }
3254     case WM_KEYUP:
3255     case WM_KEYDOWN:
3256     {
3257       const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
3258       if (aVKey != Aspect_VKey_UNKNOWN)
3259       {
3260         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3261         if (theMsg == WM_KEYDOWN)
3262         {
3263           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3264         }
3265         else
3266         {
3267           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3268         }
3269         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3270       }
3271       break;
3272     }
3273     case WM_LBUTTONUP:
3274     case WM_MBUTTONUP:
3275     case WM_RBUTTONUP:
3276     case WM_LBUTTONDOWN:
3277     case WM_MBUTTONDOWN:
3278     case WM_RBUTTONDOWN:
3279     {
3280       const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3281       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3282       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3283       switch (theMsg)
3284       {
3285         case WM_LBUTTONUP:
3286         case WM_LBUTTONDOWN:
3287           aButton = Aspect_VKeyMouse_LeftButton;
3288           break;
3289         case WM_MBUTTONUP:
3290         case WM_MBUTTONDOWN:
3291           aButton = Aspect_VKeyMouse_MiddleButton;
3292           break;
3293         case WM_RBUTTONUP:
3294         case WM_RBUTTONDOWN:
3295           aButton = Aspect_VKeyMouse_RightButton;
3296           break;
3297       }
3298       if (theMsg == WM_LBUTTONDOWN
3299        || theMsg == WM_MBUTTONDOWN
3300        || theMsg == WM_RBUTTONDOWN)
3301       {
3302         if (aButton == Aspect_VKeyMouse_LeftButton)
3303         {
3304           TheIsAnimating = Standard_False;
3305         }
3306
3307         SetFocus  (theWinHandle);
3308         SetCapture(theWinHandle);
3309         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3310       }
3311       else
3312       {
3313         ReleaseCapture();
3314         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3315       }
3316       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3317       break;
3318     }
3319     case WM_MOUSEWHEEL:
3320     {
3321       const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3322       const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
3323       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3324       Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
3325       POINT aCursorPnt = { aPos.x(), aPos.y() };
3326       if (ScreenToClient (theWinHandle, &aCursorPnt))
3327       {
3328         aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3329       }
3330
3331       ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3332       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3333       break;
3334     }
3335     case WM_MOUSEMOVE:
3336     {
3337       Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3338       Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (wParam);
3339       Aspect_VKeyFlags aFlags   = WNT_Window::MouseKeyFlagsFromEvent(wParam);
3340
3341       // don't make a slide-show from input events - fetch the actual mouse cursor position
3342       CURSORINFO aCursor;
3343       aCursor.cbSize = sizeof(aCursor);
3344       if (::GetCursorInfo (&aCursor) != FALSE)
3345       {
3346         POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
3347         if (ScreenToClient (theWinHandle, &aCursorPnt))
3348         {
3349           // as we override mouse position, we need overriding also mouse state
3350           aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3351           aButtons = WNT_Window::MouseButtonsAsync();
3352           aFlags   = WNT_Window::MouseKeyFlagsAsync();
3353         }
3354       }
3355
3356       if (VT_GetWindow().IsNull()
3357       || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3358       {
3359         // mouse move events come also for inactive windows
3360         break;
3361       }
3362
3363       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3364       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
3365       break;
3366     }
3367     default:
3368     {
3369       return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3370     }
3371   }
3372   return 0L;
3373 }
3374
3375 //==============================================================================
3376 //function : ViewerMainLoop
3377 //purpose  : Get a Event on the view and dispatch it
3378 //==============================================================================
3379
3380 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3381 {
3382   Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
3383   if (aViewCtrl.IsNull()
3384    || theNbArgs < 4)
3385   {
3386     return 0;
3387   }
3388
3389   aViewCtrl->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3390
3391   std::cout << "Start picking\n";
3392
3393   MSG aMsg;
3394   aMsg.wParam = 1;
3395   while (aViewCtrl->ToPickPoint())
3396   {
3397     // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
3398     if (GetMessageW (&aMsg, NULL, 0, 0))
3399     {
3400       TranslateMessage (&aMsg);
3401       DispatchMessageW (&aMsg);
3402     }
3403   }
3404
3405   std::cout << "Picking done\n";
3406   return 0;
3407 }
3408
3409 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
3410
3411 int min( int a, int b )
3412 {
3413   if( a<b )
3414     return a;
3415   else
3416     return b;
3417 }
3418
3419 int max( int a, int b )
3420 {
3421   if( a>b )
3422     return a;
3423   else
3424     return b;
3425 }
3426
3427 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3428 {
3429   static XEvent aReport;
3430   const Standard_Boolean toPick = theNbArgs > 0;
3431   if (theNbArgs > 0)
3432   {
3433     if (ViewerTest::CurrentEventManager().IsNull())
3434     {
3435       return 0;
3436     }
3437     ViewerTest::CurrentEventManager()->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3438   }
3439
3440   Display* aDisplay = GetDisplayConnection()->GetDisplay();
3441   XNextEvent (aDisplay, &aReport);
3442
3443   // Handle event for the chosen display connection
3444   switch (aReport.type)
3445   {
3446     case ClientMessage:
3447     {
3448       if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
3449       {
3450         // Close the window
3451         ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
3452         return toPick ? 0 : 1;
3453       }
3454       break;
3455     }
3456     case FocusIn:
3457     {
3458       // Activate inactive view
3459       Window aWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3460       if (aWindow != aReport.xfocus.window)
3461       {
3462         ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
3463       }
3464       break;
3465     }
3466     case Expose:
3467     {
3468       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3469       if (anXWindow == aReport.xexpose.window)
3470       {
3471         ViewerTest::CurrentEventManager()->ProcessExpose();
3472       }
3473
3474       // remove all the ExposureMask and process them at once
3475       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3476       {
3477         if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
3478         {
3479           break;
3480         }
3481       }
3482
3483       break;
3484     }
3485     case ConfigureNotify:
3486     {
3487       // remove all the StructureNotifyMask and process them at once
3488       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3489       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3490       {
3491         if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
3492         {
3493           break;
3494         }
3495       }
3496
3497       if (anXWindow == aReport.xconfigure.window)
3498       {
3499         ViewerTest::CurrentEventManager()->ProcessConfigure();
3500       }
3501       break;
3502     }
3503     case KeyPress:
3504     case KeyRelease:
3505     {
3506       XKeyEvent*   aKeyEvent = (XKeyEvent* )&aReport;
3507       const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
3508       const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
3509       if (aVKey != Aspect_VKey_UNKNOWN)
3510       {
3511         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3512         if (aReport.type == KeyPress)
3513         {
3514           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3515         }
3516         else
3517         {
3518           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3519         }
3520         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3521       }
3522       break;
3523     }
3524     case ButtonPress:
3525     case ButtonRelease:
3526     {
3527       const Graphic3d_Vec2i aPos (aReport.xbutton.x, aReport.xbutton.y);
3528       Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
3529       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3530       if (aReport.xbutton.button == Button1)
3531       {
3532         aButton = Aspect_VKeyMouse_LeftButton;
3533       }
3534       if (aReport.xbutton.button == Button2)
3535       {
3536         aButton = Aspect_VKeyMouse_MiddleButton;
3537       }
3538       if (aReport.xbutton.button == Button3)
3539       {
3540         aButton = Aspect_VKeyMouse_RightButton;
3541       }
3542
3543       if (aReport.xbutton.state & ControlMask)
3544       {
3545         aFlags |= Aspect_VKeyFlags_CTRL;
3546       }
3547       if (aReport.xbutton.state & ShiftMask)
3548       {
3549         aFlags |= Aspect_VKeyFlags_SHIFT;
3550       }
3551       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3552       {
3553         aFlags |= Aspect_VKeyFlags_ALT;
3554       }
3555
3556       if (aReport.xbutton.button == Button4
3557        || aReport.xbutton.button == Button5)
3558       {
3559         if (aReport.type != ButtonPress)
3560         {
3561           break;
3562         }
3563
3564         const double aDeltaF = (aReport.xbutton.button == Button4 ? 1.0 : -1.0);
3565         ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3566       }
3567       else if (aReport.type == ButtonPress)
3568       {
3569         if (aButton == Aspect_VKeyMouse_LeftButton)
3570         {
3571           TheIsAnimating = Standard_False;
3572         }
3573         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3574       }
3575       else
3576       {
3577         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3578       }
3579       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3580       break;
3581     }
3582     case MotionNotify:
3583     {
3584       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3585       if (anXWindow != aReport.xmotion.window)
3586       {
3587         break;
3588       }
3589
3590       // remove all the ButtonMotionMask and process them at once
3591       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3592       {
3593         if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
3594         {
3595           break;
3596         }
3597       }
3598
3599       Graphic3d_Vec2i aPos (aReport.xmotion.x, aReport.xmotion.y);
3600       Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
3601       Aspect_VKeyFlags aFlags   = Aspect_VKeyFlags_NONE;
3602       if ((aReport.xmotion.state & Button1Mask) != 0)
3603       {
3604         aButtons |= Aspect_VKeyMouse_LeftButton;
3605       }
3606       else if ((aReport.xmotion.state & Button2Mask) != 0)
3607       {
3608         aButtons |= Aspect_VKeyMouse_MiddleButton;
3609       }
3610       else if ((aReport.xmotion.state & Button3Mask) != 0)
3611       {
3612         aButtons |= Aspect_VKeyMouse_RightButton;
3613       }
3614
3615       if (aReport.xmotion.state & ControlMask)
3616       {
3617         aFlags |= Aspect_VKeyFlags_CTRL;
3618       }
3619       if (aReport.xmotion.state & ShiftMask)
3620       {
3621         aFlags |= Aspect_VKeyFlags_SHIFT;
3622       }
3623       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3624       {
3625         aFlags |= Aspect_VKeyFlags_ALT;
3626       }
3627
3628       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3629       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3630       break;
3631     }
3632   }
3633   return (!toPick || ViewerTest::CurrentEventManager()->ToPickPoint()) ? 1 : 0;
3634 }
3635
3636 //==============================================================================
3637 //function : VProcessEvents
3638 //purpose  : manage the event in the Viewer window (see Tcl_CreateFileHandler())
3639 //==============================================================================
3640 static void VProcessEvents (ClientData theDispX, int)
3641 {
3642   Display* aDispX = (Display* )theDispX;
3643   Handle(Aspect_DisplayConnection) aDispConn;
3644   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
3645        aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
3646   {
3647     const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
3648     if (aDispConnTmp->GetDisplay() == aDispX)
3649     {
3650       aDispConn = aDispConnTmp;
3651       break;
3652     }
3653   }
3654   if (aDispConn.IsNull())
3655   {
3656     std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
3657     return;
3658   }
3659
3660   // process new events in queue
3661   SetDisplayConnection (aDispConn);
3662   int aNbRemain = 0;
3663   for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
3664   {
3665     const int anEventResult = ViewerMainLoop (0, NULL);
3666     if (anEventResult == 0)
3667     {
3668       return;
3669     }
3670
3671     aNbRemain = XPending (aDispX);
3672     if (++anEventIter >= aNbEventsMax
3673      || aNbRemain <= 0)
3674     {
3675       break;
3676     }
3677   }
3678
3679   // Listening X events through Tcl_CreateFileHandler() callback is fragile,
3680   // it is possible that new events will arrive to queue before the end of this callback
3681   // so that either this callback should go into an infinite loop (blocking processing of other events)
3682   // or to keep unprocessed events till the next queue update (which can arrive not soon).
3683   // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
3684   if (aNbRemain != 0)
3685   {
3686     XEvent aDummyEvent;
3687     memset (&aDummyEvent, 0, sizeof(aDummyEvent));
3688     aDummyEvent.type = ClientMessage;
3689     aDummyEvent.xclient.format = 32;
3690     XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
3691     XFlush (aDispX);
3692   }
3693
3694   if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
3695   {
3696     SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
3697   }
3698 }
3699 #endif
3700
3701 //==============================================================================
3702 //function : OSWindowSetup
3703 //purpose  : Setup for the X11 window to be able to cath the event
3704 //==============================================================================
3705
3706
3707 static void OSWindowSetup()
3708 {
3709 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
3710   // X11
3711
3712   Window  window   = VT_GetWindow()->XWindow();
3713   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
3714   Display *aDisplay = GetDisplayConnection()->GetDisplay();
3715   XSynchronize(aDisplay, 1);
3716
3717   // X11 : For keyboard on SUN
3718   XWMHints wmhints;
3719   wmhints.flags = InputHint;
3720   wmhints.input = 1;
3721
3722   XSetWMHints( aDisplay, window, &wmhints);
3723
3724   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask | KeyReleaseMask |
3725     ButtonPressMask | ButtonReleaseMask |
3726     StructureNotifyMask |
3727     PointerMotionMask |
3728     Button1MotionMask | Button2MotionMask |
3729     Button3MotionMask | FocusChangeMask
3730     );
3731   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
3732   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
3733
3734   XSynchronize(aDisplay, 0);
3735
3736 #else
3737   // _WIN32
3738 #endif
3739
3740 }
3741
3742 //==============================================================================
3743 //function : VFit
3744 //purpose  :
3745 //==============================================================================
3746
3747 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
3748 {
3749   const Handle(V3d_View) aView = ViewerTest::CurrentView();
3750   if (aView.IsNull())
3751   {
3752     std::cout << "Error: no active viewer!\n";
3753     return 1;
3754   }
3755
3756   Standard_Boolean toFit = Standard_True;
3757   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
3758   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3759   {
3760     TCollection_AsciiString anArg (theArgv[anArgIter]);
3761     anArg.LowerCase();
3762     if (anUpdateTool.parseRedrawMode (anArg))
3763     {
3764       continue;
3765     }
3766     else if (anArg == "-selected")
3767     {
3768       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
3769       toFit = Standard_False;
3770     }
3771     else
3772     {
3773       std::cout << "Syntax error at '" << anArg << "'\n";
3774     }
3775   }
3776
3777   if (toFit)
3778   {
3779     aView->FitAll (0.01, Standard_False);
3780   }
3781   return 0;
3782 }
3783
3784 //=======================================================================
3785 //function : VFitArea
3786 //purpose  : Fit view to show area located between two points
3787 //         : given in world 2D or 3D coordinates.
3788 //=======================================================================
3789 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
3790 {
3791   Handle(V3d_View) aView = ViewerTest::CurrentView();
3792   if (aView.IsNull())
3793   {
3794     std::cerr << theArgVec[0] << "Error: No active view.\n";
3795     return 1;
3796   }
3797
3798   // Parse arguments.
3799   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
3800   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
3801
3802   if (theArgNb == 5)
3803   {
3804     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3805     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3806     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
3807     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
3808   }
3809   else if (theArgNb == 7)
3810   {
3811     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3812     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3813     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
3814     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
3815     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
3816     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
3817   }
3818   else
3819   {
3820     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
3821     theDI.PrintHelp(theArgVec[0]);
3822     return 1;
3823   }
3824
3825   // Convert model coordinates to view space
3826   Handle(Graphic3d_Camera) aCamera = aView->Camera();
3827   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
3828   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
3829
3830   // Determine fit area
3831   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
3832   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
3833
3834   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
3835
3836   if (aDiagonal < Precision::Confusion())
3837   {
3838     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
3839     return 1;
3840   }
3841
3842   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
3843   return 0;
3844 }
3845
3846 //==============================================================================
3847 //function : VZFit
3848 //purpose  : ZFitall, no DRAW arguments
3849 //Draw arg : No args
3850 //==============================================================================
3851 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3852 {
3853   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
3854
3855   if (aCurrentView.IsNull())
3856   {
3857     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
3858     return 1;
3859   }
3860
3861   if (theArgsNb == 1)
3862   {
3863     aCurrentView->ZFitAll();
3864     aCurrentView->Redraw();
3865     return 0;
3866   }
3867
3868   Standard_Real aScale = 1.0;
3869
3870   if (theArgsNb >= 2)
3871   {
3872     aScale = Draw::Atoi (theArgVec[1]);
3873   }
3874
3875   aCurrentView->ZFitAll (aScale);
3876   aCurrentView->Redraw();
3877
3878   return 0;
3879 }
3880
3881 //==============================================================================
3882 //function : VRepaint
3883 //purpose  :
3884 //==============================================================================
3885 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
3886 {
3887   Handle(V3d_View) aView = ViewerTest::CurrentView();
3888   if (aView.IsNull())
3889   {
3890     std::cout << "Error: no active viewer!\n";
3891     return 1;
3892   }
3893
3894   Standard_Boolean isImmediateUpdate = Standard_False;
3895   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3896   {
3897     TCollection_AsciiString anArg (theArgVec[anArgIter]);
3898     anArg.LowerCase();
3899     if (anArg == "-immediate"
3900      || anArg == "-imm")
3901     {
3902       isImmediateUpdate = Standard_True;
3903       if (anArgIter + 1 < theArgNb
3904        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
3905       {
3906         ++anArgIter;
3907       }
3908     }
3909     else if (anArg == "-continuous"
3910           || anArg == "-cont"
3911           || anArg == "-fps"
3912           || anArg == "-framerate")
3913     {
3914       Standard_Real aFps = -1.0;
3915       if (anArgIter + 1 < theArgNb
3916        && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
3917       {
3918         aFps = Draw::Atof (theArgVec[++anArgIter]);
3919       }
3920
3921       ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
3922       if (Abs (aFps) >= 1.0)
3923       {
3924         aRedrawer.Start (aView->Window(), aFps);
3925       }
3926       else
3927       {
3928         aRedrawer.Stop();
3929       }
3930     }
3931     else
3932     {
3933       std::cout << "Syntax error at '" << anArg << "'\n";
3934       return 1;
3935     }
3936   }
3937
3938   if (isImmediateUpdate)
3939   {
3940     aView->RedrawImmediate();
3941   }
3942   else
3943   {
3944     aView->Redraw();
3945   }
3946   return 0;
3947 }
3948
3949 //==============================================================================
3950 //function : VClear
3951 //purpose  : Remove all the object from the viewer
3952 //Draw arg : No args
3953 //==============================================================================
3954
3955 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3956 {
3957   Handle(V3d_View) V = ViewerTest::CurrentView();
3958   if(!V.IsNull())
3959     ViewerTest::Clear();
3960   return 0;
3961 }
3962
3963 //==============================================================================
3964 //function : VPick
3965 //purpose  :
3966 //==============================================================================
3967
3968 static int VPick (Draw_Interpretor& ,
3969                   Standard_Integer theNbArgs,
3970                   const char** theArgVec)
3971 {
3972   if (ViewerTest::CurrentView().IsNull())
3973   {
3974     return 1;
3975   }
3976
3977   if (theNbArgs < 4)
3978   {
3979     std::cout << "Syntax error: Invalid number of arguments\n";
3980     return 1;
3981   }
3982
3983   while (ViewerMainLoop (theNbArgs, theArgVec))
3984   {
3985     //
3986   }
3987
3988   return 0;
3989 }
3990
3991 namespace
3992 {
3993
3994   //! Changes the background
3995   //! @param theDrawInterpretor the interpreter of the Draw Harness application
3996   //! @param theNumberOfCommandLineArguments the number of passed command line arguments
3997   //! @param theCommandLineArguments the array of command line arguments
3998   //! @return TCL_OK if changing was successful, or TCL_ERROR otherwise
3999   static int vbackground (Draw_Interpretor&      theDrawInterpretor,
4000                           const Standard_Integer theNumberOfCommandLineArguments,
4001                           const char** const     theCommandLineArguments)
4002   {
4003     if (theNumberOfCommandLineArguments < 1)
4004     {
4005       return TCL_ERROR;
4006     }
4007     BackgroundChanger aBackgroundChanger;
4008     if (!aBackgroundChanger.ProcessCommandLine (theDrawInterpretor,
4009                                                 theNumberOfCommandLineArguments,
4010                                                 theCommandLineArguments))
4011     {
4012       theDrawInterpretor << "Wrong command arguments.\n"
4013                             "Type 'help "
4014                          << theCommandLineArguments[0] << "' for information about command options and its arguments.\n";
4015       return TCL_ERROR;
4016     }
4017     return TCL_OK;
4018   }
4019
4020 } // namespace
4021
4022 //==============================================================================
4023 //function : VScale
4024 //purpose  : View Scaling
4025 //==============================================================================
4026
4027 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4028 {
4029   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4030   if ( V3dView.IsNull() ) return 1;
4031
4032   if ( argc != 4 ) {
4033     di << argv[0] << "Invalid number of arguments\n";
4034     return 1;
4035   }
4036   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
4037   return 0;
4038 }
4039 //==============================================================================
4040 //function : VZBuffTrihedron
4041 //purpose  :
4042 //==============================================================================
4043
4044 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
4045                             Standard_Integer  theArgNb,
4046                             const char**      theArgVec)
4047 {
4048   Handle(V3d_View) aView = ViewerTest::CurrentView();
4049   if (aView.IsNull())
4050   {
4051     std::cout << "Error: no active viewer!\n";
4052     return 1;
4053   }
4054
4055   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4056
4057   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
4058   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
4059   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
4060   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
4061   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
4062   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
4063   Standard_Real                 aScale        = 0.1;
4064   Standard_Real                 aSizeRatio    = 0.8;
4065   Standard_Real                 anArrowDiam   = 0.05;
4066   Standard_Integer              aNbFacets     = 12;
4067   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4068   {
4069     Standard_CString        anArg = theArgVec[anArgIter];
4070     TCollection_AsciiString aFlag (anArg);
4071     aFlag.LowerCase();
4072     if (anUpdateTool.parseRedrawMode (aFlag))
4073     {
4074       continue;
4075     }
4076     else if (aFlag == "-on")
4077     {
4078       continue;
4079     }
4080     else if (aFlag == "-off")
4081     {
4082       aView->TriedronErase();
4083       return 0;
4084     }
4085     else if (aFlag == "-pos"
4086           || aFlag == "-position"
4087           || aFlag == "-corner")
4088     {
4089       if (++anArgIter >= theArgNb)
4090       {
4091         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4092         return 1;
4093       }
4094
4095       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
4096       aPosName.LowerCase();
4097       if (aPosName == "center")
4098       {
4099         aPosition = Aspect_TOTP_CENTER;
4100       }
4101       else if (aPosName == "left_lower"
4102             || aPosName == "lower_left"
4103             || aPosName == "leftlower"
4104             || aPosName == "lowerleft")
4105       {
4106         aPosition = Aspect_TOTP_LEFT_LOWER;
4107       }
4108       else if (aPosName == "left_upper"
4109             || aPosName == "upper_left"
4110             || aPosName == "leftupper"
4111             || aPosName == "upperleft")
4112       {
4113         aPosition = Aspect_TOTP_LEFT_UPPER;
4114       }
4115       else if (aPosName == "right_lower"
4116             || aPosName == "lower_right"
4117             || aPosName == "rightlower"
4118             || aPosName == "lowerright")
4119       {
4120         aPosition = Aspect_TOTP_RIGHT_LOWER;
4121       }
4122       else if (aPosName == "right_upper"
4123             || aPosName == "upper_right"
4124             || aPosName == "rightupper"
4125             || aPosName == "upperright")
4126       {
4127         aPosition = Aspect_TOTP_RIGHT_UPPER;
4128       }
4129       else
4130       {
4131         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
4132         return 1;
4133       }
4134     }
4135     else if (aFlag == "-type")
4136     {
4137       if (++anArgIter >= theArgNb)
4138       {
4139         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4140         return 1;
4141       }
4142
4143       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
4144       aTypeName.LowerCase();
4145       if (aTypeName == "wireframe"
4146        || aTypeName == "wire")
4147       {
4148         aVisType = V3d_WIREFRAME;
4149       }
4150       else if (aTypeName == "zbuffer"
4151             || aTypeName == "shaded")
4152       {
4153         aVisType = V3d_ZBUFFER;
4154       }
4155       else
4156       {
4157         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
4158       }
4159     }
4160     else if (aFlag == "-scale")
4161     {
4162       if (++anArgIter >= theArgNb)
4163       {
4164         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4165         return 1;
4166       }
4167
4168       aScale = Draw::Atof (theArgVec[anArgIter]);
4169     }
4170     else if (aFlag == "-size"
4171           || aFlag == "-sizeratio")
4172     {
4173       if (++anArgIter >= theArgNb)
4174       {
4175         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4176         return 1;
4177       }
4178
4179       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
4180     }
4181     else if (aFlag == "-arrowdiam"
4182           || aFlag == "-arrowdiameter")
4183     {
4184       if (++anArgIter >= theArgNb)
4185       {
4186         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4187         return 1;
4188       }
4189
4190       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
4191     }
4192     else if (aFlag == "-nbfacets")
4193     {
4194       if (++anArgIter >= theArgNb)
4195       {
4196         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4197         return 1;
4198       }
4199
4200       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
4201     }
4202     else if (aFlag == "-colorlabel"
4203           || aFlag == "-colorlabels")
4204     {
4205       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4206                                                            theArgVec + anArgIter + 1,
4207                                                            aLabelsColor);
4208       if (aNbParsed == 0)
4209       {
4210         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4211         return 1;
4212       }
4213       anArgIter += aNbParsed;
4214     }
4215     else if (aFlag == "-colorarrowx")
4216     {
4217       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4218                                                            theArgVec + anArgIter + 1,
4219                                                            anArrowColorX);
4220       if (aNbParsed == 0)
4221       {
4222         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4223         return 1;
4224       }
4225       anArgIter += aNbParsed;
4226     }
4227     else if (aFlag == "-colorarrowy")
4228     {
4229       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4230                                                            theArgVec + anArgIter + 1,
4231                                                            anArrowColorY);
4232       if (aNbParsed == 0)
4233       {
4234         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4235         return 1;
4236       }
4237       anArgIter += aNbParsed;
4238     }
4239     else if (aFlag == "-colorarrowz")
4240     {
4241       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4242                                                            theArgVec + anArgIter + 1,
4243                                                            anArrowColorZ);
4244       if (aNbParsed == 0)
4245       {
4246         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4247         return 1;
4248       }
4249       anArgIter += aNbParsed;
4250     }
4251     else
4252     {
4253       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4254       return 1;
4255     }
4256   }
4257
4258   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
4259                                aSizeRatio, anArrowDiam, aNbFacets);
4260   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
4261   aView->ZFitAll();
4262   return 0;
4263 }
4264
4265 //==============================================================================
4266 //function : VRotate
4267 //purpose  : Camera Rotating
4268 //==============================================================================
4269
4270 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
4271 {
4272   Handle(V3d_View) aView = ViewerTest::CurrentView();
4273   if (aView.IsNull())
4274   {
4275     std::cout << "No active view!\n";
4276     return 1;
4277   }
4278
4279   Standard_Boolean hasFlags = Standard_False;
4280   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4281   {
4282     Standard_CString        anArg (theArgVec[anArgIter]);
4283     TCollection_AsciiString aFlag (anArg);
4284     aFlag.LowerCase();
4285     if (aFlag == "-mousestart"
4286      || aFlag == "-mousefrom")
4287     {
4288       hasFlags = Standard_True;
4289       if (anArgIter + 2 >= theArgNb)
4290       {
4291         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4292         return 1;
4293       }
4294
4295       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4296       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4297       aView->StartRotation (anX, anY);
4298     }
4299     else if (aFlag == "-mousemove")
4300     {
4301       hasFlags = Standard_True;
4302       if (anArgIter + 2 >= theArgNb)
4303       {
4304         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4305         return 1;
4306       }
4307
4308       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4309       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4310       aView->Rotation (anX, anY);
4311     }
4312     else if (theArgNb != 4
4313           && theArgNb != 7)
4314     {
4315       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4316       return 1;
4317     }
4318   }
4319
4320   if (hasFlags)
4321   {
4322     return 0;
4323   }
4324   else if (theArgNb == 4)
4325   {
4326     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4327     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4328     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4329     aView->Rotate (anAX, anAY, anAZ);
4330     return 0;
4331   }
4332   else if (theArgNb == 7)
4333   {
4334     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4335     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4336     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4337
4338     Standard_Real anX = Draw::Atof (theArgVec[4]);
4339     Standard_Real anY = Draw::Atof (theArgVec[5]);
4340     Standard_Real anZ = Draw::Atof (theArgVec[6]);
4341
4342     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
4343     return 0;
4344   }
4345
4346   std::cout << "Error: Invalid number of arguments\n";
4347   return 1;
4348 }
4349
4350 //==============================================================================
4351 //function : VZoom
4352 //purpose  : View zoom in / out (relative to current zoom)
4353 //==============================================================================
4354
4355 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4356   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4357   if ( V3dView.IsNull() ) {
4358     return 1;
4359   }
4360
4361   if ( argc == 2 ) {
4362     Standard_Real coef = Draw::Atof(argv[1]);
4363     if ( coef <= 0.0 ) {
4364       di << argv[1] << "Invalid value\n";
4365       return 1;
4366     }
4367     V3dView->SetZoom( Draw::Atof(argv[1]) );
4368     return 0;
4369   } else {
4370     di << argv[0] << " Invalid number of arguments\n";
4371     return 1;
4372   }
4373 }
4374
4375 //==============================================================================
4376 //function : VPan
4377 //purpose  : View panning (in pixels)
4378 //==============================================================================
4379
4380 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4381   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4382   if ( V3dView.IsNull() ) return 1;
4383
4384   if ( argc == 3 ) {
4385     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
4386     return 0;
4387   } else {
4388     di << argv[0] << " Invalid number of arguments\n";
4389     return 1;
4390   }
4391 }
4392
4393 //==============================================================================
4394 //function : VPlace
4395 //purpose  : Place the point (in pixels) at the center of the window
4396 //==============================================================================
4397 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
4398 {
4399   Handle(V3d_View) aView = ViewerTest::CurrentView();
4400   if (aView.IsNull())
4401   {
4402     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
4403     return 1;
4404   }
4405
4406   if (theArgNb != 3)
4407   {
4408     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
4409     return 1;
4410   }
4411
4412   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
4413
4414   return 0;
4415 }
4416
4417 static int VColorScale (Draw_Interpretor& theDI,
4418                         Standard_Integer  theArgNb,
4419                         const char**      theArgVec)
4420 {
4421   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4422   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
4423   if (aContext.IsNull())
4424   {
4425     std::cout << "Error: no active view!\n";
4426     return 1;
4427   }
4428   if (theArgNb <= 1)
4429   {
4430     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
4431     return 1;
4432   }
4433
4434   Handle(AIS_ColorScale) aColorScale;
4435   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
4436   {
4437     // find existing object
4438     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
4439     if (aColorScale.IsNull())
4440     {
4441       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
4442       return 1;
4443     }
4444   }
4445
4446   if (theArgNb <= 2)
4447   {
4448     if (aColorScale.IsNull())
4449     {
4450       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
4451       return 1;
4452     }
4453
4454     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
4455           << "Min range: "            << aColorScale->GetMin() << "\n"
4456           << "Max range: "            << aColorScale->GetMax() << "\n"
4457           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
4458           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
4459           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
4460           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
4461           << "Label position: ";
4462     switch (aColorScale->GetLabelPosition())
4463     {
4464       case Aspect_TOCSP_NONE:
4465         theDI << "None\n";
4466         break;
4467       case Aspect_TOCSP_LEFT:
4468         theDI << "Left\n";
4469         break;
4470       case Aspect_TOCSP_RIGHT:
4471         theDI << "Right\n";
4472         break;
4473       case Aspect_TOCSP_CENTER:
4474         theDI << "Center\n";
4475         break;
4476     }
4477     return 0;
4478   }
4479
4480   if (aColorScale.IsNull())
4481   {
4482     aColorScale = new AIS_ColorScale();
4483     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4484     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4485   }
4486
4487   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
4488   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
4489   {
4490     Standard_CString        anArg = theArgVec[anArgIter];
4491     TCollection_AsciiString aFlag (anArg);
4492     aFlag.LowerCase();
4493     if (anUpdateTool.parseRedrawMode (aFlag))
4494     {
4495       continue;
4496     }
4497     else if (aFlag == "-range")
4498     {
4499       if (anArgIter + 3 >= theArgNb)
4500       {
4501         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4502         return 1;
4503       }
4504
4505       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
4506       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
4507       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
4508       if (!aRangeMin.IsRealValue()
4509        || !aRangeMax.IsRealValue())
4510       {
4511         std::cout << "Error: the range values should be real!\n";
4512         return 1;
4513       }
4514       else if (!aNbIntervals.IsIntegerValue())
4515       {
4516         std::cout << "Error: the number of intervals should be integer!\n";
4517         return 1;
4518       }
4519
4520       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
4521       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
4522     }
4523     else if (aFlag == "-font")
4524     {
4525       if (anArgIter + 1 >= theArgNb)
4526       {
4527         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4528         return 1;
4529       }
4530       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
4531       if (!aFontArg.IsIntegerValue())
4532       {
4533         std::cout << "Error: HeightFont value should be integer!\n";
4534         return 1;
4535       }
4536
4537       aColorScale->SetTextHeight (aFontArg.IntegerValue());
4538       anArgIter += 1;
4539     }
4540     else if (aFlag == "-textpos")
4541     {
4542       if (anArgIter + 1 >= theArgNb)
4543       {
4544         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4545         return 1;
4546       }
4547
4548       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
4549       aTextPosArg.LowerCase();
4550       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
4551       if (aTextPosArg == "none")
4552       {
4553         aLabPosition = Aspect_TOCSP_NONE;
4554       }
4555       else if (aTextPosArg == "left")
4556       {
4557         aLabPosition = Aspect_TOCSP_LEFT;
4558       }
4559       else if (aTextPosArg == "right")
4560       {
4561         aLabPosition = Aspect_TOCSP_RIGHT;
4562       }
4563       else if (aTextPosArg == "center")
4564       {
4565         aLabPosition = Aspect_TOCSP_CENTER;
4566       }
4567       else
4568       {
4569         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
4570         return 1;
4571       }
4572       aColorScale->SetLabelPosition (aLabPosition);
4573     }
4574     else if (aFlag == "-logarithmic"
4575           || aFlag == "-log")
4576     {
4577       if (anArgIter + 1 >= theArgNb)
4578       {
4579         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4580         return 1;
4581       }
4582
4583       Standard_Boolean IsLog;
4584       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
4585       {
4586         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4587         return 1;
4588       }
4589       aColorScale->SetLogarithmic (IsLog);
4590     }
4591     else if (aFlag == "-huerange"
4592           || aFlag == "-hue")
4593     {
4594       if (anArgIter + 2 >= theArgNb)
4595       {
4596         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4597         return 1;
4598       }
4599
4600       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
4601       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
4602       aColorScale->SetHueRange (aHueMin, aHueMax);
4603     }
4604     else if (aFlag == "-colorrange")
4605     {
4606       Quantity_Color aColorMin, aColorMax;
4607       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4608                                                             theArgVec + (anArgIter + 1),
4609                                                             aColorMin);
4610       anArgIter += aNbParsed1;
4611       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4612                                                             theArgVec + (anArgIter + 1),
4613                                                             aColorMax);
4614       anArgIter += aNbParsed2;
4615       if (aNbParsed1 == 0
4616        || aNbParsed2 == 0)
4617       {
4618         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4619         return 1;
4620       }
4621
4622       aColorScale->SetColorRange (aColorMin, aColorMax);
4623     }
4624     else if (aFlag == "-reversed"
4625           || aFlag == "-inverted"
4626           || aFlag == "-topdown"
4627           || aFlag == "-bottomup")
4628     {
4629       Standard_Boolean toEnable = Standard_True;
4630       if (anArgIter + 1 < theArgNb
4631        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
4632       {
4633         ++anArgIter;
4634       }
4635       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
4636     }
4637     else if (aFlag == "-smooth"
4638           || aFlag == "-smoothtransition")
4639     {
4640       Standard_Boolean toEnable = Standard_True;
4641       if (anArgIter + 1 < theArgNb
4642        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4643       {
4644         ++anArgIter;
4645       }
4646       aColorScale->SetSmoothTransition (toEnable);
4647     }
4648     else if (aFlag == "-xy")
4649     {
4650       if (anArgIter + 2 >= theArgNb)
4651       {
4652         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4653         return 1;
4654       }
4655
4656       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
4657       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
4658       if (!anX.IsIntegerValue()
4659        || !anY.IsIntegerValue())
4660       {
4661         std::cout << "Error: coordinates should be integer values!\n";
4662         return 1;
4663       }
4664
4665       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
4666     }
4667     else if (aFlag == "-width"
4668           || aFlag == "-w"
4669           || aFlag == "-breadth")
4670     {
4671       if (anArgIter + 1 >= theArgNb)
4672       {
4673         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4674         return 1;
4675       }
4676
4677       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
4678       if (!aBreadth.IsIntegerValue())
4679       {
4680         std::cout << "Error: a width should be an integer value!\n";
4681         return 1;
4682       }
4683       aColorScale->SetBreadth (aBreadth.IntegerValue());
4684     }
4685     else if (aFlag == "-height"
4686           || aFlag == "-h")
4687     {
4688       if (anArgIter + 1 >= theArgNb)
4689       {
4690         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4691         return 1;
4692       }
4693
4694       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
4695       if (!aHeight.IsIntegerValue())
4696       {
4697         std::cout << "Error: a width should be an integer value!\n";
4698         return 1;
4699       }
4700       aColorScale->SetHeight (aHeight.IntegerValue());
4701     }
4702     else if (aFlag == "-color")
4703     {
4704       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4705       {
4706         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
4707         return 1;
4708       }
4709       else if (anArgIter + 2 >= theArgNb)
4710       {
4711         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4712         return 1;
4713       }
4714
4715       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
4716       if (!anInd.IsIntegerValue())
4717       {
4718         std::cout << "Error: Index value should be integer!\n";
4719         return 1;
4720       }
4721       const Standard_Integer anIndex = anInd.IntegerValue();
4722       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
4723       {
4724         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
4725         return 1;
4726       }
4727
4728       Quantity_Color aColor;
4729       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4730                                                            theArgVec + (anArgIter + 1),
4731                                                            aColor);
4732       if (aNbParsed == 0)
4733       {
4734         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4735         return 1;
4736       }
4737       aColorScale->SetIntervalColor (aColor, anIndex);
4738       aColorScale->SetColorType (Aspect_TOCSD_USER);
4739       anArgIter += aNbParsed;
4740     }
4741     else if (aFlag == "-label")
4742     {
4743       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4744       {
4745         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4746         return 1;
4747       }
4748       else if (anArgIter + 2 >= theArgNb)
4749       {
4750         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4751         return 1;
4752       }
4753
4754       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4755       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4756       {
4757         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4758         return 1;
4759       }
4760
4761       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4762       aColorScale->SetLabel     (aText, anIndex);
4763       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4764       anArgIter += 2;
4765     }
4766     else if (aFlag == "-labelat"
4767           || aFlag == "-labat"
4768           || aFlag == "-labelatborder"
4769           || aFlag == "-labatborder"
4770           || aFlag == "-labelatcenter"
4771           || aFlag == "-labatcenter")
4772     {
4773       Standard_Boolean toEnable = Standard_True;
4774       if (aFlag == "-labelat"
4775        || aFlag == "-labat")
4776       {
4777         Standard_Integer aLabAtBorder = -1;
4778         if (++anArgIter >= theArgNb)
4779         {
4780           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4781           anAtBorder.LowerCase();
4782           if (anAtBorder == "border")
4783           {
4784             aLabAtBorder = 1;
4785           }
4786           else if (anAtBorder == "center")
4787           {
4788             aLabAtBorder = 0;
4789           }
4790         }
4791         if (aLabAtBorder == -1)
4792         {
4793           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4794           return 1;
4795         }
4796         toEnable = (aLabAtBorder == 1);
4797       }
4798       else if (anArgIter + 1 < theArgNb
4799             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4800       {
4801         ++anArgIter;
4802       }
4803       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4804                                   || aFlag == "-labatcenter"
4805                                    ? !toEnable
4806                                    :  toEnable);
4807     }
4808     else if (aFlag == "-colors")
4809     {
4810       Aspect_SequenceOfColor aSeq;
4811       for (;;)
4812       {
4813         Quantity_Color aColor;
4814         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4815                                                              theArgVec + (anArgIter + 1),
4816                                                              aColor);
4817         if (aNbParsed == 0)
4818         {
4819           break;
4820         }
4821         anArgIter += aNbParsed;
4822         aSeq.Append (aColor);
4823       }
4824       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4825       {
4826         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4827                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4828         return 1;
4829       }
4830
4831       aColorScale->SetColors    (aSeq);
4832       aColorScale->SetColorType (Aspect_TOCSD_USER);
4833     }
4834     else if (aFlag == "-labels"
4835           || aFlag == "-freelabels")
4836     {
4837       if (anArgIter + 1 >= theArgNb)
4838       {
4839         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4840         return 1;
4841       }
4842
4843       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4844                                  ? aColorScale->GetNumberOfIntervals() + 1
4845                                  : aColorScale->GetNumberOfIntervals();
4846       if (aFlag == "-freelabels")
4847       {
4848         ++anArgIter;
4849         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4850       }
4851       if (anArgIter + aNbLabels >= theArgNb)
4852       {
4853         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4854         return 1;
4855       }
4856
4857       TColStd_SequenceOfExtendedString aSeq;
4858       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4859       {
4860         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4861       }
4862       aColorScale->SetLabels (aSeq);
4863       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4864     }
4865     else if (aFlag == "-title")
4866     {
4867       if (anArgIter + 1 >= theArgNb)
4868       {
4869         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4870         return 1;
4871       }
4872
4873       Standard_Boolean isTwoArgs = Standard_False;
4874       if (anArgIter + 2 < theArgNb)
4875       {
4876         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4877         aSecondArg.LowerCase();
4878       Standard_DISABLE_DEPRECATION_WARNINGS
4879         if (aSecondArg == "none")
4880         {
4881           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4882           isTwoArgs = Standard_True;
4883         }
4884         else if (aSecondArg == "left")
4885         {
4886           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4887           isTwoArgs = Standard_True;
4888         }
4889         else if (aSecondArg == "right")
4890         {
4891           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4892           isTwoArgs = Standard_True;
4893         }
4894         else if (aSecondArg == "center")
4895         {
4896           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4897           isTwoArgs = Standard_True;
4898         }
4899       Standard_ENABLE_DEPRECATION_WARNINGS
4900       }
4901
4902       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4903       if (isTwoArgs)
4904       {
4905         anArgIter += 1;
4906       }
4907       anArgIter += 1;
4908     }
4909     else if (aFlag == "-demoversion"
4910           || aFlag == "-demo")
4911     {
4912       aColorScale->SetPosition (0, 0);
4913       aColorScale->SetTextHeight (16);
4914       aColorScale->SetRange (0.0, 100.0);
4915       aColorScale->SetNumberOfIntervals (10);
4916       aColorScale->SetBreadth (0);
4917       aColorScale->SetHeight  (0);
4918       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4919       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4920       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4921     }
4922     else if (aFlag == "-findcolor")
4923     {
4924       if (anArgIter + 1 >= theArgNb)
4925       {
4926         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4927         return 1;
4928       }
4929
4930       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4931
4932       if (!anArg1.IsRealValue())
4933       {
4934         std::cout << "Error: the value should be real!\n";
4935         return 1;
4936       }
4937
4938       Quantity_Color aColor;
4939       aColorScale->FindColor (anArg1.RealValue(), aColor);
4940       theDI << Quantity_Color::StringName (aColor.Name());
4941       return 0;
4942     }
4943     else
4944     {
4945       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4946       return 1;
4947     }
4948   }
4949
4950   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4951   aView->Window()->Size (aWinWidth, aWinHeight);
4952   if (aColorScale->GetBreadth() == 0)
4953   {
4954     aColorScale->SetBreadth (aWinWidth);
4955   }
4956   if (aColorScale->GetHeight() == 0)
4957   {
4958     aColorScale->SetHeight (aWinHeight);
4959   }
4960   aColorScale->SetToUpdate();
4961   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4962   return 0;
4963 }
4964
4965 //==============================================================================
4966 //function : VGraduatedTrihedron
4967 //purpose  : Displays or hides a graduated trihedron
4968 //==============================================================================
4969 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4970                                   Quantity_Color& theColor)
4971 {
4972   Quantity_NameOfColor aColorName;
4973   TCollection_AsciiString aVal = theValue;
4974   aVal.UpperCase();
4975   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4976   {
4977     return Standard_False;
4978   }
4979   theColor = Quantity_Color (aColorName);
4980   return Standard_True;
4981 }
4982
4983 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4984 {
4985   if (theArgNum < 2)
4986   {
4987     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4988               << theArgs[0] <<"' for more information.\n";
4989     return 1;  //TCL_ERROR
4990   }
4991
4992   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4993   TCollection_AsciiString aParseKey;
4994   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4995   {
4996     TCollection_AsciiString anArg (theArgs [anArgIt]);
4997
4998     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4999     {
5000       aParseKey = anArg;
5001       aParseKey.Remove (1);
5002       aParseKey.LowerCase();
5003       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
5004       continue;
5005     }
5006
5007     if (aParseKey.IsEmpty())
5008     {
5009       continue;
5010     }
5011
5012     aMapOfArgs(aParseKey)->Append (anArg);
5013   }
5014
5015   // Check parameters
5016   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
5017        aMapIt.More(); aMapIt.Next())
5018   {
5019     const TCollection_AsciiString& aKey = aMapIt.Key();
5020     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
5021
5022     // Bool key, without arguments
5023     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
5024         && anArgs->IsEmpty())
5025     {
5026       continue;
5027     }
5028
5029     // One argument
5030     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
5031           && anArgs->Length() == 1)
5032     {
5033       continue;
5034     }
5035
5036     // On/off arguments
5037     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
5038         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
5039         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
5040         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
5041         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
5042     {
5043       continue;
5044     }
5045
5046     // One string argument
5047     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
5048           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
5049           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5050     {
5051       continue;
5052     }
5053
5054     // One integer argument
5055     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
5056           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
5057           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
5058           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
5059          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
5060     {
5061       continue;
5062     }
5063
5064     // One real argument
5065     if ( aKey.IsEqual ("arrowlength")
5066          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
5067     {
5068       continue;
5069     }
5070
5071     // Two string arguments
5072     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
5073          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5074     {
5075       continue;
5076     }
5077
5078     TCollection_AsciiString aLowerKey;
5079     aLowerKey  = "-";
5080     aLowerKey += aKey;
5081     aLowerKey.LowerCase();
5082     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
5083     std::cout << "Type help for more information.\n";
5084     return 1;
5085   }
5086
5087   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
5088   if (anAISContext.IsNull())
5089   {
5090     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
5091     return 1;
5092   }
5093
5094   Standard_Boolean toDisplay = Standard_True;
5095   Quantity_Color aColor;
5096   Graphic3d_GraduatedTrihedron aTrihedronData;
5097   // Process parameters
5098   Handle(TColStd_HSequenceOfAsciiString) aValues;
5099   if (aMapOfArgs.Find ("off", aValues))
5100   {
5101     toDisplay = Standard_False;
5102   }
5103
5104   // AXES NAMES
5105   if (aMapOfArgs.Find ("xname", aValues))
5106   {
5107     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
5108   }
5109   if (aMapOfArgs.Find ("yname", aValues))
5110   {
5111     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
5112   }
5113   if (aMapOfArgs.Find ("zname", aValues))
5114   {
5115     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
5116   }
5117   if (aMapOfArgs.Find ("xdrawname", aValues))
5118   {
5119     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5120   }
5121   if (aMapOfArgs.Find ("ydrawname", aValues))
5122   {
5123     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5124   }
5125   if (aMapOfArgs.Find ("zdrawname", aValues))
5126   {
5127     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5128   }
5129   if (aMapOfArgs.Find ("xnameoffset", aValues))
5130   {
5131     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5132   }
5133   if (aMapOfArgs.Find ("ynameoffset", aValues))
5134   {
5135     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5136   }
5137   if (aMapOfArgs.Find ("znameoffset", aValues))
5138   {
5139     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5140   }
5141
5142   // COLORS
5143   if (aMapOfArgs.Find ("xnamecolor", aValues))
5144   {
5145     if (!GetColor (aValues->Value(1), aColor))
5146     {
5147       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
5148       return 1;
5149     }
5150     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
5151   }
5152   if (aMapOfArgs.Find ("ynamecolor", aValues))
5153   {
5154     if (!GetColor (aValues->Value(1), aColor))
5155     {
5156       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
5157       return 1;
5158     }
5159     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
5160   }
5161   if (aMapOfArgs.Find ("znamecolor", aValues))
5162   {
5163     if (!GetColor (aValues->Value(1), aColor))
5164     {
5165       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
5166       return 1;
5167     }
5168     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
5169   }
5170   if (aMapOfArgs.Find ("xcolor", aValues))
5171   {
5172     if (!GetColor (aValues->Value(1), aColor))
5173     {
5174       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
5175       return 1;
5176     }
5177     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
5178   }
5179   if (aMapOfArgs.Find ("ycolor", aValues))
5180   {
5181     if (!GetColor (aValues->Value(1), aColor))
5182     {
5183       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
5184       return 1;
5185     }
5186     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
5187   }
5188   if (aMapOfArgs.Find ("zcolor", aValues))
5189   {
5190     if (!GetColor (aValues->Value(1), aColor))
5191     {
5192       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
5193       return 1;
5194     }
5195     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
5196   }
5197
5198   // TICKMARKS
5199   if (aMapOfArgs.Find ("xticks", aValues))
5200   {
5201     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5202   }
5203   if (aMapOfArgs.Find ("yticks", aValues))
5204   {
5205     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5206   }
5207   if (aMapOfArgs.Find ("zticks", aValues))
5208   {
5209     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5210   }
5211   if (aMapOfArgs.Find ("xticklength", aValues))
5212   {
5213     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5214   }
5215   if (aMapOfArgs.Find ("yticklength", aValues))
5216   {
5217     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5218   }
5219   if (aMapOfArgs.Find ("zticklength", aValues))
5220   {
5221     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5222   }
5223   if (aMapOfArgs.Find ("xdrawticks", aValues))
5224   {
5225     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5226   }
5227   if (aMapOfArgs.Find ("ydrawticks", aValues))
5228   {
5229     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5230   }
5231   if (aMapOfArgs.Find ("zdrawticks", aValues))
5232   {
5233     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5234   }
5235
5236   // VALUES
5237   if (aMapOfArgs.Find ("xdrawvalues", aValues))
5238   {
5239     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5240   }
5241   if (aMapOfArgs.Find ("ydrawvalues", aValues))
5242   {
5243     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5244   }
5245   if (aMapOfArgs.Find ("zdrawvalues", aValues))
5246   {
5247     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5248   }
5249   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
5250   {
5251     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5252   }
5253   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
5254   {
5255     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5256   }
5257   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
5258   {
5259     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5260   }
5261
5262   // ARROWS
5263   if (aMapOfArgs.Find ("arrowlength", aValues))
5264   {
5265     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
5266   }
5267
5268   // FONTS
5269   if (aMapOfArgs.Find ("namefont", aValues))
5270   {
5271     aTrihedronData.SetNamesFont (aValues->Value(1));
5272   }
5273   if (aMapOfArgs.Find ("valuesfont", aValues))
5274   {
5275     aTrihedronData.SetValuesFont (aValues->Value(1));
5276   }
5277
5278   if (aMapOfArgs.Find ("drawgrid", aValues))
5279   {
5280     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
5281   }
5282   if (aMapOfArgs.Find ("drawaxes", aValues))
5283   {
5284     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
5285   }
5286
5287   // The final step: display of erase trihedron
5288   if (toDisplay)
5289   {
5290     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
5291   }
5292   else
5293   {
5294     ViewerTest::CurrentView()->GraduatedTrihedronErase();
5295   }
5296
5297   ViewerTest::GetAISContext()->UpdateCurrentViewer();
5298   ViewerTest::CurrentView()->Redraw();
5299
5300   return 0;
5301 }
5302
5303 //==============================================================================
5304 //function : VTile
5305 //purpose  :
5306 //==============================================================================
5307 static int VTile (Draw_Interpretor& theDI,
5308                   Standard_Integer  theArgNb,
5309                   const char**      theArgVec)
5310 {
5311   Handle(V3d_View) aView = ViewerTest::CurrentView();
5312   if (aView.IsNull())
5313   {
5314     std::cerr << "Error: no active viewer.\n";
5315     return 1;
5316   }
5317
5318   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
5319   if (theArgNb < 2)
5320   {
5321     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
5322           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
5323           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
5324     return 0;
5325   }
5326
5327   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
5328   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5329   {
5330     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5331     anArg.LowerCase();
5332     if (anArg == "-lowerleft"
5333      || anArg == "-upperleft")
5334     {
5335       if (anArgIter + 3 < theArgNb)
5336       {
5337         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5338         return 1;
5339       }
5340       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
5341       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5342       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5343     }
5344     else if (anArg == "-total"
5345           || anArg == "-totalsize"
5346           || anArg == "-viewsize")
5347     {
5348       if (anArgIter + 3 < theArgNb)
5349       {
5350         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5351         return 1;
5352       }
5353       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5354       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5355       if (aTile.TotalSize.x() < 1
5356        || aTile.TotalSize.y() < 1)
5357       {
5358         std::cerr << "Error: total size is incorrect.\n";
5359         return 1;
5360       }
5361     }
5362     else if (anArg == "-tilesize")
5363     {
5364       if (anArgIter + 3 < theArgNb)
5365       {
5366         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5367         return 1;
5368       }
5369
5370       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5371       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5372       if (aTile.TileSize.x() < 1
5373        || aTile.TileSize.y() < 1)
5374       {
5375         std::cerr << "Error: tile size is incorrect.\n";
5376         return 1;
5377       }
5378     }
5379     else if (anArg == "-unset")
5380     {
5381       aView->Camera()->SetTile (Graphic3d_CameraTile());
5382       aView->Redraw();
5383       return 0;
5384     }
5385   }
5386
5387   if (aTile.TileSize.x() < 1
5388    || aTile.TileSize.y() < 1)
5389   {
5390     std::cerr << "Error: tile size is undefined.\n";
5391     return 1;
5392   }
5393   else if (aTile.TotalSize.x() < 1
5394         || aTile.TotalSize.y() < 1)
5395   {
5396     std::cerr << "Error: total size is undefined.\n";
5397     return 1;
5398   }
5399
5400   aView->Camera()->SetTile (aTile);
5401   aView->Redraw();
5402   return 0;
5403 }
5404
5405 //! Format ZLayer ID.
5406 inline const char* formZLayerId (const Standard_Integer theLayerId)
5407 {
5408   switch (theLayerId)
5409   {
5410     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
5411     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
5412     case Graphic3d_ZLayerId_Top:     return "[TOP]";
5413     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
5414     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
5415     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
5416   }
5417   return "";
5418 }
5419
5420 //! Print the ZLayer information.
5421 inline void printZLayerInfo (Draw_Interpretor& theDI,
5422                              const Graphic3d_ZLayerSettings& theLayer)
5423 {
5424   if (!theLayer.Name().IsEmpty())
5425   {
5426     theDI << "  Name: " << theLayer.Name() << "\n";
5427   }
5428   if (theLayer.IsImmediate())
5429   {
5430     theDI << "  Immediate: TRUE\n";
5431   }
5432   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
5433   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
5434   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
5435   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
5436   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
5437   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
5438   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
5439   {
5440     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
5441   }
5442 }
5443
5444 //==============================================================================
5445 //function : VZLayer
5446 //purpose  : Test z layer operations for v3d viewer
5447 //==============================================================================
5448 static int VZLayer (Draw_Interpretor& theDI,
5449                     Standard_Integer  theArgNb,
5450                     const char**      theArgVec)
5451 {
5452   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5453   if (aContextAIS.IsNull())
5454   {
5455     std::cout << "No active viewer!\n";
5456     return 1;
5457   }
5458
5459   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
5460   if (theArgNb < 2)
5461   {
5462     TColStd_SequenceOfInteger aLayers;
5463     aViewer->GetAllZLayers (aLayers);
5464     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5465     {
5466       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
5467       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
5468       printZLayerInfo (theDI, aSettings);
5469     }
5470     return 1;
5471   }
5472
5473   Standard_Integer anArgIter = 1;
5474   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5475   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
5476   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5477   {
5478     ++anArgIter;
5479   }
5480
5481   {
5482     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
5483     if (aFirstArg.IsIntegerValue())
5484     {
5485       ++anArgIter;
5486       aLayerId = aFirstArg.IntegerValue();
5487     }
5488     else
5489     {
5490       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
5491       {
5492         ++anArgIter;
5493       }
5494     }
5495   }
5496
5497   Graphic3d_ZLayerId anOtherLayerId = Graphic3d_ZLayerId_UNKNOWN;
5498   for (; anArgIter < theArgNb; ++anArgIter)
5499   {
5500     // perform operation
5501     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5502     anArg.LowerCase();
5503     if (anUpdateTool.parseRedrawMode (anArg))
5504     {
5505       //
5506     }
5507     else if (anArg == "-add"
5508           || anArg == "add")
5509     {
5510       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5511       if (!aViewer->AddZLayer (aLayerId))
5512       {
5513         std::cout << "Error: can not add a new z layer!\n";
5514         return 0;
5515       }
5516
5517       theDI << aLayerId;
5518     }
5519     else if (anArg == "-insertbefore"
5520           && anArgIter + 1 < theArgNb
5521           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5522     {
5523       ++anArgIter;
5524       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5525       if (!aViewer->InsertLayerBefore (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5526       {
5527         std::cout << "Error: can not add a new z layer!\n";
5528         return 0;
5529       }
5530
5531       theDI << aLayerId;
5532     }
5533     else if (anArg == "-insertafter"
5534           && anArgIter + 1 < theArgNb
5535           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5536     {
5537       ++anArgIter;
5538       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5539       if (!aViewer->InsertLayerAfter (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5540       {
5541         std::cout << "Error: can not add a new z layer!\n";
5542         return 0;
5543       }
5544
5545       theDI << aLayerId;
5546     }
5547     else if (anArg == "-del"
5548           || anArg == "-delete"
5549           || anArg == "del")
5550     {
5551       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5552       {
5553         if (++anArgIter >= theArgNb)
5554         {
5555           std::cout << "Syntax error: id of z layer to remove is missing\n";
5556           return 1;
5557         }
5558
5559         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5560       }
5561
5562       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
5563        || aLayerId == Graphic3d_ZLayerId_Default
5564        || aLayerId == Graphic3d_ZLayerId_Top
5565        || aLayerId == Graphic3d_ZLayerId_Topmost
5566        || aLayerId == Graphic3d_ZLayerId_TopOSD
5567        || aLayerId == Graphic3d_ZLayerId_BotOSD)
5568       {
5569         std::cout << "Syntax error: standard Z layer can not be removed\n";
5570         return 1;
5571       }
5572
5573       // move all object displayed in removing layer to default layer
5574       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5575            anObjIter.More(); anObjIter.Next())
5576       {
5577         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
5578         if (aPrs.IsNull()
5579          || aPrs->ZLayer() != aLayerId)
5580         {
5581           continue;
5582         }
5583         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
5584       }
5585
5586       if (!aViewer->RemoveZLayer (aLayerId))
5587       {
5588         std::cout << "Z layer can not be removed!\n";
5589       }
5590       else
5591       {
5592         theDI << aLayerId << " ";
5593       }
5594     }
5595     else if (anArg == "-get"
5596           || anArg == "get")
5597     {
5598       TColStd_SequenceOfInteger aLayers;
5599       aViewer->GetAllZLayers (aLayers);
5600       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5601       {
5602         theDI << aLayeriter.Value() << " ";
5603       }
5604
5605       theDI << "\n";
5606     }
5607     else if (anArg == "-name")
5608     {
5609       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5610       {
5611         std::cout << "Syntax error: id of Z layer is missing\n";
5612         return 1;
5613       }
5614
5615       if (++anArgIter >= theArgNb)
5616       {
5617         std::cout << "Syntax error: name is missing\n";
5618         return 1;
5619       }
5620
5621       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5622       aSettings.SetName (theArgVec[anArgIter]);
5623       aViewer->SetZLayerSettings (aLayerId, aSettings);
5624     }
5625     else if (anArg == "-origin")
5626     {
5627       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5628       {
5629         std::cout << "Syntax error: id of Z layer is missing\n";
5630         return 1;
5631       }
5632
5633       if (anArgIter + 2 >= theArgNb)
5634       {
5635         std::cout << "Syntax error: origin coordinates are missing\n";
5636         return 1;
5637       }
5638
5639       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5640       gp_XYZ anOrigin;
5641       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5642       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5643       anOrigin.SetZ (0.0);
5644       if (anArgIter + 3 < theArgNb)
5645       {
5646         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5647         anArgIter += 3;
5648       }
5649       else
5650       {
5651         anArgIter += 2;
5652       }
5653       aSettings.SetOrigin (anOrigin);
5654       aViewer->SetZLayerSettings (aLayerId, aSettings);
5655     }
5656     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5657           && anArgIter + 1 < theArgNb
5658           && (anArg == "-cullingdistance"
5659            || anArg == "-cullingdist"
5660            || anArg == "-culldistance"
5661            || anArg == "-culldist"
5662            || anArg == "-distcull"
5663            || anArg == "-distculling"
5664            || anArg == "-distanceculling"))
5665     {
5666       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5667       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5668       aSettings.SetCullingDistance (aDist);
5669       aViewer->SetZLayerSettings (aLayerId, aSettings);
5670     }
5671     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5672           && anArgIter + 1 < theArgNb
5673           && (anArg == "-cullingsize"
5674            || anArg == "-cullsize"
5675            || anArg == "-sizecull"
5676            || anArg == "-sizeculling"))
5677     {
5678       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5679       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5680       aSettings.SetCullingSize (aSize);
5681       aViewer->SetZLayerSettings (aLayerId, aSettings);
5682     }
5683     else if (anArg == "-settings"
5684           || anArg == "settings")
5685     {
5686       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5687       {
5688         if (++anArgIter >= theArgNb)
5689         {
5690           std::cout << "Syntax error: id of Z layer is missing\n";
5691           return 1;
5692         }
5693
5694         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5695       }
5696
5697       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5698       printZLayerInfo (theDI, aSettings);
5699     }
5700     else if (anArg == "-enable"
5701           || anArg == "enable"
5702           || anArg == "-disable"
5703           || anArg == "disable")
5704     {
5705       const Standard_Boolean toEnable = anArg == "-enable"
5706                                      || anArg == "enable";
5707       if (++anArgIter >= theArgNb)
5708       {
5709         std::cout << "Syntax error: option name is missing\n";
5710         return 1;
5711       }
5712
5713       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5714       aSubOp.LowerCase();
5715       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5716       {
5717         if (++anArgIter >= theArgNb)
5718         {
5719           std::cout << "Syntax error: id of Z layer is missing\n";
5720           return 1;
5721         }
5722
5723         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5724       }
5725
5726       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5727       if (aSubOp == "depthtest"
5728        || aSubOp == "test")
5729       {
5730         aSettings.SetEnableDepthTest (toEnable);
5731       }
5732       else if (aSubOp == "depthwrite"
5733             || aSubOp == "write")
5734       {
5735         aSettings.SetEnableDepthWrite (toEnable);
5736       }
5737       else if (aSubOp == "depthclear"
5738             || aSubOp == "clear")
5739       {
5740         aSettings.SetClearDepth (toEnable);
5741       }
5742       else if (aSubOp == "depthoffset"
5743             || aSubOp == "offset")
5744       {
5745         Graphic3d_PolygonOffset aParams;
5746         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5747         if (toEnable)
5748         {
5749           if (anArgIter + 2 >= theArgNb)
5750           {
5751             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5752             return 1;
5753           }
5754
5755           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5756           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5757         }
5758         aSettings.SetPolygonOffset (aParams);
5759       }
5760       else if (aSubOp == "positiveoffset"
5761             || aSubOp == "poffset")
5762       {
5763         if (toEnable)
5764         {
5765           aSettings.SetDepthOffsetPositive();
5766         }
5767         else
5768         {
5769           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5770         }
5771       }
5772       else if (aSubOp == "negativeoffset"
5773             || aSubOp == "noffset")
5774       {
5775         if (toEnable)
5776         {
5777           aSettings.SetDepthOffsetNegative();
5778         }
5779         else
5780         {
5781           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5782         }
5783       }
5784       else if (aSubOp == "textureenv")
5785       {
5786         aSettings.SetEnvironmentTexture (toEnable);
5787       }
5788       else if (aSubOp == "raytracing")
5789       {
5790         aSettings.SetRaytracable (toEnable);
5791       }
5792
5793       aViewer->SetZLayerSettings (aLayerId, aSettings);
5794     }
5795     else
5796     {
5797       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5798       return 1;
5799     }
5800   }
5801
5802   return 0;
5803 }
5804
5805 // The interactive presentation of 2d layer item
5806 // for "vlayerline" command it provides a presentation of
5807 // line with user-defined linewidth, linetype and transparency.
5808 class V3d_LineItem : public AIS_InteractiveObject
5809 {
5810 public:
5811   // CASCADE RTTI
5812   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5813
5814   // constructor
5815   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5816                                Standard_Real X2, Standard_Real Y2,
5817                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5818                                Standard_Real theWidth    = 0.5,
5819                                Standard_Real theTransp   = 1.0);
5820
5821   private:
5822
5823   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5824                 const Handle(Prs3d_Presentation)& thePresentation,
5825                 const Standard_Integer theMode) Standard_OVERRIDE;
5826
5827   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5828                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5829   {}
5830
5831 private:
5832
5833   Standard_Real       myX1, myY1, myX2, myY2;
5834   Aspect_TypeOfLine   myType;
5835   Standard_Real       myWidth;
5836 };
5837
5838 // default constructor for line item
5839 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5840                            Standard_Real X2, Standard_Real Y2,
5841                            Aspect_TypeOfLine theType,
5842                            Standard_Real theWidth,
5843                            Standard_Real theTransp) :
5844   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5845   myType(theType), myWidth(theWidth)
5846 {
5847   SetTransparency (1-theTransp);
5848 }
5849
5850 // render line
5851 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5852                             const Handle(Prs3d_Presentation)& thePresentation,
5853                             const Standard_Integer /*theMode*/)
5854 {
5855   thePresentation->Clear();
5856   Quantity_Color aColor (Quantity_NOC_RED);
5857   Standard_Integer aWidth, aHeight;
5858   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5859   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5860   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5861   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5862   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5863   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5864   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5865   aGroup->AddPrimitiveArray (aPrim);
5866 }
5867
5868 //=============================================================================
5869 //function : VLayerLine
5870 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5871 //         : linewidth, transparency coefficient
5872 //============================================================================
5873 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5874 {
5875   // get the active view
5876   Handle(V3d_View) aView = ViewerTest::CurrentView();
5877   if (aView.IsNull())
5878   {
5879     di << "Call vinit before!\n";
5880     return 1;
5881   }
5882   else if (argc < 5)
5883   {
5884     di << "Use: " << argv[0];
5885     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5886     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5887     di << "              0 - solid  \n";
5888     di << "              1 - dashed \n";
5889     di << "              2 - dot    \n";
5890     di << "              3 - dashdot\n";
5891     di << " transparency : { 0.0 - 1.0 } \n";
5892     di << "                  0.0 - transparent\n";
5893     di << "                  1.0 - visible    \n";
5894     return 1;
5895   }
5896
5897   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5898   // get the input params
5899   Standard_Real X1 = Draw::Atof(argv[1]);
5900   Standard_Real Y1 = Draw::Atof(argv[2]);
5901   Standard_Real X2 = Draw::Atof(argv[3]);
5902   Standard_Real Y2 = Draw::Atof(argv[4]);
5903
5904   Standard_Real aWidth = 0.5;
5905   Standard_Real aTransparency = 1.0;
5906
5907   // has width
5908   if (argc > 5)
5909     aWidth = Draw::Atof(argv[5]);
5910
5911   // select appropriate line type
5912   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5913   if (argc > 6
5914   && !ViewerTest::ParseLineType (argv[6], aLineType))
5915   {
5916     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5917     return 1;
5918   }
5919
5920   // has transparency
5921   if (argc > 7)
5922   {
5923     aTransparency = Draw::Atof(argv[7]);
5924     if (aTransparency < 0 || aTransparency > 1.0)
5925       aTransparency = 1.0;
5926   }
5927
5928   static Handle (V3d_LineItem) aLine;
5929   if (!aLine.IsNull())
5930   {
5931     aContext->Erase (aLine, Standard_False);
5932   }
5933   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5934                             aLineType, aWidth,
5935                             aTransparency);
5936
5937   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5938   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5939   aLine->SetToUpdate();
5940   aContext->Display (aLine, Standard_True);
5941
5942   return 0;
5943 }
5944
5945
5946 //==============================================================================
5947 //function : VGrid
5948 //purpose  :
5949 //==============================================================================
5950
5951 static int VGrid (Draw_Interpretor& /*theDI*/,
5952                   Standard_Integer  theArgNb,
5953                   const char**      theArgVec)
5954 {
5955   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5956   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5957   if (aView.IsNull() || aViewer.IsNull())
5958   {
5959     std::cerr << "Error: no active view\n";
5960     return 1;
5961   }
5962
5963   Aspect_GridType     aType = aViewer->GridType();
5964   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5965   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5966   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5967   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
5968   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5969   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5970   {
5971     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5972     anArg.LowerCase();
5973     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5974     {
5975       continue;
5976     }
5977     else if (anArgIter + 1 < theArgNb
5978           && anArg == "-type")
5979     {
5980       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5981       anArgNext.LowerCase();
5982       if (anArgNext == "r"
5983        || anArgNext == "rect"
5984        || anArgNext == "rectangular")
5985       {
5986         aType = Aspect_GT_Rectangular;
5987       }
5988       else if (anArgNext == "c"
5989             || anArgNext == "circ"
5990             || anArgNext == "circular")
5991       {
5992         aType = Aspect_GT_Circular;
5993       }
5994       else
5995       {
5996         std::cout << "Syntax error at '" << anArgNext << "'\n";
5997         return 1;
5998       }
5999     }
6000     else if (anArgIter + 1 < theArgNb
6001           && anArg == "-mode")
6002     {
6003       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
6004       anArgNext.LowerCase();
6005       if (anArgNext == "l"
6006        || anArgNext == "line"
6007        || anArgNext == "lines")
6008       {
6009         aMode = Aspect_GDM_Lines;
6010       }
6011       else if (anArgNext == "p"
6012             || anArgNext == "point"
6013             || anArgNext == "points")
6014       {
6015         aMode = Aspect_GDM_Points;
6016       }
6017       else
6018       {
6019         std::cout << "Syntax error at '" << anArgNext << "'\n";
6020         return 1;
6021       }
6022     }
6023     else if (anArgIter + 2 < theArgNb
6024           && (anArg == "-origin"
6025            || anArg == "-orig"))
6026     {
6027       hasOrigin = true;
6028       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6029                               Draw::Atof (theArgVec[anArgIter + 2]));
6030       anArgIter += 2;
6031     }
6032     else if (anArgIter + 2 < theArgNb
6033           && anArg == "-step")
6034     {
6035       hasStep = true;
6036       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6037                             Draw::Atof (theArgVec[anArgIter + 2]));
6038       if (aNewStepXY.x() <= 0.0
6039        || aNewStepXY.y() <= 0.0)
6040       {
6041         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6042         return 1;
6043       }
6044       anArgIter += 2;
6045     }
6046     else if (anArgIter + 1 < theArgNb
6047           && (anArg == "-angle"
6048            || anArg == "-rotangle"
6049            || anArg == "-rotationangle"))
6050     {
6051       hasRotAngle = true;
6052       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
6053     }
6054     else if (anArgIter + 1 < theArgNb
6055           && (anArg == "-zoffset"
6056            || anArg == "-dz"))
6057     {
6058       hasZOffset = true;
6059       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
6060     }
6061     else if (anArgIter + 1 < theArgNb
6062           && anArg == "-radius")
6063     {
6064       hasSize = true;
6065       ++anArgIter;
6066       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
6067       if (aNewStepXY.x() <= 0.0)
6068       {
6069         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
6070         return 1;
6071       }
6072     }
6073     else if (anArgIter + 2 < theArgNb
6074           && anArg == "-size")
6075     {
6076       hasSize = true;
6077       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6078                             Draw::Atof (theArgVec[anArgIter + 2]));
6079       if (aNewStepXY.x() <= 0.0
6080        || aNewStepXY.y() <= 0.0)
6081       {
6082         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6083         return 1;
6084       }
6085       anArgIter += 2;
6086     }
6087     else if (anArg == "r"
6088           || anArg == "rect"
6089           || anArg == "rectangular")
6090     {
6091       aType = Aspect_GT_Rectangular;
6092     }
6093     else if (anArg == "c"
6094           || anArg == "circ"
6095           || anArg == "circular")
6096     {
6097       aType = Aspect_GT_Circular;
6098     }
6099     else if (anArg == "l"
6100           || anArg == "line"
6101           || anArg == "lines")
6102     {
6103       aMode = Aspect_GDM_Lines;
6104     }
6105     else if (anArg == "p"
6106           || anArg == "point"
6107           || anArg == "points")
6108     {
6109       aMode = Aspect_GDM_Points;
6110     }
6111     else if (anArgIter + 1 >= theArgNb
6112           && anArg == "off")
6113     {
6114       aViewer->DeactivateGrid();
6115       return 0;
6116     }
6117     else
6118     {
6119       std::cout << "Syntax error at '" << anArg << "'\n";
6120       return 1;
6121     }
6122   }
6123
6124   if (aType == Aspect_GT_Rectangular)
6125   {
6126     Graphic3d_Vec2d anOrigXY, aStepXY;
6127     Standard_Real aRotAngle = 0.0;
6128     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6129     if (hasOrigin)
6130     {
6131       anOrigXY = aNewOriginXY;
6132     }
6133     if (hasStep)
6134     {
6135       aStepXY = aNewStepXY;
6136     }
6137     if (hasRotAngle)
6138     {
6139       aRotAngle = aNewRotAngle;
6140     }
6141     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6142     if (hasSize || hasZOffset)
6143     {
6144       Graphic3d_Vec3d aSize;
6145       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6146       if (hasSize)
6147       {
6148         aSize.x() = aNewSizeXY.x();
6149         aSize.y() = aNewSizeXY.y();
6150       }
6151       if (hasZOffset)
6152       {
6153         aSize.z() = aNewZOffset;
6154       }
6155       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6156     }
6157   }
6158   else if (aType == Aspect_GT_Circular)
6159   {
6160     Graphic3d_Vec2d anOrigXY;
6161     Standard_Real aRadiusStep;
6162     Standard_Integer aDivisionNumber;
6163     Standard_Real aRotAngle = 0.0;
6164     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6165     if (hasOrigin)
6166     {
6167       anOrigXY = aNewOriginXY;
6168     }
6169     if (hasStep)
6170     {
6171       aRadiusStep     = aNewStepXY[0];
6172       aDivisionNumber = (int )aNewStepXY[1];
6173       if (aDivisionNumber < 1)
6174       {
6175         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
6176         return 1;
6177       }
6178     }
6179     if (hasRotAngle)
6180     {
6181       aRotAngle = aNewRotAngle;
6182     }
6183
6184     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6185     if (hasSize || hasZOffset)
6186     {
6187       Standard_Real aRadius = 0.0, aZOffset = 0.0;
6188       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
6189       if (hasSize)
6190       {
6191         aRadius = aNewSizeXY.x();
6192         if (aNewSizeXY.y() != 0.0)
6193         {
6194           std::cout << "Syntax error: circular size should be specified as radius\n";
6195           return 1;
6196         }
6197       }
6198       if (hasZOffset)
6199       {
6200         aZOffset = aNewZOffset;
6201       }
6202       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
6203     }
6204   }
6205   aViewer->ActivateGrid (aType, aMode);
6206   return 0;
6207 }
6208
6209 //==============================================================================
6210 //function : VPriviledgedPlane
6211 //purpose  :
6212 //==============================================================================
6213
6214 static int VPriviledgedPlane (Draw_Interpretor& theDI,
6215                               Standard_Integer  theArgNb,
6216                               const char**      theArgVec)
6217 {
6218   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
6219   {
6220     std::cerr << "Error: wrong number of arguments! See usage:\n";
6221     theDI.PrintHelp (theArgVec[0]);
6222     return 1;
6223   }
6224
6225   // get the active viewer
6226   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6227   if (aViewer.IsNull())
6228   {
6229     std::cerr << "Error: no active viewer. Please call vinit.\n";
6230     return 1;
6231   }
6232
6233   if (theArgNb == 1)
6234   {
6235     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
6236     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
6237     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
6238     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
6239     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
6240           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
6241           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
6242     return 0;
6243   }
6244
6245   Standard_Integer anArgIdx = 1;
6246   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
6247   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
6248   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
6249   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
6250   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
6251   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
6252
6253   gp_Ax3 aPriviledgedPlane;
6254   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
6255   gp_Dir aNorm (aNormX, aNormY, aNormZ);
6256   if (theArgNb > 7)
6257   {
6258     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
6259     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
6260     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
6261     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
6262     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
6263   }
6264   else
6265   {
6266     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
6267   }
6268
6269   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
6270
6271   return 0;
6272 }
6273
6274 //==============================================================================
6275 //function : VConvert
6276 //purpose  :
6277 //==============================================================================
6278
6279 static int VConvert (Draw_Interpretor& theDI,
6280                      Standard_Integer  theArgNb,
6281                      const char**      theArgVec)
6282 {
6283   // get the active view
6284   Handle(V3d_View) aView = ViewerTest::CurrentView();
6285   if (aView.IsNull())
6286   {
6287     std::cerr << "Error: no active view. Please call vinit.\n";
6288     return 1;
6289   }
6290
6291   enum { Model, Ray, View, Window, Grid } aMode = Model;
6292
6293   // access coordinate arguments
6294   TColStd_SequenceOfReal aCoord;
6295   Standard_Integer anArgIdx = 1;
6296   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
6297   {
6298     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6299     if (!anArg.IsRealValue())
6300     {
6301       break;
6302     }
6303     aCoord.Append (anArg.RealValue());
6304   }
6305
6306   // non-numeric argument too early
6307   if (aCoord.IsEmpty())
6308   {
6309     std::cerr << "Error: wrong number of arguments! See usage:\n";
6310     theDI.PrintHelp (theArgVec[0]);
6311     return 1;
6312   }
6313
6314   // collect all other arguments and options
6315   for (; anArgIdx < theArgNb; ++anArgIdx)
6316   {
6317     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6318     anArg.LowerCase();
6319     if      (anArg == "window") aMode = Window;
6320     else if (anArg == "view")   aMode = View;
6321     else if (anArg == "grid")   aMode = Grid;
6322     else if (anArg == "ray")    aMode = Ray;
6323     else
6324     {
6325       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
6326       theDI.PrintHelp (theArgVec[0]);
6327       return 1;
6328     }
6329   }
6330
6331   // complete input checks
6332   if ((aCoord.Length() == 1 && theArgNb > 3) ||
6333       (aCoord.Length() == 2 && theArgNb > 4) ||
6334       (aCoord.Length() == 3 && theArgNb > 5))
6335   {
6336     std::cerr << "Error: wrong number of arguments! See usage:\n";
6337     theDI.PrintHelp (theArgVec[0]);
6338     return 1;
6339   }
6340
6341   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6342   Standard_Integer aXYp[2] = {0, 0};
6343
6344   // convert one-dimensional coordinate
6345   if (aCoord.Length() == 1)
6346   {
6347     switch (aMode)
6348     {
6349       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
6350       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
6351       default:
6352         std::cerr << "Error: wrong arguments! See usage:\n";
6353         theDI.PrintHelp (theArgVec[0]);
6354         return 1;
6355     }
6356   }
6357
6358   // convert 2D coordinates from projection or view reference space
6359   if (aCoord.Length() == 2)
6360   {
6361     switch (aMode)
6362     {
6363       case Model :
6364         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6365         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6366         return 0;
6367
6368       case View :
6369         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
6370         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
6371         return 0;
6372
6373       case Window :
6374         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
6375         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6376         return 0;
6377
6378       case Grid :
6379         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6380         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
6381         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6382         return 0;
6383
6384       case Ray :
6385         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
6386                                 (Standard_Integer) aCoord (2),
6387                                 aXYZ[0], aXYZ[1], aXYZ[2],
6388                                 aXYZ[3], aXYZ[4], aXYZ[5]);
6389         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6390         return 0;
6391
6392       default:
6393         std::cerr << "Error: wrong arguments! See usage:\n";
6394         theDI.PrintHelp (theArgVec[0]);
6395         return 1;
6396     }
6397   }
6398
6399   // convert 3D coordinates from view reference space
6400   else if (aCoord.Length() == 3)
6401   {
6402     switch (aMode)
6403     {
6404       case Window :
6405         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
6406         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6407         return 0;
6408
6409       case Grid :
6410         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
6411         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6412         return 0;
6413
6414       default:
6415         std::cerr << "Error: wrong arguments! See usage:\n";
6416         theDI.PrintHelp (theArgVec[0]);
6417         return 1;
6418     }
6419   }
6420
6421   return 0;
6422 }
6423
6424 //==============================================================================
6425 //function : VFps
6426 //purpose  :
6427 //==============================================================================
6428
6429 static int VFps (Draw_Interpretor& theDI,
6430                  Standard_Integer  theArgNb,
6431                  const char**      theArgVec)
6432 {
6433   // get the active view
6434   Handle(V3d_View) aView = ViewerTest::CurrentView();
6435   if (aView.IsNull())
6436   {
6437     std::cerr << "No active view. Please call vinit.\n";
6438     return 1;
6439   }
6440
6441   Standard_Integer aFramesNb = -1;
6442   Standard_Real aDuration = -1.0;
6443   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6444   {
6445     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6446     anArg.LowerCase();
6447     if (aDuration < 0.0
6448      && anArgIter + 1 < theArgNb
6449      && (anArg == "-duration"
6450       || anArg == "-dur"
6451       || anArg == "-time"))
6452     {
6453       aDuration = Draw::Atof (theArgVec[++anArgIter]);
6454     }
6455     else if (aFramesNb < 0
6456           && anArg.IsIntegerValue())
6457     {
6458       aFramesNb = anArg.IntegerValue();
6459       if (aFramesNb <= 0)
6460       {
6461         std::cerr << "Syntax error at '" << anArg << "'\n";
6462         return 1;
6463       }
6464     }
6465     else
6466     {
6467       std::cerr << "Syntax error at '" << anArg << "'\n";
6468       return 1;
6469     }
6470   }
6471   if (aFramesNb < 0 && aDuration < 0.0)
6472   {
6473     aFramesNb = 100;
6474   }
6475
6476   // the time is meaningless for first call
6477   // due to async OpenGl rendering
6478   aView->Redraw();
6479
6480   // redraw view in loop to estimate average values
6481   OSD_Timer aTimer;
6482   aTimer.Start();
6483   Standard_Integer aFrameIter = 1;
6484   for (;; ++aFrameIter)
6485   {
6486     aView->Redraw();
6487     if ((aFramesNb > 0
6488       && aFrameIter >= aFramesNb)
6489      || (aDuration > 0.0
6490       && aTimer.ElapsedTime() >= aDuration))
6491     {
6492       break;
6493     }
6494   }
6495   aTimer.Stop();
6496   Standard_Real aCpu;
6497   const Standard_Real aTime = aTimer.ElapsedTime();
6498   aTimer.OSD_Chronometer::Show (aCpu);
6499
6500   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
6501   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
6502
6503   // return statistics
6504   theDI << "FPS: " << aFpsAver << "\n"
6505         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
6506
6507   // compute additional statistics in ray-tracing mode
6508   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
6509   if (aParams.Method == Graphic3d_RM_RAYTRACING)
6510   {
6511     Graphic3d_Vec2i aWinSize (0, 0);
6512     aView->Window()->Size (aWinSize.x(), aWinSize.y());
6513
6514     // 1 shadow ray and 1 secondary ray pew each bounce
6515     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
6516     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
6517   }
6518
6519   return 0;
6520 }
6521
6522 //! Auxiliary function for parsing glsl dump level argument.
6523 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
6524                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
6525 {
6526   TCollection_AsciiString aTypeStr (theArg);
6527   aTypeStr.LowerCase();
6528   if (aTypeStr == "off"
6529    || aTypeStr == "0")
6530   {
6531     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6532   }
6533   else if (aTypeStr == "short")
6534   {
6535     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
6536   }
6537   else if (aTypeStr == "full"
6538         || aTypeStr == "1")
6539   {
6540     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6541   }
6542   else
6543   {
6544     return Standard_False;
6545   }
6546   return Standard_True;
6547 }
6548
6549 //==============================================================================
6550 //function : VGlDebug
6551 //purpose  :
6552 //==============================================================================
6553
6554 static int VGlDebug (Draw_Interpretor& theDI,
6555                      Standard_Integer  theArgNb,
6556                      const char**      theArgVec)
6557 {
6558   Handle(OpenGl_GraphicDriver) aDriver;
6559   Handle(V3d_View) aView = ViewerTest::CurrentView();
6560   if (!aView.IsNull())
6561   {
6562     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
6563   }
6564   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
6565   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
6566
6567   if (theArgNb < 2)
6568   {
6569     TCollection_AsciiString aDebActive, aSyncActive;
6570     if (aCaps == NULL)
6571     {
6572       aCaps = aDefCaps;
6573     }
6574     else
6575     {
6576       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
6577                                                                   "GL_ARB_debug_output");
6578       aDebActive = isActive ? " (active)" : " (inactive)";
6579       if (isActive)
6580       {
6581         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
6582         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
6583       }
6584     }
6585
6586     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
6587       + "glslSourceCode: "
6588       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
6589          ? "Off"
6590          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
6591           ? "Short"
6592           : "Full")
6593       + "\n";
6594     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
6595           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
6596           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
6597           << aGlslCodeDebugStatus
6598           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
6599     return 0;
6600   }
6601
6602   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6603   {
6604     Standard_CString        anArg     = theArgVec[anArgIter];
6605     TCollection_AsciiString anArgCase (anArg);
6606     anArgCase.LowerCase();
6607     Standard_Boolean toEnableDebug = Standard_True;
6608     if (anArgCase == "-glsl"
6609      || anArgCase == "-glslwarn"
6610      || anArgCase == "-glslwarns"
6611      || anArgCase == "-glslwarnings")
6612     {
6613       Standard_Boolean toShowWarns = Standard_True;
6614       if (++anArgIter < theArgNb
6615       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
6616       {
6617         --anArgIter;
6618       }
6619       aDefCaps->glslWarnings = toShowWarns;
6620       if (aCaps != NULL)
6621       {
6622         aCaps->glslWarnings = toShowWarns;
6623       }
6624     }
6625     else if (anArgCase == "-extra"
6626           || anArgCase == "-extramsg"
6627           || anArgCase == "-extramessages")
6628     {
6629       Standard_Boolean toShow = Standard_True;
6630       if (++anArgIter < theArgNb
6631       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
6632       {
6633         --anArgIter;
6634       }
6635       aDefCaps->suppressExtraMsg = !toShow;
6636       if (aCaps != NULL)
6637       {
6638         aCaps->suppressExtraMsg = !toShow;
6639       }
6640     }
6641     else if (anArgCase == "-noextra"
6642           || anArgCase == "-noextramsg"
6643           || anArgCase == "-noextramessages")
6644     {
6645       Standard_Boolean toSuppress = Standard_True;
6646       if (++anArgIter < theArgNb
6647       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
6648       {
6649         --anArgIter;
6650       }
6651       aDefCaps->suppressExtraMsg = toSuppress;
6652       if (aCaps != NULL)
6653       {
6654         aCaps->suppressExtraMsg = toSuppress;
6655       }
6656     }
6657     else if (anArgCase == "-sync")
6658     {
6659       Standard_Boolean toSync = Standard_True;
6660       if (++anArgIter < theArgNb
6661       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
6662       {
6663         --anArgIter;
6664       }
6665       aDefCaps->contextSyncDebug = toSync;
6666       if (toSync)
6667       {
6668         aDefCaps->contextDebug = Standard_True;
6669       }
6670     }
6671     else if (anArgCase == "-glslsourcecode"
6672           || anArgCase == "-glslcode")
6673     {
6674       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6675       if (++anArgIter < theArgNb
6676       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
6677       {
6678         --anArgIter;
6679       }
6680       aDefCaps->glslDumpLevel = aGslsDumpLevel;
6681       if (aCaps != NULL)
6682       {
6683         aCaps->glslDumpLevel = aGslsDumpLevel;
6684       }
6685     }
6686     else if (anArgCase == "-debug")
6687     {
6688       if (++anArgIter < theArgNb
6689       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
6690       {
6691         --anArgIter;
6692       }
6693       aDefCaps->contextDebug = toEnableDebug;
6694     }
6695     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
6696           && (anArgIter + 1 == theArgNb))
6697     {
6698       // simple alias to turn on almost everything
6699       aDefCaps->contextDebug     = toEnableDebug;
6700       aDefCaps->contextSyncDebug = toEnableDebug;
6701       aDefCaps->glslWarnings     = toEnableDebug;
6702       if (!toEnableDebug)
6703       {
6704         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6705       }
6706       aDefCaps->suppressExtraMsg = !toEnableDebug;
6707       if (aCaps != NULL)
6708       {
6709         aCaps->contextDebug     = toEnableDebug;
6710         aCaps->contextSyncDebug = toEnableDebug;
6711         aCaps->glslWarnings     = toEnableDebug;
6712         if (!toEnableDebug)
6713         {
6714           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6715         }
6716         aCaps->suppressExtraMsg = !toEnableDebug;
6717       }
6718     }
6719     else
6720     {
6721       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
6722       return 1;
6723     }
6724   }
6725
6726   return 0;
6727 }
6728
6729 //==============================================================================
6730 //function : VVbo
6731 //purpose  :
6732 //==============================================================================
6733
6734 static int VVbo (Draw_Interpretor& theDI,
6735                  Standard_Integer  theArgNb,
6736                  const char**      theArgVec)
6737 {
6738   const Standard_Boolean toSet    = (theArgNb > 1);
6739   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
6740   if (toSet)
6741   {
6742     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
6743   }
6744
6745   // get the context
6746   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6747   if (aContextAIS.IsNull())
6748   {
6749     if (!toSet)
6750     {
6751       std::cerr << "No active view!\n";
6752     }
6753     return 1;
6754   }
6755   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
6756   if (!aDriver.IsNull())
6757   {
6758     if (!toSet)
6759     {
6760       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
6761     }
6762     else
6763     {
6764       aDriver->ChangeOptions().vboDisable = toUseVbo;
6765     }
6766   }
6767
6768   return 0;
6769 }
6770
6771 //==============================================================================
6772 //function : VCaps
6773 //purpose  :
6774 //==============================================================================
6775
6776 static int VCaps (Draw_Interpretor& theDI,
6777                   Standard_Integer  theArgNb,
6778                   const char**      theArgVec)
6779 {
6780   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
6781   Handle(OpenGl_GraphicDriver)   aDriver;
6782   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6783   if (!aContext.IsNull())
6784   {
6785     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
6786     aCaps   = &aDriver->ChangeOptions();
6787   }
6788
6789   if (theArgNb < 2)
6790   {
6791     theDI << "sRGB:    " << (aCaps->sRGBDisable       ? "0" : "1") << "\n";
6792     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
6793     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
6794     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
6795     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
6796     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
6797     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
6798     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
6799     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
6800     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
6801     theDI << "NoExt:"    << (aCaps->contextNoExtensions ? "1" : "0") << "\n";
6802     theDI << "MaxVersion:" << aCaps->contextMajorVersionUpper << "." << aCaps->contextMinorVersionUpper << "\n";
6803     return 0;
6804   }
6805
6806   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6807   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6808   {
6809     Standard_CString        anArg     = theArgVec[anArgIter];
6810     TCollection_AsciiString anArgCase (anArg);
6811     anArgCase.LowerCase();
6812     if (anUpdateTool.parseRedrawMode (anArg))
6813     {
6814       continue;
6815     }
6816     else if (anArgCase == "-vsync"
6817           || anArgCase == "-swapinterval")
6818     {
6819       Standard_Boolean toEnable = Standard_True;
6820       if (++anArgIter < theArgNb
6821       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6822       {
6823         --anArgIter;
6824       }
6825       aCaps->swapInterval = toEnable;
6826     }
6827     else if (anArgCase == "-ffp")
6828     {
6829       Standard_Boolean toEnable = Standard_True;
6830       if (++anArgIter < theArgNb
6831       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6832       {
6833         --anArgIter;
6834       }
6835       aCaps->ffpEnable = toEnable;
6836     }
6837     else if (anArgCase == "-polygonmode")
6838     {
6839       Standard_Boolean toEnable = Standard_True;
6840       if (++anArgIter < theArgNb
6841       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6842       {
6843         --anArgIter;
6844       }
6845       aCaps->usePolygonMode = toEnable;
6846     }
6847     else if (anArgCase == "-srgb")
6848     {
6849       Standard_Boolean toEnable = Standard_True;
6850       if (++anArgIter < theArgNb
6851       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6852       {
6853         --anArgIter;
6854       }
6855       aCaps->sRGBDisable = !toEnable;
6856     }
6857     else if (anArgCase == "-vbo")
6858     {
6859       Standard_Boolean toEnable = Standard_True;
6860       if (++anArgIter < theArgNb
6861       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6862       {
6863         --anArgIter;
6864       }
6865       aCaps->vboDisable = !toEnable;
6866     }
6867     else if (anArgCase == "-sprite"
6868           || anArgCase == "-sprites")
6869     {
6870       Standard_Boolean toEnable = Standard_True;
6871       if (++anArgIter < theArgNb
6872       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6873       {
6874         --anArgIter;
6875       }
6876       aCaps->pntSpritesDisable = !toEnable;
6877     }
6878     else if (anArgCase == "-softmode")
6879     {
6880       Standard_Boolean toEnable = Standard_True;
6881       if (++anArgIter < theArgNb
6882       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6883       {
6884         --anArgIter;
6885       }
6886       aCaps->contextNoAccel = toEnable;
6887     }
6888     else if (anArgCase == "-winbuffer"
6889           || anArgCase == "-windowbuffer"
6890           || anArgCase == "-usewinbuffer"
6891           || anArgCase == "-usewindowbuffer"
6892           || anArgCase == "-usesystembuffer")
6893     {
6894       Standard_Boolean toEnable = Standard_True;
6895       if (++anArgIter < theArgNb
6896       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6897       {
6898         --anArgIter;
6899       }
6900       aCaps->useSystemBuffer = toEnable;
6901     }
6902     else if (anArgCase == "-accel"
6903           || anArgCase == "-acceleration")
6904     {
6905       Standard_Boolean toEnable = Standard_True;
6906       if (++anArgIter < theArgNb
6907       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6908       {
6909         --anArgIter;
6910       }
6911       aCaps->contextNoAccel = !toEnable;
6912     }
6913     else if (anArgCase == "-compat"
6914           || anArgCase == "-compatprofile"
6915           || anArgCase == "-compatible"
6916           || anArgCase == "-compatibleprofile")
6917     {
6918       Standard_Boolean toEnable = Standard_True;
6919       if (++anArgIter < theArgNb
6920       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6921       {
6922         --anArgIter;
6923       }
6924       aCaps->contextCompatible = toEnable;
6925       if (!aCaps->contextCompatible)
6926       {
6927         aCaps->ffpEnable = Standard_False;
6928       }
6929     }
6930     else if (anArgCase == "-core"
6931           || anArgCase == "-coreprofile")
6932     {
6933       Standard_Boolean toEnable = Standard_True;
6934       if (++anArgIter < theArgNb
6935       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6936       {
6937         --anArgIter;
6938       }
6939       aCaps->contextCompatible = !toEnable;
6940       if (!aCaps->contextCompatible)
6941       {
6942         aCaps->ffpEnable = Standard_False;
6943       }
6944     }
6945     else if (anArgCase == "-stereo"
6946           || anArgCase == "-quadbuffer")
6947     {
6948       Standard_Boolean toEnable = Standard_True;
6949       if (++anArgIter < theArgNb
6950       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6951       {
6952         --anArgIter;
6953       }
6954       aCaps->contextStereo = toEnable;
6955     }
6956     else if (anArgCase == "-noext"
6957           || anArgCase == "-noextensions"
6958           || anArgCase == "-noextension")
6959     {
6960       Standard_Boolean toDisable = Standard_True;
6961       if (++anArgIter < theArgNb
6962       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
6963       {
6964         --anArgIter;
6965       }
6966       aCaps->contextNoExtensions = toDisable;
6967     }
6968     else if (anArgCase == "-maxversion"
6969           || anArgCase == "-upperversion"
6970           || anArgCase == "-limitversion")
6971     {
6972       Standard_Integer aVer[2] = { -2, -1 };
6973       for (Standard_Integer aValIter = 0; aValIter < 2; ++aValIter)
6974       {
6975         if (anArgIter + 1 < theArgNb)
6976         {
6977           const TCollection_AsciiString aStr (theArgVec[anArgIter + 1]);
6978           if (aStr.IsIntegerValue())
6979           {
6980             aVer[aValIter] = aStr.IntegerValue();
6981             ++anArgIter;
6982           }
6983         }
6984       }
6985       if (aVer[0] < -1
6986        || aVer[1] < -1)
6987       {
6988         std::cout << "Syntax error at '" << anArgCase << "'\n";
6989         return 1;
6990       }
6991       aCaps->contextMajorVersionUpper = aVer[0];
6992       aCaps->contextMinorVersionUpper = aVer[1];
6993     }
6994     else
6995     {
6996       std::cout << "Error: unknown argument '" << anArg << "'\n";
6997       return 1;
6998     }
6999   }
7000   if (aCaps != &ViewerTest_myDefaultCaps)
7001   {
7002     ViewerTest_myDefaultCaps = *aCaps;
7003   }
7004   return 0;
7005 }
7006
7007 //==============================================================================
7008 //function : VMemGpu
7009 //purpose  :
7010 //==============================================================================
7011
7012 static int VMemGpu (Draw_Interpretor& theDI,
7013                     Standard_Integer  theArgNb,
7014                     const char**      theArgVec)
7015 {
7016   // get the context
7017   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
7018   if (aContextAIS.IsNull())
7019   {
7020     std::cerr << "No active view. Please call vinit.\n";
7021     return 1;
7022   }
7023
7024   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
7025   if (aDriver.IsNull())
7026   {
7027     std::cerr << "Graphic driver not available.\n";
7028     return 1;
7029   }
7030
7031   Standard_Size aFreeBytes = 0;
7032   TCollection_AsciiString anInfo;
7033   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
7034   {
7035     std::cerr << "Information not available.\n";
7036     return 1;
7037   }
7038
7039   if (theArgNb > 1 && *theArgVec[1] == 'f')
7040   {
7041     theDI << Standard_Real (aFreeBytes);
7042   }
7043   else
7044   {
7045     theDI << anInfo;
7046   }
7047
7048   return 0;
7049 }
7050
7051 // ==============================================================================
7052 // function : VReadPixel
7053 // purpose  :
7054 // ==============================================================================
7055 static int VReadPixel (Draw_Interpretor& theDI,
7056                        Standard_Integer  theArgNb,
7057                        const char**      theArgVec)
7058 {
7059   // get the active view
7060   Handle(V3d_View) aView = ViewerTest::CurrentView();
7061   if (aView.IsNull())
7062   {
7063     std::cerr << "No active view. Please call vinit.\n";
7064     return 1;
7065   }
7066   else if (theArgNb < 3)
7067   {
7068     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
7069     return 1;
7070   }
7071
7072   Image_Format         aFormat     = Image_Format_RGBA;
7073   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
7074
7075   Standard_Integer aWidth, aHeight;
7076   aView->Window()->Size (aWidth, aHeight);
7077   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
7078   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
7079   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
7080   {
7081     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
7082     return 1;
7083   }
7084
7085   bool toShowName = false, toShowHls = false, toShowHex = false, toShow_sRGB = false;
7086   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
7087   {
7088     TCollection_AsciiString aParam (theArgVec[anIter]);
7089     aParam.LowerCase();
7090     if (aParam == "-rgb"
7091      || aParam == "rgb"
7092      || aParam == "-srgb"
7093      || aParam == "srgb")
7094     {
7095       aFormat     = Image_Format_RGB;
7096       aBufferType = Graphic3d_BT_RGB;
7097       toShow_sRGB = aParam == "-srgb" || aParam == "srgb";
7098     }
7099     else if (aParam == "-hls"
7100           || aParam == "hls")
7101     {
7102       aFormat     = Image_Format_RGB;
7103       aBufferType = Graphic3d_BT_RGB;
7104       toShowHls   = Standard_True;
7105     }
7106     else if (aParam == "-rgbf"
7107           || aParam == "rgbf")
7108     {
7109       aFormat     = Image_Format_RGBF;
7110       aBufferType = Graphic3d_BT_RGB;
7111     }
7112     else if (aParam == "-rgba"
7113           || aParam == "rgba"
7114           || aParam == "-srgba"
7115           || aParam == "srgba")
7116     {
7117       aFormat     = Image_Format_RGBA;
7118       aBufferType = Graphic3d_BT_RGBA;
7119       toShow_sRGB = aParam == "-srgba" || aParam == "srgba";
7120     }
7121     else if (aParam == "-rgbaf"
7122           || aParam == "rgbaf")
7123     {
7124       aFormat     = Image_Format_RGBAF;
7125       aBufferType = Graphic3d_BT_RGBA;
7126     }
7127     else if (aParam == "-depth"
7128           || aParam == "depth")
7129     {
7130       aFormat     = Image_Format_GrayF;
7131       aBufferType = Graphic3d_BT_Depth;
7132     }
7133     else if (aParam == "-name"
7134           || aParam == "name")
7135     {
7136       toShowName = Standard_True;
7137     }
7138     else if (aParam == "-hex"
7139           || aParam == "hex")
7140     {
7141       toShowHex = Standard_True;
7142     }
7143     else
7144     {
7145       std::cout << "Syntax error at '" << aParam << "'\n";
7146       return 1;
7147     }
7148   }
7149
7150   Image_PixMap anImage;
7151   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
7152   {
7153     std::cerr << "Image allocation failed\n";
7154     return 1;
7155   }
7156   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
7157   {
7158     std::cerr << "Image dump failed\n";
7159     return 1;
7160   }
7161
7162   // redirect possible warning messages that could have been added by ToPixMap
7163   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
7164   // contaminate result of the command
7165   Standard_CString aWarnLog = theDI.Result();
7166   if (aWarnLog != NULL && aWarnLog[0] != '\0')
7167   {
7168     std::cout << aWarnLog << std::endl;
7169   }
7170   theDI.Reset();
7171
7172   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY, true);
7173   if (toShowName)
7174   {
7175     if (aBufferType == Graphic3d_BT_RGBA)
7176     {
7177       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
7178     }
7179     else
7180     {
7181       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
7182     }
7183   }
7184   else if (toShowHex)
7185   {
7186     if (aBufferType == Graphic3d_BT_RGBA)
7187     {
7188       theDI << Quantity_ColorRGBA::ColorToHex (aColor);
7189     }
7190     else
7191     {
7192       theDI << Quantity_Color::ColorToHex (aColor.GetRGB());
7193     }
7194   }
7195   else
7196   {
7197     switch (aBufferType)
7198     {
7199       default:
7200       case Graphic3d_BT_RGB:
7201       {
7202         if (toShowHls)
7203         {
7204           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
7205         }
7206         else if (toShow_sRGB)
7207         {
7208           const Graphic3d_Vec4 aColor_sRGB = Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor);
7209           theDI << aColor_sRGB.r() << " " << aColor_sRGB.g() << " " << aColor_sRGB.b();
7210         }
7211         else
7212         {
7213           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
7214         }
7215         break;
7216       }
7217       case Graphic3d_BT_RGBA:
7218       {
7219         const Graphic3d_Vec4 aVec4 = toShow_sRGB ? Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor) : (Graphic3d_Vec4 )aColor;
7220         theDI << aVec4.r() << " " << aVec4.g() << " " << aVec4.b() << " " << aVec4.a();
7221         break;
7222       }
7223       case Graphic3d_BT_Depth:
7224       {
7225         theDI << aColor.GetRGB().Red();
7226         break;
7227       }
7228     }
7229   }
7230
7231   return 0;
7232 }
7233
7234 //! Auxiliary presentation for an image plane.
7235 class ViewerTest_ImagePrs : public AIS_InteractiveObject
7236 {
7237 public:
7238   //! Main constructor.
7239   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
7240                        const Standard_Real theWidth,
7241                        const Standard_Real theHeight,
7242                        const TCollection_AsciiString& theLabel)
7243   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
7244   {
7245     SetDisplayMode (0);
7246     SetHilightMode (1);
7247     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
7248     {
7249       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
7250       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
7251       Graphic3d_MaterialAspect aMat;
7252       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
7253       aMat.SetAmbientColor  (Quantity_NOC_BLACK);
7254       aMat.SetDiffuseColor  (Quantity_NOC_WHITE);
7255       aMat.SetSpecularColor (Quantity_NOC_BLACK);
7256       aMat.SetEmissiveColor (Quantity_NOC_BLACK);
7257       aFillAspect->SetFrontMaterial (aMat);
7258       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
7259       aFillAspect->SetTextureMapOn();
7260     }
7261     {
7262       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
7263       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
7264       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
7265       myDrawer->SetTextAspect (aTextAspect);
7266     }
7267     {
7268       const gp_Dir aNorm (0.0, 0.0, 1.0);
7269       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
7270       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
7271       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
7272       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
7273       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
7274       myTris->AddEdge (1);
7275       myTris->AddEdge (2);
7276       myTris->AddEdge (3);
7277       myTris->AddEdge (3);
7278       myTris->AddEdge (2);
7279       myTris->AddEdge (4);
7280
7281       myRect = new Graphic3d_ArrayOfPolylines (4);
7282       myRect->AddVertex (myTris->Vertice (1));
7283       myRect->AddVertex (myTris->Vertice (3));
7284       myRect->AddVertex (myTris->Vertice (4));
7285       myRect->AddVertex (myTris->Vertice (2));
7286     }
7287   }
7288
7289   //! Returns TRUE for accepted display modes.
7290   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7291
7292   //! Compute presentation.
7293   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7294   {
7295     switch (theMode)
7296     {
7297       case 0:
7298       {
7299         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7300         aGroup->AddPrimitiveArray (myTris);
7301         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7302         aGroup->AddPrimitiveArray (myRect);
7303         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7304         return;
7305       }
7306       case 1:
7307       {
7308         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7309         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7310         aGroup->AddPrimitiveArray (myRect);
7311         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7312         return;
7313       }
7314     }
7315   }
7316
7317   //! Compute selection.
7318   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7319   {
7320     if (theMode == 0)
7321     {
7322       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7323       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7324       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7325       theSel->Add (aSensitive);
7326     }
7327   }
7328
7329 private:
7330   Handle(Graphic3d_ArrayOfTriangles) myTris;
7331   Handle(Graphic3d_ArrayOfPolylines) myRect;
7332   TCollection_AsciiString myLabel;
7333   Standard_Real myWidth;
7334   Standard_Real myHeight;
7335 };
7336
7337 //==============================================================================
7338 //function : VDiffImage
7339 //purpose  : The draw-command compares two images.
7340 //==============================================================================
7341
7342 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7343 {
7344   if (theArgNb < 3)
7345   {
7346     std::cout << "Syntax error: not enough arguments.\n";
7347     return 1;
7348   }
7349
7350   Standard_Integer anArgIter = 1;
7351   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7352   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7353   TCollection_AsciiString aDiffImagePath;
7354   Standard_Real    aTolColor        = -1.0;
7355   Standard_Integer toBlackWhite     = -1;
7356   Standard_Integer isBorderFilterOn = -1;
7357   Standard_Boolean isOldSyntax = Standard_False;
7358   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7359   for (; anArgIter < theArgNb; ++anArgIter)
7360   {
7361     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7362     anArg.LowerCase();
7363     if (anArgIter + 1 < theArgNb
7364      && (anArg == "-toleranceofcolor"
7365       || anArg == "-tolerancecolor"
7366       || anArg == "-tolerance"
7367       || anArg == "-toler"))
7368     {
7369       aTolColor = Atof (theArgVec[++anArgIter]);
7370       if (aTolColor < 0.0 || aTolColor > 1.0)
7371       {
7372         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7373         return 1;
7374       }
7375     }
7376     else if (anArg == "-blackwhite")
7377     {
7378       Standard_Boolean toEnable = Standard_True;
7379       if (anArgIter + 1 < theArgNb
7380        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7381       {
7382         ++anArgIter;
7383       }
7384       toBlackWhite = toEnable ? 1 : 0;
7385     }
7386     else if (anArg == "-borderfilter")
7387     {
7388       Standard_Boolean toEnable = Standard_True;
7389       if (anArgIter + 1 < theArgNb
7390        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7391       {
7392         ++anArgIter;
7393       }
7394       isBorderFilterOn = toEnable ? 1 : 0;
7395     }
7396     else if (anArg == "-exitonclose")
7397     {
7398       ViewerTest_EventManager::ToExitOnCloseView() = true;
7399       if (anArgIter + 1 < theArgNb
7400        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToExitOnCloseView()))
7401       {
7402         ++anArgIter;
7403       }
7404     }
7405     else if (anArg == "-closeonescape"
7406           || anArg == "-closeonesc")
7407     {
7408       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
7409       if (anArgIter + 1 < theArgNb
7410        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
7411       {
7412         ++anArgIter;
7413       }
7414     }
7415     else if (anArgIter + 3 < theArgNb
7416           && anArg == "-display")
7417     {
7418       aViewName   = theArgVec[++anArgIter];
7419       aPrsNameRef = theArgVec[++anArgIter];
7420       aPrsNameNew = theArgVec[++anArgIter];
7421       if (anArgIter + 1 < theArgNb
7422       && *theArgVec[anArgIter + 1] != '-')
7423       {
7424         aPrsNameDiff = theArgVec[++anArgIter];
7425       }
7426     }
7427     else if (aTolColor < 0.0
7428           && anArg.IsRealValue())
7429     {
7430       isOldSyntax = Standard_True;
7431       aTolColor = anArg.RealValue();
7432       if (aTolColor < 0.0 || aTolColor > 1.0)
7433       {
7434         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7435         return 1;
7436       }
7437     }
7438     else if (isOldSyntax
7439           && toBlackWhite == -1
7440           && (anArg == "0" || anArg == "1"))
7441     {
7442       toBlackWhite = anArg == "1" ? 1 : 0;
7443     }
7444     else if (isOldSyntax
7445           && isBorderFilterOn == -1
7446           && (anArg == "0" || anArg == "1"))
7447     {
7448       isBorderFilterOn = anArg == "1" ? 1 : 0;
7449     }
7450     else if (aDiffImagePath.IsEmpty())
7451     {
7452       aDiffImagePath = theArgVec[anArgIter];
7453     }
7454     else
7455     {
7456       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7457       return 1;
7458     }
7459   }
7460
7461   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7462   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7463   if (!anImgRef->Load (anImgPathRef))
7464   {
7465     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7466     return 1;
7467   }
7468   if (!anImgNew->Load (anImgPathNew))
7469   {
7470     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7471     return 1;
7472   }
7473
7474   // compare the images
7475   Image_Diff aComparer;
7476   Standard_Integer aDiffColorsNb = -1;
7477   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7478   {
7479     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7480     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7481     aDiffColorsNb = aComparer.Compare();
7482     theDI << aDiffColorsNb << "\n";
7483   }
7484
7485   // save image of difference
7486   Handle(Image_AlienPixMap) aDiff;
7487   if (aDiffColorsNb > 0
7488   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7489   {
7490     aDiff = new Image_AlienPixMap();
7491     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7492     {
7493       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7494       return 1;
7495     }
7496     aComparer.SaveDiffImage (*aDiff);
7497     if (!aDiffImagePath.IsEmpty()
7498      && !aDiff->Save (aDiffImagePath))
7499     {
7500       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7501       return 1;
7502     }
7503   }
7504
7505   if (aViewName.IsEmpty())
7506   {
7507     return 0;
7508   }
7509
7510   ViewerTest_Names aViewNames (aViewName);
7511   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7512   {
7513     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7514     theDI.Eval (aCommand.ToCString());
7515   }
7516
7517   Standard_Integer aPxLeft = 0;
7518   Standard_Integer aPxTop  = 0;
7519   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7520   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7521                               ? int(anImgRef->SizeY() * 2)
7522                               : int(anImgRef->SizeY());
7523   TCollection_AsciiString aDisplayName;
7524   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7525                                                             aViewName, aDisplayName);
7526
7527   Standard_Real aRatio = anImgRef->Ratio();
7528   Standard_Real aSizeX = 1.0;
7529   Standard_Real aSizeY = aSizeX / aRatio;
7530   {
7531     OSD_Path aPath (anImgPathRef);
7532     TCollection_AsciiString aLabelRef;
7533     if (!aPath.Name().IsEmpty())
7534     {
7535       aLabelRef = aPath.Name() + aPath.Extension();
7536     }
7537     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7538
7539     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7540     gp_Trsf aTrsfRef;
7541     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7542     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7543     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7544   }
7545   {
7546     OSD_Path aPath (anImgPathNew);
7547     TCollection_AsciiString aLabelNew;
7548     if (!aPath.Name().IsEmpty())
7549     {
7550       aLabelNew = aPath.Name() + aPath.Extension();
7551     }
7552     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7553
7554     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7555     gp_Trsf aTrsfRef;
7556     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7557     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7558     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7559   }
7560   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7561   if (!aDiff.IsNull())
7562   {
7563     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7564     gp_Trsf aTrsfDiff;
7565     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7566     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7567   }
7568   if (!aPrsNameDiff.IsEmpty())
7569   {
7570     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7571   }
7572   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7573   ViewerTest::CurrentView()->FitAll();
7574   return 0;
7575 }
7576
7577 //=======================================================================
7578 //function : VSelect
7579 //purpose  : Emulates different types of selection by mouse:
7580 //           1) single click selection
7581 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7582 //           3) selection with polygon having corners at
7583 //           pixel positions (x1,y1),...,(xn,yn)
7584 //           4) any of these selections with shift button pressed
7585 //=======================================================================
7586 static Standard_Integer VSelect (Draw_Interpretor& ,
7587                                  Standard_Integer theNbArgs,
7588                                  const char** theArgVec)
7589 {
7590   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7591   if (aCtx.IsNull())
7592   {
7593     std::cout << "Error: no active View\n";
7594     return 1;
7595   }
7596
7597   NCollection_Sequence<Graphic3d_Vec2i> aPnts;
7598   bool isShiftSelection = false, toAllowOverlap = false;
7599   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7600   {
7601     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7602     anArg.LowerCase();
7603     if (anArg == "-allowoverlap")
7604     {
7605       toAllowOverlap = true;
7606       if (anArgIter + 1 < theNbArgs
7607        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toAllowOverlap))
7608       {
7609         ++anArgIter;
7610       }
7611     }
7612     else if (anArgIter + 1 < theNbArgs
7613           && anArg.IsIntegerValue()
7614           && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
7615     {
7616       const TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
7617       aPnts.Append (Graphic3d_Vec2i (anArg.IntegerValue(), anArgNext.IntegerValue()));
7618     }
7619     else if (anArgIter + 1 == theNbArgs
7620           && anArg.IsIntegerValue())
7621     {
7622       isShiftSelection = anArg.IntegerValue() == 1;
7623     }
7624     else
7625     {
7626       std::cout << "Syntax error at '" << anArg << "'\n";
7627       return 1;
7628     }
7629   }
7630   if (toAllowOverlap
7631    && aPnts.Length() != 2)
7632   {
7633     std::cout << "Syntax error: -allowoverlap key is applied only for rectangle selection\n";
7634     return 1;
7635   }
7636   if (toAllowOverlap)
7637   {
7638     aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
7639   }
7640
7641   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7642   if (aPnts.IsEmpty())
7643   {
7644     if (isShiftSelection)
7645     {
7646       aCtx->ShiftSelect (false);
7647     }
7648     else
7649     {
7650       aCtx->Select (false);
7651     }
7652     aCtx->CurrentViewer()->Invalidate();
7653   }
7654   else if (aPnts.Length() == 2)
7655   {
7656     if (toAllowOverlap
7657      && aPnts.First().y() < aPnts.Last().y())
7658     {
7659       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7660     }
7661     else if (!toAllowOverlap
7662            && aPnts.First().y() > aPnts.Last().y())
7663     {
7664       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7665     }
7666     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7667   }
7668   else
7669   {
7670     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7671   }
7672   aCurrentEventManager->FlushViewEvents (aCtx, ViewerTest::CurrentView(), true);
7673   return 0;
7674 }
7675
7676 //=======================================================================
7677 //function : VMoveTo
7678 //purpose  : Emulates cursor movement to defined pixel position
7679 //=======================================================================
7680 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7681                                 Standard_Integer theNbArgs,
7682                                 const char**     theArgVec)
7683 {
7684   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7685   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7686   if (aContext.IsNull())
7687   {
7688     std::cout << "Error: no active View\n";
7689     return 1;
7690   }
7691
7692   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7693   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7694   {
7695     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7696     anArgStr.LowerCase();
7697     if (anArgStr == "-reset"
7698      || anArgStr == "-clear")
7699     {
7700       if (anArgIter + 1 < theNbArgs)
7701       {
7702         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7703         return 1;
7704       }
7705
7706       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7707                                        && aContext->CurrentViewer()->GridEcho();
7708       if (toEchoGrid)
7709       {
7710         aContext->CurrentViewer()->HideGridEcho (aView);
7711       }
7712       if (aContext->ClearDetected() || toEchoGrid)
7713       {
7714         aContext->CurrentViewer()->RedrawImmediate();
7715       }
7716       return 0;
7717     }
7718     else if (aMousePos.x() == IntegerLast()
7719           && anArgStr.IsIntegerValue())
7720     {
7721       aMousePos.x() = anArgStr.IntegerValue();
7722     }
7723     else if (aMousePos.y() == IntegerLast()
7724           && anArgStr.IsIntegerValue())
7725     {
7726       aMousePos.y() = anArgStr.IntegerValue();
7727     }
7728     else
7729     {
7730       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7731       return 1;
7732     }
7733   }
7734
7735   if (aMousePos.x() == IntegerLast()
7736    || aMousePos.y() == IntegerLast())
7737   {
7738     std::cout << "Syntax error: wrong number of arguments\n";
7739     return 1;
7740   }
7741
7742   ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
7743   ViewerTest::CurrentEventManager()->UpdateMousePosition (aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
7744   ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
7745
7746   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7747   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7748   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7749   {
7750     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7751     {
7752       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7753       break;
7754     }
7755   }
7756   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7757   return 0;
7758 }
7759
7760 namespace
7761 {
7762   //! Global map storing all animations registered in ViewerTest.
7763   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7764
7765   //! The animation calling the Draw Harness command.
7766   class ViewerTest_AnimationProc : public AIS_Animation
7767   {
7768   public:
7769
7770     //! Main constructor.
7771     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7772                               Draw_Interpretor* theDI,
7773                               const TCollection_AsciiString& theCommand)
7774     : AIS_Animation (theAnimationName),
7775       myDrawInter(theDI),
7776       myCommand  (theCommand)
7777     {
7778       //
7779     }
7780
7781   protected:
7782
7783     //! Evaluate the command.
7784     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7785     {
7786       TCollection_AsciiString aCmd = myCommand;
7787       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7788       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7789       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7790       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7791       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7792       myDrawInter->Eval (aCmd.ToCString());
7793     }
7794
7795     //! Find the keyword in the command and replace it with value.
7796     //! @return the position of the keyword to pass value
7797     void replace (TCollection_AsciiString&       theCmd,
7798                   const TCollection_AsciiString& theKey,
7799                   const TCollection_AsciiString& theVal)
7800     {
7801       TCollection_AsciiString aCmd (theCmd);
7802       aCmd.LowerCase();
7803       const Standard_Integer aPos = aCmd.Search (theKey);
7804       if (aPos == -1)
7805       {
7806         return;
7807       }
7808
7809       TCollection_AsciiString aPart1, aPart2;
7810       Standard_Integer aPart1To = aPos - 1;
7811       if (aPart1To >= 1
7812        && aPart1To <= theCmd.Length())
7813       {
7814         aPart1 = theCmd.SubString (1, aPart1To);
7815       }
7816
7817       Standard_Integer aPart2From = aPos + theKey.Length();
7818       if (aPart2From >= 1
7819        && aPart2From <= theCmd.Length())
7820       {
7821         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7822       }
7823
7824       theCmd = aPart1 + theVal + aPart2;
7825     }
7826
7827   protected:
7828
7829     Draw_Interpretor*       myDrawInter;
7830     TCollection_AsciiString myCommand;
7831
7832   };
7833
7834   //! Replace the animation with the new one.
7835   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7836                                 Handle(AIS_Animation)&       theAnimation,
7837                                 const Handle(AIS_Animation)& theAnimationNew)
7838   {
7839     theAnimationNew->CopyFrom (theAnimation);
7840     if (!theParentAnimation.IsNull())
7841     {
7842       theParentAnimation->Replace (theAnimation, theAnimationNew);
7843     }
7844     else
7845     {
7846       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
7847       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7848     }
7849     theAnimation = theAnimationNew;
7850   }
7851
7852   //! Parse the point.
7853   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7854   {
7855     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7856     if (!anXYZ[0].IsRealValue()
7857      || !anXYZ[1].IsRealValue()
7858      || !anXYZ[2].IsRealValue())
7859     {
7860       return Standard_False;
7861     }
7862
7863     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7864     return Standard_True;
7865   }
7866
7867   //! Parse the quaternion.
7868   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7869   {
7870     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7871     if (!anXYZW[0].IsRealValue()
7872      || !anXYZW[1].IsRealValue()
7873      || !anXYZW[2].IsRealValue()
7874      || !anXYZW[3].IsRealValue())
7875     {
7876       return Standard_False;
7877     }
7878
7879     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7880     return Standard_True;
7881   }
7882
7883   //! Auxiliary class for flipping image upside-down.
7884   class ImageFlipper
7885   {
7886   public:
7887
7888     //! Empty constructor.
7889     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7890
7891     //! Perform flipping.
7892     Standard_Boolean FlipY (Image_PixMap& theImage)
7893     {
7894       if (theImage.IsEmpty()
7895        || theImage.SizeX() == 0
7896        || theImage.SizeY() == 0)
7897       {
7898         return Standard_False;
7899       }
7900
7901       const Standard_Size aRowSize = theImage.SizeRowBytes();
7902       if (myTmp.Size() < aRowSize
7903       && !myTmp.Allocate (aRowSize))
7904       {
7905         return Standard_False;
7906       }
7907
7908       // for odd height middle row should be left as is
7909       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7910       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7911       {
7912         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7913         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7914         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7915         memcpy (aTop,               aBot,         aRowSize);
7916         memcpy (aBot,               myTmp.Data(), aRowSize);
7917       }
7918       return Standard_True;
7919     }
7920
7921   private:
7922     NCollection_Buffer myTmp;
7923   };
7924
7925 }
7926
7927 //=================================================================================================
7928 //function : VViewParams
7929 //purpose  : Gets or sets AIS View characteristics
7930 //=================================================================================================
7931 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7932 {
7933   Handle(V3d_View) aView = ViewerTest::CurrentView();
7934   if (aView.IsNull())
7935   {
7936     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7937     return 1;
7938   }
7939
7940   Standard_Boolean toSetProj     = Standard_False;
7941   Standard_Boolean toSetUp       = Standard_False;
7942   Standard_Boolean toSetAt       = Standard_False;
7943   Standard_Boolean toSetEye      = Standard_False;
7944   Standard_Boolean toSetScale    = Standard_False;
7945   Standard_Boolean toSetSize     = Standard_False;
7946   Standard_Boolean toSetCenter2d = Standard_False;
7947   Standard_Real    aViewScale = aView->Scale();
7948   Standard_Real    aViewSize  = 1.0;
7949   Graphic3d_Vec2i  aCenter2d;
7950   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7951   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7952   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7953   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7954   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7955   if (theArgsNb == 1)
7956   {
7957     // print all of the available view parameters
7958     char aText[4096];
7959     Sprintf (aText,
7960              "Scale: %g\n"
7961              "Proj:  %12g %12g %12g\n"
7962              "Up:    %12g %12g %12g\n"
7963              "At:    %12g %12g %12g\n"
7964              "Eye:   %12g %12g %12g\n",
7965               aViewScale,
7966               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7967               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7968               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7969               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7970     theDi << aText;
7971     return 0;
7972   }
7973
7974   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7975   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7976   {
7977     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7978     anArg.LowerCase();
7979     if (anUpdateTool.parseRedrawMode (anArg))
7980     {
7981       continue;
7982     }
7983     else if (anArg == "-cmd"
7984           || anArg == "-command"
7985           || anArg == "-args")
7986     {
7987       char aText[4096];
7988       Sprintf (aText,
7989                "-scale %g "
7990                "-proj %g %g %g "
7991                "-up %g %g %g "
7992                "-at %g %g %g\n",
7993                 aViewScale,
7994                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7995                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7996                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7997       theDi << aText;
7998     }
7999     else if (anArg == "-scale"
8000           || anArg == "-size")
8001     {
8002       if (anArgIter + 1 < theArgsNb
8003        && *theArgVec[anArgIter + 1] != '-')
8004       {
8005         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
8006         if (aValueArg.IsRealValue())
8007         {
8008           ++anArgIter;
8009           if (anArg == "-scale")
8010           {
8011             toSetScale = Standard_True;
8012             aViewScale = aValueArg.RealValue();
8013           }
8014           else if (anArg == "-size")
8015           {
8016             toSetSize = Standard_True;
8017             aViewSize = aValueArg.RealValue();
8018           }
8019           continue;
8020         }
8021       }
8022       if (anArg == "-scale")
8023       {
8024         theDi << "Scale: " << aView->Scale() << "\n";
8025       }
8026       else if (anArg == "-size")
8027       {
8028         Graphic3d_Vec2d aSizeXY;
8029         aView->Size (aSizeXY.x(), aSizeXY.y());
8030         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
8031       }
8032     }
8033     else if (anArg == "-eye"
8034           || anArg == "-at"
8035           || anArg == "-up"
8036           || anArg == "-proj")
8037     {
8038       if (anArgIter + 3 < theArgsNb)
8039       {
8040         gp_XYZ anXYZ;
8041         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
8042         {
8043           anArgIter += 3;
8044           if (anArg == "-eye")
8045           {
8046             toSetEye = Standard_True;
8047             aViewEye = anXYZ;
8048           }
8049           else if (anArg == "-at")
8050           {
8051             toSetAt = Standard_True;
8052             aViewAt = anXYZ;
8053           }
8054           else if (anArg == "-up")
8055           {
8056             toSetUp = Standard_True;
8057             aViewUp = anXYZ;
8058           }
8059           else if (anArg == "-proj")
8060           {
8061             toSetProj = Standard_True;
8062             aViewProj = anXYZ;
8063           }
8064           continue;
8065         }
8066       }
8067
8068       if (anArg == "-eye")
8069       {
8070         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
8071       }
8072       else if (anArg == "-at")
8073       {
8074         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
8075       }
8076       else if (anArg == "-up")
8077       {
8078         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
8079       }
8080       else if (anArg == "-proj")
8081       {
8082         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
8083       }
8084     }
8085     else if (anArg == "-center")
8086     {
8087       if (anArgIter + 2 < theArgsNb)
8088       {
8089         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
8090         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
8091         if (anX.IsIntegerValue()
8092          && anY.IsIntegerValue())
8093         {
8094           toSetCenter2d = Standard_True;
8095           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
8096         }
8097       }
8098     }
8099     else
8100     {
8101       std::cout << "Syntax error at '" << anArg << "'\n";
8102       return 1;
8103     }
8104   }
8105
8106   // change view parameters in proper order
8107   if (toSetScale)
8108   {
8109     aView->SetScale (aViewScale);
8110   }
8111   if (toSetSize)
8112   {
8113     aView->SetSize (aViewSize);
8114   }
8115   if (toSetEye)
8116   {
8117     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
8118   }
8119   if (toSetAt)
8120   {
8121     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
8122   }
8123   if (toSetProj)
8124   {
8125     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
8126   }
8127   if (toSetUp)
8128   {
8129     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
8130   }
8131   if (toSetCenter2d)
8132   {
8133     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
8134   }
8135
8136   return 0;
8137 }
8138
8139 //==============================================================================
8140 //function : V2DMode
8141 //purpose  :
8142 //==============================================================================
8143 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
8144 {
8145   bool is2dMode = true;
8146   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
8147   if (aV3dView.IsNull())
8148   {
8149     std::cout << "Error: no active view.\n";
8150     return 1;
8151   }
8152   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8153   {
8154     const TCollection_AsciiString anArg = theArgVec[anArgIt];
8155     TCollection_AsciiString anArgCase = anArg;
8156     anArgCase.LowerCase();
8157     if (anArgIt + 1 < theArgsNb
8158      && anArgCase == "-name")
8159     {
8160       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
8161       TCollection_AsciiString aViewName = aViewNames.GetViewName();
8162       if (!ViewerTest_myViews.IsBound1 (aViewName))
8163       {
8164         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
8165         return 1;
8166       }
8167       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
8168     }
8169     else if (anArgCase == "-mode")
8170     {
8171       if (anArgIt + 1 < theArgsNb
8172        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
8173       {
8174         ++anArgIt;
8175       }
8176     }
8177     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
8178     {
8179       //
8180     }
8181     else
8182     {
8183       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
8184       return 1;
8185     }
8186   }
8187
8188   aV3dView->SetView2DMode (is2dMode);
8189   return 0;
8190 }
8191
8192 //==============================================================================
8193 //function : VAnimation
8194 //purpose  :
8195 //==============================================================================
8196 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
8197                                     Standard_Integer  theArgNb,
8198                                     const char**      theArgVec)
8199 {
8200   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
8201   if (theArgNb < 2)
8202   {
8203     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
8204          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
8205     {
8206       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
8207     }
8208     return 0;
8209   }
8210   if (aCtx.IsNull())
8211   {
8212     std::cout << "Error: no active view\n";
8213     return 1;
8214   }
8215
8216   Standard_Integer anArgIter = 1;
8217   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
8218   if (aNameArg.IsEmpty())
8219   {
8220     std::cout << "Syntax error: animation name is not defined.\n";
8221     return 1;
8222   }
8223
8224   TCollection_AsciiString aNameArgLower = aNameArg;
8225   aNameArgLower.LowerCase();
8226   if (aNameArgLower == "-reset"
8227    || aNameArgLower == "-clear")
8228   {
8229     ViewerTest_AnimationTimelineMap.Clear();
8230     return 0;
8231   }
8232   else if (aNameArg.Value (1) == '-')
8233   {
8234     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
8235     return 1;
8236   }
8237
8238   const char* aNameSplitter = "/";
8239   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
8240   if (aSplitPos == -1)
8241   {
8242     aNameSplitter = ".";
8243     aSplitPos = aNameArg.Search (aNameSplitter);
8244   }
8245
8246   // find existing or create a new animation by specified name within syntax "parent.child".
8247   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
8248   for (; !aNameArg.IsEmpty();)
8249   {
8250     TCollection_AsciiString aNameParent;
8251     if (aSplitPos != -1)
8252     {
8253       if (aSplitPos == aNameArg.Length())
8254       {
8255         std::cout << "Syntax error: animation name is not defined.\n";
8256         return 1;
8257       }
8258
8259       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
8260       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
8261
8262       aSplitPos = aNameArg.Search (aNameSplitter);
8263     }
8264     else
8265     {
8266       aNameParent = aNameArg;
8267       aNameArg.Clear();
8268     }
8269
8270     if (anAnimation.IsNull())
8271     {
8272       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
8273       {
8274         anAnimation = new AIS_Animation (aNameParent);
8275         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8276       }
8277       aRootAnimation = anAnimation;
8278     }
8279     else
8280     {
8281       aParentAnimation = anAnimation;
8282       anAnimation = aParentAnimation->Find (aNameParent);
8283       if (anAnimation.IsNull())
8284       {
8285         anAnimation = new AIS_Animation (aNameParent);
8286         aParentAnimation->Add (anAnimation);
8287       }
8288     }
8289   }
8290
8291   if (anArgIter >= theArgNb)
8292   {
8293     // just print the list of children
8294     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8295     {
8296       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8297     }
8298     return 0;
8299   }
8300
8301   // animation parameters
8302   Standard_Boolean toPlay = Standard_False;
8303   Standard_Real aPlaySpeed     = 1.0;
8304   Standard_Real aPlayStartTime = anAnimation->StartPts();
8305   Standard_Real aPlayDuration  = anAnimation->Duration();
8306   Standard_Boolean isFreeCamera = Standard_False;
8307   Standard_Boolean isLockLoop   = Standard_False;
8308
8309   // video recording parameters
8310   TCollection_AsciiString aRecFile;
8311   Image_VideoParams aRecParams;
8312
8313   Handle(V3d_View) aView = ViewerTest::CurrentView();
8314   for (; anArgIter < theArgNb; ++anArgIter)
8315   {
8316     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8317     anArg.LowerCase();
8318     // general options
8319     if (anArg == "-reset"
8320      || anArg == "-clear")
8321     {
8322       anAnimation->Clear();
8323     }
8324     else if (anArg == "-remove"
8325           || anArg == "-del"
8326           || anArg == "-delete")
8327     {
8328       if (!aParentAnimation.IsNull())
8329       {
8330         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8331       }
8332       else
8333       {
8334         aParentAnimation->Remove (anAnimation);
8335       }
8336     }
8337     // playback options
8338     else if (anArg == "-play")
8339     {
8340       toPlay = Standard_True;
8341       if (++anArgIter < theArgNb)
8342       {
8343         if (*theArgVec[anArgIter] == '-')
8344         {
8345           --anArgIter;
8346           continue;
8347         }
8348         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8349
8350         if (++anArgIter < theArgNb)
8351         {
8352           if (*theArgVec[anArgIter] == '-')
8353           {
8354             --anArgIter;
8355             continue;
8356           }
8357           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8358         }
8359       }
8360     }
8361     else if (anArg == "-resume")
8362     {
8363       toPlay = Standard_True;
8364       aPlayStartTime = anAnimation->ElapsedTime();
8365       if (++anArgIter < theArgNb)
8366       {
8367         if (*theArgVec[anArgIter] == '-')
8368         {
8369           --anArgIter;
8370           continue;
8371         }
8372
8373         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8374       }
8375     }
8376     else if (anArg == "-playspeed"
8377           || anArg == "-speed")
8378     {
8379       if (++anArgIter >= theArgNb)
8380       {
8381         std::cout << "Syntax error at " << anArg << ".\n";
8382         return 1;
8383       }
8384       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8385     }
8386     else if (anArg == "-lock"
8387           || anArg == "-lockloop"
8388           || anArg == "-playlockloop")
8389     {
8390       isLockLoop = Standard_True;
8391     }
8392     else if (anArg == "-freecamera"
8393           || anArg == "-playfreecamera"
8394           || anArg == "-freelook")
8395     {
8396       isFreeCamera = Standard_True;
8397     }
8398     // video recodring options
8399     else if (anArg == "-rec"
8400           || anArg == "-record")
8401     {
8402       if (++anArgIter >= theArgNb)
8403       {
8404         std::cout << "Syntax error at " << anArg << ".\n";
8405         return 1;
8406       }
8407
8408       aRecFile = theArgVec[anArgIter];
8409       if (aRecParams.FpsNum <= 0)
8410       {
8411         aRecParams.FpsNum = 24;
8412       }
8413
8414       if (anArgIter + 2 < theArgNb
8415       && *theArgVec[anArgIter + 1] != '-'
8416       && *theArgVec[anArgIter + 2] != '-')
8417       {
8418         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8419         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8420         if (aWidthArg .IsIntegerValue()
8421          && aHeightArg.IsIntegerValue())
8422         {
8423           aRecParams.Width  = aWidthArg .IntegerValue();
8424           aRecParams.Height = aHeightArg.IntegerValue();
8425           anArgIter += 2;
8426         }
8427       }
8428     }
8429     else if (anArg == "-fps")
8430     {
8431       if (++anArgIter >= theArgNb)
8432       {
8433         std::cout << "Syntax error at " << anArg << ".\n";
8434         return 1;
8435       }
8436
8437       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8438       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8439       if (aSplitIndex == 0)
8440       {
8441         aRecParams.FpsNum = aFpsArg.IntegerValue();
8442       }
8443       else
8444       {
8445         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8446         aFpsArg.Split (aFpsArg.Length() - 1);
8447         const TCollection_AsciiString aNumStr = aFpsArg;
8448         aRecParams.FpsNum = aNumStr.IntegerValue();
8449         aRecParams.FpsDen = aDenStr.IntegerValue();
8450         if (aRecParams.FpsDen < 1)
8451         {
8452           std::cout << "Syntax error at " << anArg << ".\n";
8453           return 1;
8454         }
8455       }
8456     }
8457     else if (anArg == "-format")
8458     {
8459       if (++anArgIter >= theArgNb)
8460       {
8461         std::cout << "Syntax error at " << anArg << ".\n";
8462         return 1;
8463       }
8464       aRecParams.Format = theArgVec[anArgIter];
8465     }
8466     else if (anArg == "-pix_fmt"
8467           || anArg == "-pixfmt"
8468           || anArg == "-pixelformat")
8469     {
8470       if (++anArgIter >= theArgNb)
8471       {
8472         std::cout << "Syntax error at " << anArg << ".\n";
8473         return 1;
8474       }
8475       aRecParams.PixelFormat = theArgVec[anArgIter];
8476     }
8477     else if (anArg == "-codec"
8478           || anArg == "-vcodec"
8479           || anArg == "-videocodec")
8480     {
8481       if (++anArgIter >= theArgNb)
8482       {
8483         std::cout << "Syntax error at " << anArg << ".\n";
8484         return 1;
8485       }
8486       aRecParams.VideoCodec = theArgVec[anArgIter];
8487     }
8488     else if (anArg == "-crf"
8489           || anArg == "-preset"
8490           || anArg == "-qp")
8491     {
8492       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8493       if (++anArgIter >= theArgNb)
8494       {
8495         std::cout << "Syntax error at " << anArg << ".\n";
8496         return 1;
8497       }
8498
8499       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8500     }
8501     // animation definition options
8502     else if (anArg == "-start"
8503           || anArg == "-starttime"
8504           || anArg == "-startpts")
8505     {
8506       if (++anArgIter >= theArgNb)
8507       {
8508         std::cout << "Syntax error at " << anArg << ".\n";
8509         return 1;
8510       }
8511
8512       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8513       aRootAnimation->UpdateTotalDuration();
8514     }
8515     else if (anArg == "-end"
8516           || anArg == "-endtime"
8517           || anArg == "-endpts")
8518     {
8519       if (++anArgIter >= theArgNb)
8520       {
8521         std::cout << "Syntax error at " << anArg << ".\n";
8522         return 1;
8523       }
8524
8525       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8526       aRootAnimation->UpdateTotalDuration();
8527     }
8528     else if (anArg == "-dur"
8529           || anArg == "-duration")
8530     {
8531       if (++anArgIter >= theArgNb)
8532       {
8533         std::cout << "Syntax error at " << anArg << ".\n";
8534         return 1;
8535       }
8536
8537       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8538       aRootAnimation->UpdateTotalDuration();
8539     }
8540     else if (anArg == "-command"
8541           || anArg == "-cmd"
8542           || anArg == "-invoke"
8543           || anArg == "-eval"
8544           || anArg == "-proc")
8545     {
8546       if (++anArgIter >= theArgNb)
8547       {
8548         std::cout << "Syntax error at " << anArg << ".\n";
8549         return 1;
8550       }
8551
8552       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8553       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8554     }
8555     else if (anArg == "-objecttrsf"
8556           || anArg == "-objectransformation"
8557           || anArg == "-objtransformation"
8558           || anArg == "-objtrsf"
8559           || anArg == "-object"
8560           || anArg == "-obj")
8561     {
8562       if (++anArgIter >= theArgNb)
8563       {
8564         std::cout << "Syntax error at " << anArg << ".\n";
8565         return 1;
8566       }
8567
8568       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8569       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8570       Handle(AIS_InteractiveObject) anObject;
8571       if (!aMapOfAIS.Find2 (anObjName, anObject))
8572       {
8573         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8574         return 1;
8575       }
8576
8577       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8578       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8579       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8580       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8581       Standard_Boolean isTrsfSet = Standard_False;
8582       Standard_Integer aTrsfArgIter = anArgIter + 1;
8583       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8584       {
8585         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8586         aTrsfArg.LowerCase();
8587         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8588         if (aTrsfArg.StartsWith ("-rotation")
8589          || aTrsfArg.StartsWith ("-rot"))
8590         {
8591           isTrsfSet = Standard_True;
8592           if (aTrsfArgIter + 4 >= theArgNb
8593           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8594           {
8595             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8596             return 1;
8597           }
8598           aTrsfArgIter += 4;
8599         }
8600         else if (aTrsfArg.StartsWith ("-location")
8601               || aTrsfArg.StartsWith ("-loc"))
8602         {
8603           isTrsfSet = Standard_True;
8604           if (aTrsfArgIter + 3 >= theArgNb
8605           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8606           {
8607             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8608             return 1;
8609           }
8610           aTrsfArgIter += 3;
8611         }
8612         else if (aTrsfArg.StartsWith ("-scale"))
8613         {
8614           isTrsfSet = Standard_True;
8615           if (++aTrsfArgIter >= theArgNb)
8616           {
8617             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8618             return 1;
8619           }
8620
8621           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8622           if (!aScaleStr.IsRealValue())
8623           {
8624             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8625             return 1;
8626           }
8627           aScales[anIndex] = aScaleStr.RealValue();
8628         }
8629         else
8630         {
8631           anArgIter = aTrsfArgIter - 1;
8632           break;
8633         }
8634       }
8635       if (!isTrsfSet)
8636       {
8637         std::cout << "Syntax error at " << anArg << ".\n";
8638         return 1;
8639       }
8640       else if (aTrsfArgIter >= theArgNb)
8641       {
8642         anArgIter = theArgNb;
8643       }
8644
8645       aTrsfs[0].SetRotation        (aRotQuats[0]);
8646       aTrsfs[1].SetRotation        (aRotQuats[1]);
8647       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8648       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8649       aTrsfs[0].SetScaleFactor     (aScales[0]);
8650       aTrsfs[1].SetScaleFactor     (aScales[1]);
8651
8652       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8653       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8654     }
8655     else if (anArg == "-viewtrsf"
8656           || anArg == "-view")
8657     {
8658       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8659       if (aCamAnimation.IsNull())
8660       {
8661         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8662         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8663       }
8664
8665       Handle(Graphic3d_Camera) aCams[2] =
8666       {
8667         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8668         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8669       };
8670
8671       Standard_Boolean isTrsfSet = Standard_False;
8672       Standard_Integer aViewArgIter = anArgIter + 1;
8673       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8674       {
8675         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8676         aViewArg.LowerCase();
8677         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8678         if (aViewArg.StartsWith ("-scale"))
8679         {
8680           isTrsfSet = Standard_True;
8681           if (++aViewArgIter >= theArgNb)
8682           {
8683             std::cout << "Syntax error at " << anArg << ".\n";
8684             return 1;
8685           }
8686
8687           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8688           if (!aScaleStr.IsRealValue())
8689           {
8690             std::cout << "Syntax error at " << aViewArg << ".\n";
8691             return 1;
8692           }
8693           Standard_Real aScale = aScaleStr.RealValue();
8694           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8695           aCams[anIndex]->SetScale (aScale);
8696         }
8697         else if (aViewArg.StartsWith ("-eye")
8698               || aViewArg.StartsWith ("-center")
8699               || aViewArg.StartsWith ("-at")
8700               || aViewArg.StartsWith ("-up"))
8701         {
8702           isTrsfSet = Standard_True;
8703           gp_XYZ anXYZ;
8704           if (aViewArgIter + 3 >= theArgNb
8705           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8706           {
8707             std::cout << "Syntax error at " << aViewArg << ".\n";
8708             return 1;
8709           }
8710           aViewArgIter += 3;
8711
8712           if (aViewArg.StartsWith ("-eye"))
8713           {
8714             aCams[anIndex]->SetEye (anXYZ);
8715           }
8716           else if (aViewArg.StartsWith ("-center")
8717                 || aViewArg.StartsWith ("-at"))
8718           {
8719             aCams[anIndex]->SetCenter (anXYZ);
8720           }
8721           else if (aViewArg.StartsWith ("-up"))
8722           {
8723             aCams[anIndex]->SetUp (anXYZ);
8724           }
8725         }
8726         else
8727         {
8728           anArgIter = aViewArgIter - 1;
8729           break;
8730         }
8731       }
8732       if (!isTrsfSet)
8733       {
8734         std::cout << "Syntax error at " << anArg << ".\n";
8735         return 1;
8736       }
8737       else if (aViewArgIter >= theArgNb)
8738       {
8739         anArgIter = theArgNb;
8740       }
8741
8742       aCamAnimation->SetCameraStart(aCams[0]);
8743       aCamAnimation->SetCameraEnd  (aCams[1]);
8744     }
8745     else
8746     {
8747       std::cout << "Syntax error at " << anArg << ".\n";
8748       return 1;
8749     }
8750   }
8751
8752   if (!toPlay && aRecFile.IsEmpty())
8753   {
8754     return 0;
8755   }
8756
8757   // Start animation timeline and process frame updating.
8758   TheIsAnimating = Standard_True;
8759   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8760   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8761   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8762   if (isFreeCamera)
8763   {
8764     aView->Camera()->Copy (aCameraBack);
8765   }
8766
8767   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8768   if (aRecParams.FpsNum <= 0)
8769   {
8770     while (!anAnimation->IsStopped())
8771     {
8772       aCameraBack->Copy (aView->Camera());
8773       const Standard_Real aPts = anAnimation->UpdateTimer();
8774       if (isFreeCamera)
8775       {
8776         aView->Camera()->Copy (aCameraBack);
8777       }
8778
8779       if (aPts >= anUpperPts)
8780       {
8781         anAnimation->Pause();
8782         break;
8783       }
8784
8785       if (aView->IsInvalidated())
8786       {
8787         aView->Redraw();
8788       }
8789       else
8790       {
8791         aView->RedrawImmediate();
8792       }
8793
8794       if (!isLockLoop)
8795       {
8796         // handle user events
8797         theDI.Eval ("after 1 set waiter 1");
8798         theDI.Eval ("vwait waiter");
8799       }
8800       if (!TheIsAnimating)
8801       {
8802         anAnimation->Pause();
8803         theDI << aPts;
8804         break;
8805       }
8806     }
8807
8808     if (aView->IsInvalidated())
8809     {
8810       aView->Redraw();
8811     }
8812     else
8813     {
8814       aView->RedrawImmediate();
8815     }
8816   }
8817   else
8818   {
8819     OSD_Timer aPerfTimer;
8820     aPerfTimer.Start();
8821
8822     Handle(Image_VideoRecorder) aRecorder;
8823     ImageFlipper aFlipper;
8824     Handle(Draw_ProgressIndicator) aProgress;
8825     if (!aRecFile.IsEmpty())
8826     {
8827       if (aRecParams.Width  <= 0
8828        || aRecParams.Height <= 0)
8829       {
8830         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8831       }
8832
8833       aRecorder = new Image_VideoRecorder();
8834       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8835       {
8836         std::cout << "Error: failed to open video file for recording\n";
8837         return 0;
8838       }
8839
8840       aProgress = new Draw_ProgressIndicator (theDI, 1);
8841     }
8842
8843     // Manage frame-rated animation here
8844     Standard_Real aPts = aPlayStartTime;
8845     int64_t aNbFrames = 0;
8846     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
8847     Standard_Integer aSecondsProgress = 0;
8848     for (; aPts <= anUpperPts && aPSentry.More();)
8849     {
8850       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8851       aPts = aPlayStartTime + aRecPts;
8852       ++aNbFrames;
8853       if (!anAnimation->Update (aPts))
8854       {
8855         break;
8856       }
8857
8858       if (!aRecorder.IsNull())
8859       {
8860         V3d_ImageDumpOptions aDumpParams;
8861         aDumpParams.Width          = aRecParams.Width;
8862         aDumpParams.Height         = aRecParams.Height;
8863         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8864         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8865         aDumpParams.ToAdjustAspect = Standard_True;
8866         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8867         {
8868           std::cout << "Error: view dump is failed!\n";
8869           return 0;
8870         }
8871         aFlipper.FlipY (aRecorder->ChangeFrame());
8872         if (!aRecorder->PushFrame())
8873         {
8874           return 0;
8875         }
8876       }
8877       else
8878       {
8879         aView->Redraw();
8880       }
8881
8882       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8883       {
8884         aPSentry.Next();
8885         ++aSecondsProgress;
8886       }
8887     }
8888
8889     aPerfTimer.Stop();
8890     anAnimation->Stop();
8891     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8892     theDI << "Average FPS: " << aRecFps << "\n"
8893           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8894
8895     aView->Redraw();
8896   }
8897
8898   aView->SetImmediateUpdate (wasImmediateUpdate);
8899   TheIsAnimating = Standard_False;
8900   return 0;
8901 }
8902
8903
8904 //=======================================================================
8905 //function : VChangeSelected
8906 //purpose  : Adds the shape to selection or remove one from it
8907 //=======================================================================
8908 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8909                                 Standard_Integer argc,
8910                                 const char ** argv)
8911 {
8912   if(argc != 2)
8913   {
8914     di<<"Usage : " << argv[0] << " shape \n";
8915     return 1;
8916   }
8917   //get AIS_Shape:
8918   TCollection_AsciiString aName(argv[1]);
8919   Handle(AIS_InteractiveObject) anAISObject;
8920   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8921     || anAISObject.IsNull())
8922   {
8923     di<<"Use 'vdisplay' before";
8924     return 1;
8925   }
8926
8927   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8928   return 0;
8929 }
8930
8931 //=======================================================================
8932 //function : VNbSelected
8933 //purpose  : Returns number of selected objects
8934 //=======================================================================
8935 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8936                                 Standard_Integer argc,
8937                                 const char ** argv)
8938 {
8939   if(argc != 1)
8940   {
8941     di << "Usage : " << argv[0] << "\n";
8942     return 1;
8943   }
8944   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8945   if(aContext.IsNull())
8946   {
8947     di << "use 'vinit' command before " << argv[0] << "\n";
8948     return 1;
8949   }
8950   di << aContext->NbSelected() << "\n";
8951   return 0;
8952 }
8953
8954 //=======================================================================
8955 //function : VPurgeDisplay
8956 //purpose  : Switches altialiasing on or off
8957 //=======================================================================
8958 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8959                                 Standard_Integer argc,
8960                                 const char ** argv)
8961 {
8962   if (argc > 1)
8963   {
8964     di << "Usage : " << argv[0] << "\n";
8965     return 1;
8966   }
8967   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8968   if (aContext.IsNull())
8969   {
8970     di << "use 'vinit' command before " << argv[0] << "\n";
8971     return 1;
8972   }
8973
8974   di << aContext->PurgeDisplay() << "\n";
8975   return 0;
8976 }
8977
8978 //=======================================================================
8979 //function : VSetViewSize
8980 //purpose  :
8981 //=======================================================================
8982 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8983                                 Standard_Integer argc,
8984                                 const char ** argv)
8985 {
8986   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8987   if(aContext.IsNull())
8988   {
8989     di << "use 'vinit' command before " << argv[0] << "\n";
8990     return 1;
8991   }
8992   if(argc != 2)
8993   {
8994     di<<"Usage : " << argv[0] << " Size\n";
8995     return 1;
8996   }
8997   Standard_Real aSize = Draw::Atof (argv[1]);
8998   if (aSize <= 0.)
8999   {
9000     di<<"Bad Size value  : " << aSize << "\n";
9001     return 1;
9002   }
9003
9004   Handle(V3d_View) aView = ViewerTest::CurrentView();
9005   aView->SetSize(aSize);
9006   return 0;
9007 }
9008
9009 //=======================================================================
9010 //function : VMoveView
9011 //purpose  :
9012 //=======================================================================
9013 static Standard_Integer VMoveView (Draw_Interpretor& di,
9014                                 Standard_Integer argc,
9015                                 const char ** argv)
9016 {
9017   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9018   if(aContext.IsNull())
9019   {
9020     di << "use 'vinit' command before " << argv[0] << "\n";
9021     return 1;
9022   }
9023   if(argc < 4 || argc > 5)
9024   {
9025     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9026     return 1;
9027   }
9028   Standard_Real Dx = Draw::Atof (argv[1]);
9029   Standard_Real Dy = Draw::Atof (argv[2]);
9030   Standard_Real Dz = Draw::Atof (argv[3]);
9031   Standard_Boolean aStart = Standard_True;
9032   if (argc == 5)
9033   {
9034       aStart = (Draw::Atoi (argv[4]) > 0);
9035   }
9036
9037   Handle(V3d_View) aView = ViewerTest::CurrentView();
9038   aView->Move(Dx,Dy,Dz,aStart);
9039   return 0;
9040 }
9041
9042 //=======================================================================
9043 //function : VTranslateView
9044 //purpose  :
9045 //=======================================================================
9046 static Standard_Integer VTranslateView (Draw_Interpretor& di,
9047                                 Standard_Integer argc,
9048                                 const char ** argv)
9049 {
9050   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9051   if(aContext.IsNull())
9052   {
9053     di << "use 'vinit' command before " << argv[0] << "\n";
9054     return 1;
9055   }
9056   if(argc < 4 || argc > 5)
9057   {
9058     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9059     return 1;
9060   }
9061   Standard_Real Dx = Draw::Atof (argv[1]);
9062   Standard_Real Dy = Draw::Atof (argv[2]);
9063   Standard_Real Dz = Draw::Atof (argv[3]);
9064   Standard_Boolean aStart = Standard_True;
9065   if (argc == 5)
9066   {
9067       aStart = (Draw::Atoi (argv[4]) > 0);
9068   }
9069
9070   Handle(V3d_View) aView = ViewerTest::CurrentView();
9071   aView->Translate(Dx,Dy,Dz,aStart);
9072   return 0;
9073 }
9074
9075 //=======================================================================
9076 //function : VTurnView
9077 //purpose  :
9078 //=======================================================================
9079 static Standard_Integer VTurnView (Draw_Interpretor& di,
9080                                 Standard_Integer argc,
9081                                 const char ** argv)
9082 {
9083   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9084   if(aContext.IsNull()) {
9085     di << "use 'vinit' command before " << argv[0] << "\n";
9086     return 1;
9087   }
9088   if(argc < 4 || argc > 5){
9089     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
9090     return 1;
9091   }
9092   Standard_Real Ax = Draw::Atof (argv[1]);
9093   Standard_Real Ay = Draw::Atof (argv[2]);
9094   Standard_Real Az = Draw::Atof (argv[3]);
9095   Standard_Boolean aStart = Standard_True;
9096   if (argc == 5)
9097   {
9098       aStart = (Draw::Atoi (argv[4]) > 0);
9099   }
9100
9101   Handle(V3d_View) aView = ViewerTest::CurrentView();
9102   aView->Turn(Ax,Ay,Az,aStart);
9103   return 0;
9104 }
9105
9106 //==============================================================================
9107 //function : VTextureEnv
9108 //purpose  : ENables or disables environment mapping
9109 //==============================================================================
9110 class OCC_TextureEnv : public Graphic3d_TextureEnv
9111 {
9112 public:
9113   OCC_TextureEnv(const Standard_CString FileName);
9114   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
9115   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
9116                             const Standard_Boolean theModulateFlag,
9117                             const Graphic3d_TypeOfTextureFilter theFilter,
9118                             const Standard_ShortReal theXScale,
9119                             const Standard_ShortReal theYScale,
9120                             const Standard_ShortReal theXShift,
9121                             const Standard_ShortReal theYShift,
9122                             const Standard_ShortReal theAngle);
9123   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
9124 };
9125 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
9126
9127 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
9128   : Graphic3d_TextureEnv(theFileName)
9129 {
9130 }
9131
9132 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
9133   : Graphic3d_TextureEnv(theTexId)
9134 {
9135 }
9136
9137 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
9138                                           const Standard_Boolean theModulateFlag,
9139                                           const Graphic3d_TypeOfTextureFilter theFilter,
9140                                           const Standard_ShortReal theXScale,
9141                                           const Standard_ShortReal theYScale,
9142                                           const Standard_ShortReal theXShift,
9143                                           const Standard_ShortReal theYShift,
9144                                           const Standard_ShortReal theAngle)
9145 {
9146   myParams->SetRepeat     (theRepeatFlag);
9147   myParams->SetModulate   (theModulateFlag);
9148   myParams->SetFilter     (theFilter);
9149   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
9150   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
9151   myParams->SetRotation   (theAngle);
9152 }
9153
9154 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
9155 {
9156   // get the active view
9157   Handle(V3d_View) aView = ViewerTest::CurrentView();
9158   if (aView.IsNull())
9159   {
9160     std::cerr << "No active view. Please call vinit.\n";
9161     return 1;
9162   }
9163
9164   // Checking the input arguments
9165   Standard_Boolean anEnableFlag = Standard_False;
9166   Standard_Boolean isOk         = theArgNb >= 2;
9167   if (isOk)
9168   {
9169     TCollection_AsciiString anEnableOpt(theArgVec[1]);
9170     anEnableFlag = anEnableOpt.IsEqual("on");
9171     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
9172   }
9173   if (anEnableFlag)
9174   {
9175     isOk = (theArgNb == 3 || theArgNb == 11);
9176     if (isOk)
9177     {
9178       TCollection_AsciiString aTextureOpt(theArgVec[2]);
9179       isOk = (!aTextureOpt.IsIntegerValue() ||
9180              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
9181
9182       if (isOk && theArgNb == 11)
9183       {
9184         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
9185                                 aModulateOpt(theArgVec[4]),
9186                                 aFilterOpt  (theArgVec[5]),
9187                                 aSScaleOpt  (theArgVec[6]),
9188                                 aTScaleOpt  (theArgVec[7]),
9189                                 aSTransOpt  (theArgVec[8]),
9190                                 aTTransOpt  (theArgVec[9]),
9191                                 anAngleOpt  (theArgVec[10]);
9192         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
9193                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
9194                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
9195                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
9196                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
9197                 anAngleOpt.IsRealValue());
9198       }
9199     }
9200   }
9201
9202   if (!isOk)
9203   {
9204     std::cerr << "Usage :" << std::endl;
9205     std::cerr << theArgVec[0] << " off" << std::endl;
9206     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;
9207     return 1;
9208   }
9209
9210   if (anEnableFlag)
9211   {
9212     TCollection_AsciiString aTextureOpt(theArgVec[2]);
9213     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
9214                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
9215                                      new OCC_TextureEnv(theArgVec[2]);
9216
9217     if (theArgNb == 11)
9218     {
9219       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
9220       aTexEnv->SetTextureParameters(
9221         aRepeatOpt.  IsEqual("repeat"),
9222         aModulateOpt.IsEqual("modulate"),
9223         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
9224                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
9225                                                                            Graphic3d_TOTF_TRILINEAR,
9226         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
9227         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
9228         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
9229         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
9230         (Standard_ShortReal)Draw::Atof(theArgVec[10])
9231         );
9232     }
9233     aView->SetTextureEnv(aTexEnv);
9234   }
9235   else // Disabling environment mapping
9236   {
9237     Handle(Graphic3d_TextureEnv) aTexture;
9238     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
9239   }
9240
9241   aView->Redraw();
9242   return 0;
9243 }
9244
9245 namespace
9246 {
9247   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
9248
9249   //! Remove registered clipping plane from all views and objects.
9250   static void removePlane (MapOfPlanes& theRegPlanes,
9251                            const TCollection_AsciiString& theName)
9252   {
9253     Handle(Graphic3d_ClipPlane) aClipPlane;
9254     if (!theRegPlanes.Find (theName, aClipPlane))
9255     {
9256       std::cout << "Warning: no such plane.\n";
9257       return;
9258     }
9259
9260     theRegPlanes.UnBind (theName);
9261     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
9262          anIObjIt.More(); anIObjIt.Next())
9263     {
9264       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
9265       aPrs->RemoveClipPlane (aClipPlane);
9266     }
9267
9268     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
9269          aViewIt.More(); aViewIt.Next())
9270     {
9271       const Handle(V3d_View)& aView = aViewIt.Key2();
9272       aView->RemoveClipPlane(aClipPlane);
9273     }
9274
9275     ViewerTest::RedrawAllViews();
9276   }
9277 }
9278
9279 //===============================================================================================
9280 //function : VClipPlane
9281 //purpose  :
9282 //===============================================================================================
9283 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9284 {
9285   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9286   static MapOfPlanes aRegPlanes;
9287
9288   if (theArgsNb < 2)
9289   {
9290     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9291     {
9292       theDi << aPlaneIter.Key() << " ";
9293     }
9294     return 0;
9295   }
9296
9297   TCollection_AsciiString aCommand (theArgVec[1]);
9298   aCommand.LowerCase();
9299   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9300   if (anActiveView.IsNull())
9301   {
9302     std::cout << "Error: no active view.\n";
9303     return 1;
9304   }
9305
9306   // print maximum number of planes for current viewer
9307   if (aCommand == "-maxplanes"
9308    || aCommand == "maxplanes")
9309   {
9310     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9311           << " plane slots provided by driver.\n";
9312     return 0;
9313   }
9314
9315   // create / delete plane instance
9316   if (aCommand == "-create"
9317    || aCommand == "create"
9318    || aCommand == "-delete"
9319    || aCommand == "delete"
9320    || aCommand == "-clone"
9321    || aCommand == "clone")
9322   {
9323     if (theArgsNb < 3)
9324     {
9325       std::cout << "Syntax error: plane name is required.\n";
9326       return 1;
9327     }
9328
9329     Standard_Boolean toCreate = aCommand == "-create"
9330                              || aCommand == "create";
9331     Standard_Boolean toClone  = aCommand == "-clone"
9332                              || aCommand == "clone";
9333     Standard_Boolean toDelete = aCommand == "-delete"
9334                              || aCommand == "delete";
9335     TCollection_AsciiString aPlane (theArgVec[2]);
9336
9337     if (toCreate)
9338     {
9339       if (aRegPlanes.IsBound (aPlane))
9340       {
9341         std::cout << "Warning: existing plane has been overridden.\n";
9342         toDelete = true;
9343       }
9344       else
9345       {
9346         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9347         return 0;
9348       }
9349     }
9350     else if (toClone) // toClone
9351     {
9352       if (!aRegPlanes.IsBound (aPlane))
9353       {
9354         std::cout << "Error: no such plane.\n";
9355         return 1;
9356       }
9357       else if (theArgsNb < 4)
9358       {
9359         std::cout << "Syntax error: enter name for new plane.\n";
9360         return 1;
9361       }
9362
9363       TCollection_AsciiString aClone (theArgVec[3]);
9364       if (aRegPlanes.IsBound (aClone))
9365       {
9366         std::cout << "Error: plane name is in use.\n";
9367         return 1;
9368       }
9369
9370       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9371
9372       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9373       return 0;
9374     }
9375
9376     if (toDelete)
9377     {
9378       if (aPlane == "ALL"
9379        || aPlane == "all"
9380        || aPlane == "*")
9381       {
9382         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9383         {
9384           aPlane = aPlaneIter.Key();
9385           removePlane (aRegPlanes, aPlane);
9386           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9387         }
9388       }
9389       else
9390       {
9391         removePlane (aRegPlanes, aPlane);
9392       }
9393     }
9394
9395     if (toCreate)
9396     {
9397       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9398     }
9399     return 0;
9400   }
9401
9402   // set / unset plane command
9403   if (aCommand == "set"
9404    || aCommand == "unset")
9405   {
9406     if (theArgsNb < 5)
9407     {
9408       std::cout << "Syntax error: need more arguments.\n";
9409       return 1;
9410     }
9411
9412     // redirect to new syntax
9413     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9414     anArgVec.SetValue (1, theArgVec[0]);
9415     anArgVec.SetValue (2, theArgVec[2]);
9416     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9417     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9418     {
9419       anArgVec.SetValue (anIt, theArgVec[anIt]);
9420     }
9421
9422     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9423   }
9424
9425   // change plane command
9426   TCollection_AsciiString aPlaneName;
9427   Handle(Graphic3d_ClipPlane) aClipPlane;
9428   Standard_Integer anArgIter = 0;
9429   if (aCommand == "-change"
9430    || aCommand == "change")
9431   {
9432     // old syntax support
9433     if (theArgsNb < 3)
9434     {
9435       std::cout << "Syntax error: need more arguments.\n";
9436       return 1;
9437     }
9438
9439     anArgIter  = 3;
9440     aPlaneName = theArgVec[2];
9441     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9442     {
9443       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9444       return 1;
9445     }
9446   }
9447   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9448   {
9449     anArgIter  = 2;
9450     aPlaneName = theArgVec[1];
9451   }
9452   else
9453   {
9454     anArgIter  = 2;
9455     aPlaneName = theArgVec[1];
9456     aClipPlane = new Graphic3d_ClipPlane();
9457     aRegPlanes.Bind (aPlaneName, aClipPlane);
9458     theDi << "Created new plane " << aPlaneName << ".\n";
9459   }
9460
9461   if (theArgsNb - anArgIter < 1)
9462   {
9463     std::cout << "Syntax error: need more arguments.\n";
9464     return 1;
9465   }
9466
9467   for (; anArgIter < theArgsNb; ++anArgIter)
9468   {
9469     const char**     aChangeArgs   = theArgVec + anArgIter;
9470     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9471     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9472     aChangeArg.LowerCase();
9473
9474     Standard_Boolean toEnable = Standard_True;
9475     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9476     {
9477       aClipPlane->SetOn (toEnable);
9478     }
9479     else if (aChangeArg.StartsWith ("-equation")
9480           || aChangeArg.StartsWith ("equation"))
9481     {
9482       if (aNbChangeArgs < 5)
9483       {
9484         std::cout << "Syntax error: need more arguments.\n";
9485         return 1;
9486       }
9487
9488       Standard_Integer aSubIndex = 1;
9489       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9490       if (aPrefixLen < aChangeArg.Length())
9491       {
9492         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9493         if (!aSubStr.IsIntegerValue()
9494           || aSubStr.IntegerValue() <= 0)
9495         {
9496           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9497           return 1;
9498         }
9499         aSubIndex = aSubStr.IntegerValue();
9500       }
9501
9502       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9503       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9504       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9505       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9506       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9507       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9508       {
9509         if (aSubPln->ChainNextPlane().IsNull())
9510         {
9511           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9512         }
9513         aSubPln = aSubPln->ChainNextPlane();
9514       }
9515       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9516       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9517       anArgIter += 4;
9518     }
9519     else if ((aChangeArg == "-boxinterior"
9520            || aChangeArg == "-boxint"
9521            || aChangeArg == "-box")
9522             && aNbChangeArgs >= 7)
9523     {
9524       Graphic3d_BndBox3d aBndBox;
9525       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9526       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9527       anArgIter += 6;
9528
9529       Standard_Integer aNbSubPlanes = 6;
9530       const Graphic3d_Vec3d aDirArray[6] =
9531       {
9532         Graphic3d_Vec3d (-1, 0, 0),
9533         Graphic3d_Vec3d ( 1, 0, 0),
9534         Graphic3d_Vec3d ( 0,-1, 0),
9535         Graphic3d_Vec3d ( 0, 1, 0),
9536         Graphic3d_Vec3d ( 0, 0,-1),
9537         Graphic3d_Vec3d ( 0, 0, 1),
9538       };
9539       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9540       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9541       {
9542         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9543         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9544         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9545         if (aSubPlaneIter + 1 == aNbSubPlanes)
9546         {
9547           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9548         }
9549         else
9550         {
9551           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9552         }
9553         aSubPln = aSubPln->ChainNextPlane();
9554       }
9555     }
9556     else if (aChangeArg == "-capping"
9557           || aChangeArg == "capping")
9558     {
9559       if (aNbChangeArgs < 2)
9560       {
9561         std::cout << "Syntax error: need more arguments.\n";
9562         return 1;
9563       }
9564
9565       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9566       {
9567         aClipPlane->SetCapping (toEnable);
9568         anArgIter += 1;
9569       }
9570       else
9571       {
9572         // just skip otherwise (old syntax)
9573       }
9574     }
9575     else if (aChangeArg == "-useobjectmaterial"
9576           || aChangeArg == "-useobjectmat"
9577           || aChangeArg == "-useobjmat"
9578           || aChangeArg == "-useobjmaterial")
9579     {
9580       if (aNbChangeArgs < 2)
9581       {
9582         std::cout << "Syntax error: need more arguments.\n";
9583         return 1;
9584       }
9585
9586       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9587       {
9588         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9589         anArgIter += 1;
9590       }
9591     }
9592     else if (aChangeArg == "-useobjecttexture"
9593           || aChangeArg == "-useobjecttex"
9594           || aChangeArg == "-useobjtexture"
9595           || aChangeArg == "-useobjtex")
9596     {
9597       if (aNbChangeArgs < 2)
9598       {
9599         std::cout << "Syntax error: need more arguments.\n";
9600         return 1;
9601       }
9602
9603       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9604       {
9605         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9606         anArgIter += 1;
9607       }
9608     }
9609     else if (aChangeArg == "-useobjectshader"
9610           || aChangeArg == "-useobjshader")
9611     {
9612       if (aNbChangeArgs < 2)
9613       {
9614         std::cout << "Syntax error: need more arguments.\n";
9615         return 1;
9616       }
9617
9618       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9619       {
9620         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9621         anArgIter += 1;
9622       }
9623     }
9624     else if (aChangeArg == "-color"
9625           || aChangeArg == "color")
9626     {
9627       Quantity_Color aColor;
9628       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9629                                                            aChangeArgs + 1,
9630                                                            aColor);
9631       if (aNbParsed == 0)
9632       {
9633         std::cout << "Syntax error: need more arguments.\n";
9634         return 1;
9635       }
9636       aClipPlane->SetCappingColor (aColor);
9637       anArgIter += aNbParsed;
9638     }
9639     else if (aNbChangeArgs >= 1
9640           && (aChangeArg == "-material"
9641            || aChangeArg == "material"))
9642     {
9643       ++anArgIter;
9644       Graphic3d_NameOfMaterial aMatName;
9645       if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeArgs[1], aMatName))
9646       {
9647         std::cout << "Syntax error: unknown material '" << aChangeArgs[1] << "'.\n";
9648         return 1;
9649       }
9650       aClipPlane->SetCappingMaterial (aMatName);
9651     }
9652     else if ((aChangeArg == "-transparency"
9653            || aChangeArg == "-transp")
9654           && aNbChangeArgs >= 2)
9655     {
9656       TCollection_AsciiString aValStr (aChangeArgs[1]);
9657       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9658       if (aValStr.IsRealValue())
9659       {
9660         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9661         aMat.SetTransparency ((float )aValStr.RealValue());
9662         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9663         aClipPlane->SetCappingMaterial (aMat);
9664       }
9665       else
9666       {
9667         aValStr.LowerCase();
9668         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9669         if (aValStr == "opaque")
9670         {
9671           aMode = Graphic3d_AlphaMode_Opaque;
9672         }
9673         else if (aValStr == "mask")
9674         {
9675           aMode = Graphic3d_AlphaMode_Mask;
9676         }
9677         else if (aValStr == "blend")
9678         {
9679           aMode = Graphic3d_AlphaMode_Blend;
9680         }
9681         else if (aValStr == "blendauto")
9682         {
9683           aMode = Graphic3d_AlphaMode_BlendAuto;
9684         }
9685         else
9686         {
9687           std::cout << "Syntax error at '" << aValStr << "'\n";
9688           return 1;
9689         }
9690         anAspect->SetAlphaMode (aMode);
9691         aClipPlane->SetCappingAspect (anAspect);
9692       }
9693       anArgIter += 1;
9694     }
9695     else if (aChangeArg == "-texname"
9696           || aChangeArg == "texname")
9697     {
9698       if (aNbChangeArgs < 2)
9699       {
9700         std::cout << "Syntax error: need more arguments.\n";
9701         return 1;
9702       }
9703
9704       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9705       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9706       if (!aTexture->IsDone())
9707       {
9708         aClipPlane->SetCappingTexture (NULL);
9709       }
9710       else
9711       {
9712         aTexture->EnableModulate();
9713         aTexture->EnableRepeat();
9714         aClipPlane->SetCappingTexture (aTexture);
9715       }
9716       anArgIter += 1;
9717     }
9718     else if (aChangeArg == "-texscale"
9719           || aChangeArg == "texscale")
9720     {
9721       if (aClipPlane->CappingTexture().IsNull())
9722       {
9723         std::cout << "Error: no texture is set.\n";
9724         return 1;
9725       }
9726
9727       if (aNbChangeArgs < 3)
9728       {
9729         std::cout << "Syntax error: need more arguments.\n";
9730         return 1;
9731       }
9732
9733       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9734       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9735       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9736       anArgIter += 2;
9737     }
9738     else if (aChangeArg == "-texorigin"
9739           || aChangeArg == "texorigin") // texture origin
9740     {
9741       if (aClipPlane->CappingTexture().IsNull())
9742       {
9743         std::cout << "Error: no texture is set.\n";
9744         return 1;
9745       }
9746
9747       if (aNbChangeArgs < 3)
9748       {
9749         std::cout << "Syntax error: need more arguments.\n";
9750         return 1;
9751       }
9752
9753       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9754       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9755
9756       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9757       anArgIter += 2;
9758     }
9759     else if (aChangeArg == "-texrotate"
9760           || aChangeArg == "texrotate") // texture rotation
9761     {
9762       if (aClipPlane->CappingTexture().IsNull())
9763       {
9764         std::cout << "Error: no texture is set.\n";
9765         return 1;
9766       }
9767
9768       if (aNbChangeArgs < 2)
9769       {
9770         std::cout << "Syntax error: need more arguments.\n";
9771         return 1;
9772       }
9773
9774       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9775       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9776       anArgIter += 1;
9777     }
9778     else if (aChangeArg == "-hatch"
9779           || aChangeArg == "hatch")
9780     {
9781       if (aNbChangeArgs < 2)
9782       {
9783         std::cout << "Syntax error: need more arguments.\n";
9784         return 1;
9785       }
9786
9787       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9788       aHatchStr.LowerCase();
9789       if (aHatchStr == "on")
9790       {
9791         aClipPlane->SetCappingHatchOn();
9792       }
9793       else if (aHatchStr == "off")
9794       {
9795         aClipPlane->SetCappingHatchOff();
9796       }
9797       else
9798       {
9799         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9800       }
9801       anArgIter += 1;
9802     }
9803     else if (aChangeArg == "-delete"
9804           || aChangeArg == "delete")
9805     {
9806       removePlane (aRegPlanes, aPlaneName);
9807       return 0;
9808     }
9809     else if (aChangeArg == "-set"
9810           || aChangeArg == "-unset"
9811           || aChangeArg == "-setoverrideglobal")
9812     {
9813       // set / unset plane command
9814       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9815       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9816       Standard_Integer anIt = 1;
9817       for (; anIt < aNbChangeArgs; ++anIt)
9818       {
9819         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9820         if (anEntityName.IsEmpty()
9821          || anEntityName.Value (1) == '-')
9822         {
9823           break;
9824         }
9825         else if (!toOverrideGlobal
9826                && ViewerTest_myViews.IsBound1 (anEntityName))
9827         {
9828           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9829           if (toSet)
9830           {
9831             aView->AddClipPlane (aClipPlane);
9832           }
9833           else
9834           {
9835             aView->RemoveClipPlane (aClipPlane);
9836           }
9837           continue;
9838         }
9839         else if (GetMapOfAIS().IsBound2 (anEntityName))
9840         {
9841           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9842           if (toSet)
9843           {
9844             aIObj->AddClipPlane (aClipPlane);
9845           }
9846           else
9847           {
9848             aIObj->RemoveClipPlane (aClipPlane);
9849           }
9850           if (!aIObj->ClipPlanes().IsNull())
9851           {
9852             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9853           }
9854         }
9855         else
9856         {
9857           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9858           return 1;
9859         }
9860       }
9861
9862       if (anIt == 1)
9863       {
9864         // apply to active view
9865         if (toSet)
9866         {
9867           anActiveView->AddClipPlane (aClipPlane);
9868         }
9869         else
9870         {
9871           anActiveView->RemoveClipPlane (aClipPlane);
9872         }
9873       }
9874       else
9875       {
9876         anArgIter = anArgIter + anIt - 1;
9877       }
9878     }
9879     else
9880     {
9881       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9882       return 1;
9883     }
9884   }
9885
9886   ViewerTest::RedrawAllViews();
9887   return 0;
9888 }
9889
9890 //===============================================================================================
9891 //function : VZRange
9892 //purpose  :
9893 //===============================================================================================
9894 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9895 {
9896   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9897
9898   if (aCurrentView.IsNull())
9899   {
9900     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9901     return 1;
9902   }
9903
9904   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9905
9906   if (theArgsNb < 2)
9907   {
9908     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9909     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9910     return 0;
9911   }
9912
9913   if (theArgsNb == 3)
9914   {
9915     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9916     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9917
9918     if (aNewZNear >= aNewZFar)
9919     {
9920       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9921       return 1;
9922     }
9923
9924     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9925     {
9926       std::cout << theArgVec[0] << ": invalid arguments: ";
9927       std::cout << "znear, zfar should be positive for perspective camera.\n";
9928       return 1;
9929     }
9930
9931     aCamera->SetZRange (aNewZNear, aNewZFar);
9932   }
9933   else
9934   {
9935     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9936     return 1;
9937   }
9938
9939   aCurrentView->Redraw();
9940
9941   return 0;
9942 }
9943
9944 //===============================================================================================
9945 //function : VAutoZFit
9946 //purpose  :
9947 //===============================================================================================
9948 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9949 {
9950   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9951
9952   if (aCurrentView.IsNull())
9953   {
9954     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9955     return 1;
9956   }
9957
9958   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9959
9960   if (theArgsNb > 3)
9961   {
9962     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9963     return 1;
9964   }
9965
9966   if (theArgsNb < 2)
9967   {
9968     theDi << "Auto z-fit mode: \n"
9969           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9970           << "Scale: " << aScale << "\n";
9971     return 0;
9972   }
9973
9974   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9975
9976   if (theArgsNb >= 3)
9977   {
9978     aScale = Draw::Atoi (theArgVec[2]);
9979   }
9980
9981   aCurrentView->SetAutoZFitMode (isOn, aScale);
9982   aCurrentView->AutoZFit();
9983   aCurrentView->Redraw();
9984
9985   return 0;
9986 }
9987
9988 //! Auxiliary function to print projection type
9989 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9990 {
9991   switch (theProjType)
9992   {
9993     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9994     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9995     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9996     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9997     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9998   }
9999   return "UNKNOWN";
10000 }
10001
10002 //===============================================================================================
10003 //function : VCamera
10004 //purpose  :
10005 //===============================================================================================
10006 static int VCamera (Draw_Interpretor& theDI,
10007                     Standard_Integer  theArgsNb,
10008                     const char**      theArgVec)
10009 {
10010   Handle(V3d_View) aView = ViewerTest::CurrentView();
10011   if (aView.IsNull())
10012   {
10013     std::cout << "Error: no active view.\n";
10014     return 1;
10015   }
10016
10017   Handle(Graphic3d_Camera) aCamera = aView->Camera();
10018   if (theArgsNb < 2)
10019   {
10020     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
10021     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
10022     theDI << "Distance:   " << aCamera->Distance() << "\n";
10023     theDI << "IOD:        " << aCamera->IOD() << "\n";
10024     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
10025     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
10026     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
10027     return 0;
10028   }
10029
10030   TCollection_AsciiString aPrsName;
10031   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10032   {
10033     Standard_CString        anArg = theArgVec[anArgIter];
10034     TCollection_AsciiString anArgCase (anArg);
10035     anArgCase.LowerCase();
10036     if (anArgCase == "-proj"
10037      || anArgCase == "-projection"
10038      || anArgCase == "-projtype"
10039      || anArgCase == "-projectiontype")
10040     {
10041       theDI << projTypeName (aCamera->ProjectionType()) << " ";
10042     }
10043     else if (anArgCase == "-ortho"
10044           || anArgCase == "-orthographic")
10045     {
10046       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
10047     }
10048     else if (anArgCase == "-persp"
10049           || anArgCase == "-perspective"
10050           || anArgCase == "-perspmono"
10051           || anArgCase == "-perspectivemono"
10052           || anArgCase == "-mono")
10053     {
10054       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10055     }
10056     else if (anArgCase == "-stereo"
10057           || anArgCase == "-stereoscopic"
10058           || anArgCase == "-perspstereo"
10059           || anArgCase == "-perspectivestereo")
10060     {
10061       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10062     }
10063     else if (anArgCase == "-left"
10064           || anArgCase == "-lefteye"
10065           || anArgCase == "-monoleft"
10066           || anArgCase == "-monolefteye"
10067           || anArgCase == "-perpsleft"
10068           || anArgCase == "-perpslefteye")
10069     {
10070       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
10071     }
10072     else if (anArgCase == "-right"
10073           || anArgCase == "-righteye"
10074           || anArgCase == "-monoright"
10075           || anArgCase == "-monorighteye"
10076           || anArgCase == "-perpsright")
10077     {
10078       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
10079     }
10080     else if (anArgCase == "-dist"
10081           || anArgCase == "-distance")
10082     {
10083       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10084       if (anArgValue != NULL
10085       && *anArgValue != '-')
10086       {
10087         ++anArgIter;
10088         aCamera->SetDistance (Draw::Atof (anArgValue));
10089         continue;
10090       }
10091       theDI << aCamera->Distance() << " ";
10092     }
10093     else if (anArgCase == "-iod")
10094     {
10095       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10096       if (anArgValue != NULL
10097       && *anArgValue != '-')
10098       {
10099         ++anArgIter;
10100         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
10101         continue;
10102       }
10103       theDI << aCamera->IOD() << " ";
10104     }
10105     else if (anArgCase == "-iodtype")
10106     {
10107       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10108       TCollection_AsciiString anValueCase (anArgValue);
10109       anValueCase.LowerCase();
10110       if (anValueCase == "abs"
10111        || anValueCase == "absolute")
10112       {
10113         ++anArgIter;
10114         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
10115         continue;
10116       }
10117       else if (anValueCase == "rel"
10118             || anValueCase == "relative")
10119       {
10120         ++anArgIter;
10121         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
10122         continue;
10123       }
10124       else if (*anArgValue != '-')
10125       {
10126         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
10127         return 1;
10128       }
10129       switch (aCamera->GetIODType())
10130       {
10131         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
10132         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
10133       }
10134     }
10135     else if (anArgCase == "-zfocus")
10136     {
10137       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10138       if (anArgValue != NULL
10139       && *anArgValue != '-')
10140       {
10141         ++anArgIter;
10142         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
10143         continue;
10144       }
10145       theDI << aCamera->ZFocus() << " ";
10146     }
10147     else if (anArgCase == "-zfocustype")
10148     {
10149       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10150       TCollection_AsciiString anValueCase (anArgValue);
10151       anValueCase.LowerCase();
10152       if (anValueCase == "abs"
10153        || anValueCase == "absolute")
10154       {
10155         ++anArgIter;
10156         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
10157         continue;
10158       }
10159       else if (anValueCase == "rel"
10160             || anValueCase == "relative")
10161       {
10162         ++anArgIter;
10163         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
10164         continue;
10165       }
10166       else if (*anArgValue != '-')
10167       {
10168         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
10169         return 1;
10170       }
10171       switch (aCamera->ZFocusType())
10172       {
10173         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
10174         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
10175       }
10176     }
10177     else if (anArgCase == "-fov"
10178           || anArgCase == "-fovy")
10179     {
10180       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10181       if (anArgValue != NULL
10182       && *anArgValue != '-')
10183       {
10184         ++anArgIter;
10185         aCamera->SetFOVy (Draw::Atof (anArgValue));
10186         continue;
10187       }
10188       theDI << aCamera->FOVy() << " ";
10189     }
10190     else if (aPrsName.IsEmpty()
10191          && !anArgCase.StartsWith ("-"))
10192     {
10193       aPrsName = anArg;
10194     }
10195     else
10196     {
10197       std::cout << "Error: unknown argument '" << anArg << "'\n";
10198       return 1;
10199     }
10200   }
10201
10202   if (aPrsName.IsEmpty()
10203    || theArgsNb > 2)
10204   {
10205     aView->AutoZFit();
10206     aView->Redraw();
10207   }
10208
10209   if (!aPrsName.IsEmpty())
10210   {
10211     Handle(AIS_CameraFrustum) aCameraFrustum;
10212     if (GetMapOfAIS().IsBound2 (aPrsName))
10213     {
10214       // find existing object
10215       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
10216       if (aCameraFrustum.IsNull())
10217       {
10218         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
10219         return 1;
10220       }
10221     }
10222
10223     if (aCameraFrustum.IsNull())
10224     {
10225       aCameraFrustum = new AIS_CameraFrustum();
10226     }
10227     else
10228     {
10229       // not include displayed object of old camera frustum in the new one.
10230       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
10231       aView->ZFitAll();
10232     }
10233     aCameraFrustum->SetCameraFrustum (aView->Camera());
10234
10235     ViewerTest::Display (aPrsName, aCameraFrustum);
10236   }
10237
10238   return 0;
10239 }
10240
10241 //! Parse stereo output mode
10242 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
10243                                          Graphic3d_StereoMode& theMode)
10244 {
10245   TCollection_AsciiString aFlag (theArg);
10246   aFlag.LowerCase();
10247   if (aFlag == "quadbuffer")
10248   {
10249     theMode = Graphic3d_StereoMode_QuadBuffer;
10250   }
10251   else if (aFlag == "anaglyph")
10252   {
10253     theMode = Graphic3d_StereoMode_Anaglyph;
10254   }
10255   else if (aFlag == "row"
10256         || aFlag == "rowinterlaced")
10257   {
10258     theMode = Graphic3d_StereoMode_RowInterlaced;
10259   }
10260   else if (aFlag == "col"
10261         || aFlag == "colinterlaced"
10262         || aFlag == "columninterlaced")
10263   {
10264     theMode = Graphic3d_StereoMode_ColumnInterlaced;
10265   }
10266   else if (aFlag == "chess"
10267         || aFlag == "chessboard")
10268   {
10269     theMode = Graphic3d_StereoMode_ChessBoard;
10270   }
10271   else if (aFlag == "sbs"
10272         || aFlag == "sidebyside")
10273   {
10274     theMode = Graphic3d_StereoMode_SideBySide;
10275   }
10276   else if (aFlag == "ou"
10277         || aFlag == "overunder")
10278   {
10279     theMode = Graphic3d_StereoMode_OverUnder;
10280   }
10281   else if (aFlag == "pageflip"
10282         || aFlag == "softpageflip")
10283   {
10284     theMode = Graphic3d_StereoMode_SoftPageFlip;
10285   }
10286   else
10287   {
10288     return Standard_False;
10289   }
10290   return Standard_True;
10291 }
10292
10293 //! Parse anaglyph filter
10294 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10295                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10296 {
10297   TCollection_AsciiString aFlag (theArg);
10298   aFlag.LowerCase();
10299   if (aFlag == "redcyansimple")
10300   {
10301     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10302   }
10303   else if (aFlag == "redcyan"
10304         || aFlag == "redcyanoptimized")
10305   {
10306     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10307   }
10308   else if (aFlag == "yellowbluesimple")
10309   {
10310     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10311   }
10312   else if (aFlag == "yellowblue"
10313         || aFlag == "yellowblueoptimized")
10314   {
10315     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10316   }
10317   else if (aFlag == "greenmagenta"
10318         || aFlag == "greenmagentasimple")
10319   {
10320     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10321   }
10322   else
10323   {
10324     return Standard_False;
10325   }
10326   return Standard_True;
10327 }
10328
10329 //==============================================================================
10330 //function : VStereo
10331 //purpose  :
10332 //==============================================================================
10333
10334 static int VStereo (Draw_Interpretor& theDI,
10335                     Standard_Integer  theArgNb,
10336                     const char**      theArgVec)
10337 {
10338   Handle(V3d_View) aView = ViewerTest::CurrentView();
10339   if (theArgNb < 2)
10340   {
10341     if (aView.IsNull())
10342     {
10343       std::cout << "Error: no active viewer!\n";
10344       return 0;
10345     }
10346
10347     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10348     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10349     if (isActive)
10350     {
10351       TCollection_AsciiString aMode;
10352       switch (aView->RenderingParams().StereoMode)
10353       {
10354         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10355         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10356         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10357         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10358         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10359         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10360         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10361         case Graphic3d_StereoMode_Anaglyph  :
10362           aMode = "anaglyph";
10363           switch (aView->RenderingParams().AnaglyphFilter)
10364           {
10365             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10366             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10367             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10368             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10369             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10370             default: break;
10371           }
10372         default: break;
10373       }
10374       theDI << "Mode " << aMode << "\n";
10375     }
10376     return 0;
10377   }
10378
10379   Handle(Graphic3d_Camera) aCamera;
10380   Graphic3d_RenderingParams*   aParams   = NULL;
10381   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10382   if (!aView.IsNull())
10383   {
10384     aParams   = &aView->ChangeRenderingParams();
10385     aMode     = aParams->StereoMode;
10386     aCamera   = aView->Camera();
10387   }
10388
10389   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10390   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10391   {
10392     Standard_CString        anArg = theArgVec[anArgIter];
10393     TCollection_AsciiString aFlag (anArg);
10394     aFlag.LowerCase();
10395     if (anUpdateTool.parseRedrawMode (aFlag))
10396     {
10397       continue;
10398     }
10399     else if (aFlag == "0"
10400           || aFlag == "off")
10401     {
10402       if (++anArgIter < theArgNb)
10403       {
10404         std::cout << "Error: wrong number of arguments!\n";
10405         return 1;
10406       }
10407
10408       if (!aCamera.IsNull()
10409        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10410       {
10411         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10412       }
10413       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10414       return 0;
10415     }
10416     else if (aFlag == "1"
10417           || aFlag == "on")
10418     {
10419       if (++anArgIter < theArgNb)
10420       {
10421         std::cout << "Error: wrong number of arguments!\n";
10422         return 1;
10423       }
10424
10425       if (!aCamera.IsNull())
10426       {
10427         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10428       }
10429       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10430       return 0;
10431     }
10432     else if (aFlag == "-reverse"
10433           || aFlag == "-reversed"
10434           || aFlag == "-swap")
10435     {
10436       Standard_Boolean toEnable = Standard_True;
10437       if (++anArgIter < theArgNb
10438       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10439       {
10440         --anArgIter;
10441       }
10442       aParams->ToReverseStereo = toEnable;
10443     }
10444     else if (aFlag == "-noreverse"
10445           || aFlag == "-noswap")
10446     {
10447       Standard_Boolean toDisable = Standard_True;
10448       if (++anArgIter < theArgNb
10449       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10450       {
10451         --anArgIter;
10452       }
10453       aParams->ToReverseStereo = !toDisable;
10454     }
10455     else if (aFlag == "-mode"
10456           || aFlag == "-stereomode")
10457     {
10458       if (++anArgIter >= theArgNb
10459       || !parseStereoMode (theArgVec[anArgIter], aMode))
10460       {
10461         std::cout << "Error: syntax error at '" << anArg << "'\n";
10462         return 1;
10463       }
10464
10465       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10466       {
10467         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10468       }
10469     }
10470     else if (aFlag == "-anaglyph"
10471           || aFlag == "-anaglyphfilter")
10472     {
10473       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10474       if (++anArgIter >= theArgNb
10475       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10476       {
10477         std::cout << "Error: syntax error at '" << anArg << "'\n";
10478         return 1;
10479       }
10480
10481       aMode = Graphic3d_StereoMode_Anaglyph;
10482       aParams->AnaglyphFilter = aFilter;
10483     }
10484     else if (parseStereoMode (anArg, aMode)) // short syntax
10485     {
10486       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10487       {
10488         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10489       }
10490     }
10491     else
10492     {
10493       std::cout << "Error: syntax error at '" << anArg << "'\n";
10494       return 1;
10495     }
10496   }
10497
10498   if (!aView.IsNull())
10499   {
10500     aParams->StereoMode = aMode;
10501     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10502   }
10503   return 0;
10504 }
10505
10506 //===============================================================================================
10507 //function : VDefaults
10508 //purpose  :
10509 //===============================================================================================
10510 static int VDefaults (Draw_Interpretor& theDi,
10511                       Standard_Integer  theArgsNb,
10512                       const char**      theArgVec)
10513 {
10514   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10515   if (aCtx.IsNull())
10516   {
10517     std::cout << "Error: no active viewer\n";
10518     return 1;
10519   }
10520
10521   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10522   if (theArgsNb < 2)
10523   {
10524     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10525     {
10526       theDi << "DeflType:           relative\n"
10527             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10528     }
10529     else
10530     {
10531       theDi << "DeflType:           absolute\n"
10532             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10533     }
10534     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10535     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10536     return 0;
10537   }
10538
10539   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10540   {
10541     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10542     anArg.UpperCase();
10543     if (anArg == "-ABSDEFL"
10544      || anArg == "-ABSOLUTEDEFLECTION"
10545      || anArg == "-DEFL"
10546      || anArg == "-DEFLECTION")
10547     {
10548       if (++anArgIter >= theArgsNb)
10549       {
10550         std::cout << "Error: wrong syntax at " << anArg << "\n";
10551         return 1;
10552       }
10553       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10554       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10555     }
10556     else if (anArg == "-RELDEFL"
10557           || anArg == "-RELATIVEDEFLECTION"
10558           || anArg == "-DEVCOEFF"
10559           || anArg == "-DEVIATIONCOEFF"
10560           || anArg == "-DEVIATIONCOEFFICIENT")
10561     {
10562       if (++anArgIter >= theArgsNb)
10563       {
10564         std::cout << "Error: wrong syntax at " << anArg << "\n";
10565         return 1;
10566       }
10567       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10568       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10569     }
10570     else if (anArg == "-ANGDEFL"
10571           || anArg == "-ANGULARDEFL"
10572           || anArg == "-ANGULARDEFLECTION")
10573     {
10574       if (++anArgIter >= theArgsNb)
10575       {
10576         std::cout << "Error: wrong syntax at " << anArg << "\n";
10577         return 1;
10578       }
10579       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10580       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10581     }
10582     else if (anArg == "-AUTOTR"
10583           || anArg == "-AUTOTRIANG"
10584           || anArg == "-AUTOTRIANGULATION")
10585     {
10586       ++anArgIter;
10587       bool toTurnOn = true;
10588       if (anArgIter >= theArgsNb
10589       || !ViewerTest::ParseOnOff (theArgVec[anArgIter], toTurnOn))
10590       {
10591         std::cout << "Syntax error at '" << anArg << "'\n";
10592         return 1;
10593       }
10594       aDefParams->SetAutoTriangulation (toTurnOn);
10595     }
10596     else
10597     {
10598       std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
10599       return 1;
10600     }
10601   }
10602
10603   return 0;
10604 }
10605
10606 //! Auxiliary method
10607 inline void addLight (const Handle(V3d_Light)& theLightNew,
10608                       const Graphic3d_ZLayerId theLayer,
10609                       const Standard_Boolean   theIsGlobal)
10610 {
10611   if (theLightNew.IsNull())
10612   {
10613     return;
10614   }
10615
10616   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10617   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10618   {
10619     aViewer->AddLight (theLightNew);
10620     if (theIsGlobal)
10621     {
10622       aViewer->SetLightOn (theLightNew);
10623     }
10624     else
10625     {
10626       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10627     }
10628   }
10629   else
10630   {
10631     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10632     if (aSettings.Lights().IsNull())
10633     {
10634       aSettings.SetLights (new Graphic3d_LightSet());
10635     }
10636     aSettings.Lights()->Add (theLightNew);
10637     aViewer->SetZLayerSettings (theLayer, aSettings);
10638   }
10639 }
10640
10641 //! Auxiliary method
10642 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10643 {
10644   TCollection_AsciiString anArgNextCase (theArgNext);
10645   anArgNextCase.UpperCase();
10646   if (anArgNextCase.Length() > 5
10647    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10648   {
10649     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10650   }
10651   else
10652   {
10653     return theArgNext.IntegerValue();
10654   }
10655 }
10656
10657 //===============================================================================================
10658 //function : VLight
10659 //purpose  :
10660 //===============================================================================================
10661 static int VLight (Draw_Interpretor& theDi,
10662                    Standard_Integer  theArgsNb,
10663                    const char**      theArgVec)
10664 {
10665   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10666   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10667   if (aView.IsNull()
10668    || aViewer.IsNull())
10669   {
10670     std::cerr << "No active viewer!\n";
10671     return 1;
10672   }
10673
10674   Standard_Real anXYZ[3]   = {};
10675   Standard_Real anAtten[2] = {};
10676   if (theArgsNb < 2)
10677   {
10678     // print lights info
10679     Standard_Integer aLightId = 0;
10680     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10681     {
10682       Handle(V3d_Light) aLight = aLightIter.Value();
10683       const Quantity_Color aColor = aLight->Color();
10684       theDi << "Light #" << aLightId
10685             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10686             << " [" << aLight->GetId() << "]" << "\n";
10687       switch (aLight->Type())
10688       {
10689         case V3d_AMBIENT:
10690         {
10691           theDi << "  Type:       Ambient\n";
10692           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10693           break;
10694         }
10695         case V3d_DIRECTIONAL:
10696         {
10697           theDi << "  Type:       Directional\n";
10698           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10699           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10700           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10701           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10702           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10703           break;
10704         }
10705         case V3d_POSITIONAL:
10706         {
10707           theDi << "  Type:       Positional\n";
10708           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10709           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10710           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10711           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10712           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10713           aLight->Attenuation (anAtten[0], anAtten[1]);
10714           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10715           theDi << "  Range:      " << aLight->Range() << "\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           theDi << "  Range:      " << aLight->Range() << "\n";
10732           break;
10733         }
10734         default:
10735         {
10736           theDi << "  Type:       UNKNOWN\n";
10737           break;
10738         }
10739       }
10740       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10741     }
10742   }
10743
10744   Handle(V3d_Light) aLightNew;
10745   Handle(V3d_Light) aLightOld;
10746   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10747   Standard_Boolean  isGlobal = Standard_True;
10748   Standard_Boolean  toCreate = Standard_False;
10749   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10750   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10751   {
10752     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10753
10754     TCollection_AsciiString aName, aValue;
10755     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10756     TCollection_AsciiString anArgCase (anArg);
10757     anArgCase.UpperCase();
10758     if (anUpdateTool.parseRedrawMode (anArg))
10759     {
10760       continue;
10761     }
10762
10763     if (anArgCase.IsEqual ("NEW")
10764      || anArgCase.IsEqual ("ADD")
10765      || anArgCase.IsEqual ("CREATE")
10766      || anArgCase.IsEqual ("-NEW")
10767      || anArgCase.IsEqual ("-ADD")
10768      || anArgCase.IsEqual ("-CREATE"))
10769     {
10770       toCreate = Standard_True;
10771     }
10772     else if (anArgCase.IsEqual ("-LAYER")
10773           || anArgCase.IsEqual ("-ZLAYER"))
10774     {
10775       if (++anArgIt >= theArgsNb)
10776       {
10777         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10778         return 1;
10779       }
10780
10781       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10782       aValStr.LowerCase();
10783       if (aValStr == "default"
10784        || aValStr == "def")
10785       {
10786         aLayer = Graphic3d_ZLayerId_Default;
10787       }
10788       else if (aValStr == "top")
10789       {
10790         aLayer = Graphic3d_ZLayerId_Top;
10791       }
10792       else if (aValStr == "topmost")
10793       {
10794         aLayer = Graphic3d_ZLayerId_Topmost;
10795       }
10796       else if (aValStr == "toposd"
10797             || aValStr == "osd")
10798       {
10799         aLayer = Graphic3d_ZLayerId_TopOSD;
10800       }
10801       else if (aValStr == "botosd"
10802             || aValStr == "bottom")
10803       {
10804         aLayer = Graphic3d_ZLayerId_BotOSD;
10805       }
10806       else if (aValStr.IsIntegerValue())
10807       {
10808         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10809       }
10810       else
10811       {
10812         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10813         return 1;
10814       }
10815     }
10816     else if (anArgCase.IsEqual ("GLOB")
10817           || anArgCase.IsEqual ("GLOBAL")
10818           || anArgCase.IsEqual ("-GLOB")
10819           || anArgCase.IsEqual ("-GLOBAL"))
10820     {
10821       isGlobal = Standard_True;
10822     }
10823     else if (anArgCase.IsEqual ("LOC")
10824           || anArgCase.IsEqual ("LOCAL")
10825           || anArgCase.IsEqual ("-LOC")
10826           || anArgCase.IsEqual ("-LOCAL"))
10827     {
10828       isGlobal = Standard_False;
10829     }
10830     else if (anArgCase.IsEqual ("DEF")
10831           || anArgCase.IsEqual ("DEFAULTS")
10832           || anArgCase.IsEqual ("-DEF")
10833           || anArgCase.IsEqual ("-DEFAULTS"))
10834     {
10835       toCreate = Standard_False;
10836       aViewer->SetDefaultLights();
10837     }
10838     else if (anArgCase.IsEqual ("CLR")
10839           || anArgCase.IsEqual ("CLEAR")
10840           || anArgCase.IsEqual ("-CLR")
10841           || anArgCase.IsEqual ("-CLEAR"))
10842     {
10843       toCreate = Standard_False;
10844
10845       TColStd_SequenceOfInteger aLayers;
10846       aViewer->GetAllZLayers (aLayers);
10847       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10848       {
10849         if (aLayeriter.Value() == aLayer
10850          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10851         {
10852           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10853           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10854           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10855           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10856           {
10857             break;
10858           }
10859         }
10860       }
10861
10862       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10863       {
10864         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10865         {
10866           Handle(V3d_Light) aLight = aLightIter.Value();
10867           aViewer->DelLight (aLight);
10868           aLightIter = aView->ActiveLightIterator();
10869         }
10870       }
10871     }
10872     else if (anArgCase.IsEqual ("AMB")
10873           || anArgCase.IsEqual ("AMBIENT")
10874           || anArgCase.IsEqual ("AMBLIGHT"))
10875     {
10876       if (!toCreate)
10877       {
10878         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10879         return 1;
10880       }
10881
10882       addLight (aLightNew, aLayer, isGlobal);
10883       toCreate  = Standard_False;
10884       aLightNew = new V3d_AmbientLight();
10885     }
10886     else if (anArgCase.IsEqual ("DIRECTIONAL")
10887           || anArgCase.IsEqual ("DIRLIGHT"))
10888     {
10889       if (!toCreate)
10890       {
10891         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10892         return 1;
10893       }
10894
10895       addLight (aLightNew, aLayer, isGlobal);
10896       toCreate  = Standard_False;
10897       aLightNew = new V3d_DirectionalLight();
10898     }
10899     else if (anArgCase.IsEqual ("SPOT")
10900           || anArgCase.IsEqual ("SPOTLIGHT"))
10901     {
10902       if (!toCreate)
10903       {
10904         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10905         return 1;
10906       }
10907
10908       addLight (aLightNew, aLayer, isGlobal);
10909       toCreate  = Standard_False;
10910       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10911     }
10912     else if (anArgCase.IsEqual ("POSLIGHT")
10913           || anArgCase.IsEqual ("POSITIONAL"))
10914     {
10915       if (!toCreate)
10916       {
10917         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10918         return 1;
10919       }
10920
10921       addLight (aLightNew, aLayer, isGlobal);
10922       toCreate  = Standard_False;
10923       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10924     }
10925     else if (anArgCase.IsEqual ("CHANGE")
10926           || anArgCase.IsEqual ("-CHANGE"))
10927     {
10928       if (++anArgIt >= theArgsNb)
10929       {
10930         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10931         return 1;
10932       }
10933
10934       addLight (aLightNew, aLayer, isGlobal);
10935       aLightNew.Nullify();
10936       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10937       Standard_Integer aLightIt = 0;
10938       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10939       {
10940         if (aLightIt == aLightId)
10941         {
10942           aLightOld = aLightIter.Value();
10943           break;
10944         }
10945       }
10946
10947       if (aLightOld.IsNull())
10948       {
10949         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10950         return 1;
10951       }
10952     }
10953     else if (anArgCase.IsEqual ("DEL")
10954           || anArgCase.IsEqual ("DELETE")
10955           || anArgCase.IsEqual ("-DEL")
10956           || anArgCase.IsEqual ("-DELETE"))
10957     {
10958       Handle(V3d_Light) aLightDel;
10959       if (++anArgIt >= theArgsNb)
10960       {
10961         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10962         return 1;
10963       }
10964
10965       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10966       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10967       Standard_Integer aLightIt = 0;
10968       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10969       {
10970         aLightDel = aLightIter.Value();
10971         if (aLightIt == aLightDelId)
10972         {
10973           break;
10974         }
10975       }
10976       if (aLightDel.IsNull())
10977       {
10978         continue;
10979       }
10980
10981       TColStd_SequenceOfInteger aLayers;
10982       aViewer->GetAllZLayers (aLayers);
10983       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10984       {
10985         if (aLayeriter.Value() == aLayer
10986          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10987         {
10988           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10989           if (!aSettings.Lights().IsNull())
10990           {
10991             aSettings.Lights()->Remove (aLightDel);
10992             if (aSettings.Lights()->IsEmpty())
10993             {
10994               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10995             }
10996           }
10997           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10998           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10999           {
11000             break;
11001           }
11002         }
11003       }
11004
11005       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
11006       {
11007         aViewer->DelLight (aLightDel);
11008       }
11009     }
11010     else if (anArgCase.IsEqual ("COLOR")
11011           || anArgCase.IsEqual ("COLOUR")
11012           || anArgCase.IsEqual ("-COLOR")
11013           || anArgCase.IsEqual ("-COLOUR"))
11014     {
11015       if (++anArgIt >= theArgsNb
11016        || aLightCurr.IsNull())
11017       {
11018         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11019         return 1;
11020       }
11021
11022       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
11023       anArgNext.UpperCase();
11024       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
11025       aLightCurr->SetColor (aColor);
11026     }
11027     else if (anArgCase.IsEqual ("POS")
11028           || anArgCase.IsEqual ("POSITION")
11029           || anArgCase.IsEqual ("-POS")
11030           || anArgCase.IsEqual ("-POSITION"))
11031     {
11032       if ((anArgIt + 3) >= theArgsNb
11033        || aLightCurr.IsNull()
11034        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11035         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11036       {
11037         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11038         return 1;
11039       }
11040
11041       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11042       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11043       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11044       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
11045     }
11046     else if (anArgCase.IsEqual ("DIR")
11047           || anArgCase.IsEqual ("DIRECTION")
11048           || anArgCase.IsEqual ("-DIR")
11049           || anArgCase.IsEqual ("-DIRECTION"))
11050     {
11051       if ((anArgIt + 3) >= theArgsNb
11052        || aLightCurr.IsNull()
11053        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
11054         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11055       {
11056         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11057         return 1;
11058       }
11059
11060       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11061       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11062       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11063       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
11064     }
11065     else if (anArgCase.IsEqual ("SM")
11066           || anArgCase.IsEqual ("SMOOTHNESS")
11067           || anArgCase.IsEqual ("-SM")
11068           || anArgCase.IsEqual ("-SMOOTHNESS"))
11069     {
11070       if (++anArgIt >= theArgsNb
11071        || aLightCurr.IsNull())
11072       {
11073         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11074         return 1;
11075       }
11076
11077       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11078       if (Abs (aSmoothness) <= ShortRealEpsilon())
11079       {
11080         aLightCurr->SetIntensity (1.f);
11081       }
11082       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
11083       {
11084         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
11085       }
11086       else
11087       {
11088         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
11089         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
11090       }
11091
11092       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
11093       {
11094         aLightCurr->SetSmoothRadius (aSmoothness);
11095       }
11096       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
11097       {
11098         aLightCurr->SetSmoothAngle (aSmoothness);
11099       }
11100     }
11101     else if (anArgCase.IsEqual ("INT")
11102           || anArgCase.IsEqual ("INTENSITY")
11103           || anArgCase.IsEqual ("-INT")
11104           || anArgCase.IsEqual ("-INTENSITY"))
11105     {
11106       if (++anArgIt >= theArgsNb
11107        || aLightCurr.IsNull())
11108       {
11109         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11110         return 1;
11111       }
11112
11113       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11114       aLightCurr->SetIntensity (aIntensity);
11115     }
11116     else if (anArgCase.IsEqual ("ANG")
11117           || anArgCase.IsEqual ("ANGLE")
11118           || anArgCase.IsEqual ("-ANG")
11119           || anArgCase.IsEqual ("-ANGLE"))
11120     {
11121       if (++anArgIt >= theArgsNb
11122        || aLightCurr.IsNull()
11123        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11124       {
11125         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11126         return 1;
11127       }
11128
11129       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11130       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
11131     }
11132     else if (anArgCase.IsEqual ("CONSTATTEN")
11133           || anArgCase.IsEqual ("CONSTATTENUATION")
11134           || anArgCase.IsEqual ("-CONSTATTEN")
11135           || anArgCase.IsEqual ("-CONSTATTENUATION"))
11136     {
11137       if (++anArgIt >= theArgsNb
11138        || aLightCurr.IsNull()
11139        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11140         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11141       {
11142         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11143         return 1;
11144       }
11145
11146       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11147       anAtten[0] = Atof (theArgVec[anArgIt]);
11148       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11149     }
11150     else if (anArgCase.IsEqual ("LINATTEN")
11151           || anArgCase.IsEqual ("LINEARATTEN")
11152           || anArgCase.IsEqual ("LINEARATTENUATION")
11153           || anArgCase.IsEqual ("-LINATTEN")
11154           || anArgCase.IsEqual ("-LINEARATTEN")
11155           || anArgCase.IsEqual ("-LINEARATTENUATION"))
11156     {
11157       if (++anArgIt >= theArgsNb
11158        || aLightCurr.IsNull()
11159        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11160         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11161       {
11162         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11163         return 1;
11164       }
11165
11166       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11167       anAtten[1] = Atof (theArgVec[anArgIt]);
11168       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11169     }
11170     else if (anArgCase.IsEqual ("EXP")
11171           || anArgCase.IsEqual ("EXPONENT")
11172           || anArgCase.IsEqual ("SPOTEXP")
11173           || anArgCase.IsEqual ("SPOTEXPONENT")
11174           || anArgCase.IsEqual ("-EXP")
11175           || anArgCase.IsEqual ("-EXPONENT")
11176           || anArgCase.IsEqual ("-SPOTEXP")
11177           || anArgCase.IsEqual ("-SPOTEXPONENT"))
11178     {
11179       if (++anArgIt >= theArgsNb
11180        || aLightCurr.IsNull()
11181        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11182       {
11183         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11184         return 1;
11185       }
11186
11187       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
11188     }
11189     else if (anArgCase.IsEqual("RANGE")
11190           || anArgCase.IsEqual("-RANGE"))
11191     {
11192       if (++anArgIt >= theArgsNb
11193        || aLightCurr.IsNull()
11194        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT
11195        || aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
11196       {
11197         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11198         return 1;
11199       }
11200
11201       aLightCurr->SetRange ((Standard_ShortReal)Atof (theArgVec[anArgIt]));
11202     }
11203     else if (anArgCase.IsEqual ("HEAD")
11204           || anArgCase.IsEqual ("HEADLIGHT")
11205           || anArgCase.IsEqual ("-HEAD")
11206           || anArgCase.IsEqual ("-HEADLIGHT"))
11207     {
11208       if (aLightCurr.IsNull()
11209        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
11210       {
11211         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11212         return 1;
11213       }
11214
11215       Standard_Boolean isHeadLight = Standard_True;
11216       if (anArgIt + 1 < theArgsNb
11217        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
11218       {
11219         ++anArgIt;
11220       }
11221       aLightCurr->SetHeadlight (isHeadLight);
11222     }
11223     else
11224     {
11225       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
11226     }
11227   }
11228
11229   addLight (aLightNew, aLayer, isGlobal);
11230   return 0;
11231 }
11232
11233 //===============================================================================================
11234 //function : VPBREnvironment
11235 //purpose  :
11236 //===============================================================================================
11237 static int VPBREnvironment (Draw_Interpretor&,
11238                             Standard_Integer theArgsNb,
11239                             const char**     theArgVec)
11240 {
11241   if (theArgsNb > 2)
11242   {
11243     std::cerr << "Error: 'vpbrenv' command has only one argument\n";
11244     return 1;
11245   }
11246
11247   Handle(V3d_View) aView = ViewerTest::CurrentView();
11248   if (aView.IsNull())
11249   {
11250     std::cerr << "Error: no active viewer!\n";
11251     return 1;
11252   }
11253
11254   TCollection_AsciiString anArg = TCollection_AsciiString (theArgVec[1]);
11255   anArg.LowerCase();
11256
11257   if (anArg == "-generate"
11258    || anArg == "-gen")
11259   {
11260     aView->GeneratePBREnvironment (Standard_True);
11261   }
11262   else if (anArg == "-clear")
11263   {
11264     aView->ClearPBREnvironment (Standard_True);
11265   }
11266   else
11267   {
11268     std::cerr << "Error: unknown argument [" << theArgVec[1] << "] for 'vpbrenv' command\n";
11269     return 1;
11270   }
11271
11272   return 0;
11273 }
11274
11275 //! Read Graphic3d_RenderingParams::PerfCounters flag.
11276 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
11277                                             Standard_Boolean& theToReset,
11278                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
11279                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
11280 {
11281   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
11282   TCollection_AsciiString aVal = theValue;
11283   Standard_Boolean toReverse = Standard_False;
11284   if (aVal == "none")
11285   {
11286     theToReset = Standard_True;
11287     return Standard_True;
11288   }
11289   else if (aVal.StartsWith ("-"))
11290   {
11291     toReverse = Standard_True;
11292     aVal = aVal.SubString (2, aVal.Length());
11293   }
11294   else if (aVal.StartsWith ("no"))
11295   {
11296     toReverse = Standard_True;
11297     aVal = aVal.SubString (3, aVal.Length());
11298   }
11299   else if (aVal.StartsWith ("+"))
11300   {
11301     aVal = aVal.SubString (2, aVal.Length());
11302   }
11303   else
11304   {
11305     theToReset = Standard_True;
11306   }
11307
11308   if (     aVal == "fps"
11309         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11310   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
11311   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
11312   else if (aVal == "structs"
11313         || aVal == "structures"
11314         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
11315   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
11316   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11317   else if (aVal == "tris"
11318         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
11319   else if (aVal == "pnts"
11320         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
11321   else if (aVal == "mem"
11322         || aVal == "gpumem"
11323         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11324   else if (aVal == "skipimmediate"
11325         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
11326   else if (aVal == "frametime"
11327         || aVal == "frametimers"
11328         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11329   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
11330   else if (aVal == "extended"
11331         || aVal == "verbose"
11332         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
11333   else if (aVal == "full"
11334         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
11335   else
11336   {
11337     return Standard_False;
11338   }
11339
11340   if (toReverse)
11341   {
11342     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11343   }
11344   else
11345   {
11346     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11347   }
11348   return Standard_True;
11349 }
11350
11351 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11352 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11353                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11354 {
11355   TCollection_AsciiString aValue = theValue;
11356   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11357   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11358   Standard_Boolean toReset = Standard_False;
11359   for (;;)
11360   {
11361     Standard_Integer aSplitPos = aValue.Search ("|");
11362     if (aSplitPos <= 0)
11363     {
11364       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11365       {
11366         return Standard_False;
11367       }
11368       if (toReset)
11369       {
11370         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11371       }
11372       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11373       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11374       return Standard_True;
11375     }
11376
11377     if (aSplitPos > 1)
11378     {
11379       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11380       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11381       {
11382         return Standard_False;
11383       }
11384     }
11385     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11386   }
11387 }
11388
11389 //=======================================================================
11390 //function : VRenderParams
11391 //purpose  : Enables/disables rendering features
11392 //=======================================================================
11393
11394 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11395                                        Standard_Integer  theArgNb,
11396                                        const char**      theArgVec)
11397 {
11398   Handle(V3d_View) aView = ViewerTest::CurrentView();
11399   if (aView.IsNull())
11400   {
11401     std::cerr << "Error: no active viewer!\n";
11402     return 1;
11403   }
11404
11405   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11406   TCollection_AsciiString aCmdName (theArgVec[0]);
11407   aCmdName.LowerCase();
11408   if (aCmdName == "vraytrace")
11409   {
11410     if (theArgNb == 1)
11411     {
11412       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11413       return 0;
11414     }
11415     else if (theArgNb == 2)
11416     {
11417       TCollection_AsciiString aValue (theArgVec[1]);
11418       aValue.LowerCase();
11419       if (aValue == "on"
11420        || aValue == "1")
11421       {
11422         aParams.Method = Graphic3d_RM_RAYTRACING;
11423         aView->Redraw();
11424         return 0;
11425       }
11426       else if (aValue == "off"
11427             || aValue == "0")
11428       {
11429         aParams.Method = Graphic3d_RM_RASTERIZATION;
11430         aView->Redraw();
11431         return 0;
11432       }
11433       else
11434       {
11435         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11436         return 1;
11437       }
11438     }
11439     else
11440     {
11441       std::cout << "Error: wrong number of arguments\n";
11442       return 1;
11443     }
11444   }
11445
11446   if (theArgNb < 2)
11447   {
11448     theDI << "renderMode:  ";
11449     switch (aParams.Method)
11450     {
11451       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11452       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11453     }
11454     theDI << "\n";
11455     theDI << "transparency:  ";
11456     switch (aParams.TransparencyMethod)
11457     {
11458       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11459       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11460                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11461     }
11462     theDI << "\n";
11463     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11464     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11465     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11466     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11467     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11468     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11469     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11470     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11471     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11472     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11473     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11474     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11475     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11476     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11477     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11478     theDI << "shadingModel: ";
11479     switch (aView->ShadingModel())
11480     {
11481       case Graphic3d_TOSM_DEFAULT:   theDI << "default";   break;
11482       case Graphic3d_TOSM_UNLIT:     theDI << "unlit";     break;
11483       case Graphic3d_TOSM_FACET:     theDI << "flat";      break;
11484       case Graphic3d_TOSM_VERTEX:    theDI << "gouraud";   break;
11485       case Graphic3d_TOSM_FRAGMENT:  theDI << "phong";     break;
11486       case Graphic3d_TOSM_PBR:       theDI << "pbr";       break;
11487       case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
11488     }
11489     {
11490       theDI << "perfCounters:";
11491       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11492       {
11493         theDI << " fps";
11494       }
11495       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11496       {
11497         theDI << " cpu";
11498       }
11499       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11500       {
11501         theDI << " structs";
11502       }
11503       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11504       {
11505         theDI << " groups";
11506       }
11507       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11508       {
11509         theDI << " arrays";
11510       }
11511       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11512       {
11513         theDI << " tris";
11514       }
11515       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11516       {
11517         theDI << " pnts";
11518       }
11519       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11520       {
11521         theDI << " gpumem";
11522       }
11523       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11524       {
11525         theDI << " frameTime";
11526       }
11527       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11528       {
11529         theDI << " skipimmediate";
11530       }
11531       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11532       {
11533         theDI << " none";
11534       }
11535       theDI << "\n";
11536     }
11537     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11538     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11539     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11540                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11541                                                                                                                     "noUpdate") << "\n";
11542     theDI << "\n";
11543     return 0;
11544   }
11545
11546   Standard_Boolean toPrint = Standard_False;
11547   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11548   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11549   {
11550     Standard_CString        anArg (theArgVec[anArgIter]);
11551     TCollection_AsciiString aFlag (anArg);
11552     aFlag.LowerCase();
11553     if (anUpdateTool.parseRedrawMode (aFlag))
11554     {
11555       continue;
11556     }
11557     else if (aFlag == "-echo"
11558           || aFlag == "-print")
11559     {
11560       toPrint = Standard_True;
11561       anUpdateTool.Invalidate();
11562     }
11563     else if (aFlag == "-mode"
11564           || aFlag == "-rendermode"
11565           || aFlag == "-render_mode")
11566     {
11567       if (toPrint)
11568       {
11569         switch (aParams.Method)
11570         {
11571           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11572           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11573         }
11574         continue;
11575       }
11576       else
11577       {
11578         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11579         return 1;
11580       }
11581     }
11582     else if (aFlag == "-ray"
11583           || aFlag == "-raytrace")
11584     {
11585       if (toPrint)
11586       {
11587         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11588         continue;
11589       }
11590
11591       aParams.Method = Graphic3d_RM_RAYTRACING;
11592     }
11593     else if (aFlag == "-rast"
11594           || aFlag == "-raster"
11595           || aFlag == "-rasterization")
11596     {
11597       if (toPrint)
11598       {
11599         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11600         continue;
11601       }
11602
11603       aParams.Method = Graphic3d_RM_RASTERIZATION;
11604     }
11605     else if (aFlag == "-msaa")
11606     {
11607       if (toPrint)
11608       {
11609         theDI << aParams.NbMsaaSamples << " ";
11610         continue;
11611       }
11612       else if (++anArgIter >= theArgNb)
11613       {
11614         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11615         return 1;
11616       }
11617
11618       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11619       if (aNbSamples < 0)
11620       {
11621         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11622         return 1;
11623       }
11624       else
11625       {
11626         aParams.NbMsaaSamples = aNbSamples;
11627       }
11628     }
11629     else if (aFlag == "-linefeather"
11630           || aFlag == "-edgefeather"
11631           || aFlag == "-feather")
11632     {
11633       if (toPrint)
11634       {
11635         theDI << " " << aParams.LineFeather << " ";
11636         continue;
11637       }
11638       else if (++anArgIter >= theArgNb)
11639       {
11640         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11641         return 1;
11642       }
11643
11644       TCollection_AsciiString aParam = theArgVec[anArgIter];
11645       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11646       if (aFeather <= 0.0f)
11647       {
11648         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11649         return 1;
11650       }
11651       aParams.LineFeather = aFeather;
11652     }
11653     else if (aFlag == "-oit")
11654     {
11655       if (toPrint)
11656       {
11657         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11658         {
11659           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11660         }
11661         else
11662         {
11663           theDI << "off" << " ";
11664         }
11665         continue;
11666       }
11667       else if (++anArgIter >= theArgNb)
11668       {
11669         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11670         return 1;
11671       }
11672
11673       TCollection_AsciiString aParam = theArgVec[anArgIter];
11674       aParam.LowerCase();
11675       if (aParam.IsRealValue())
11676       {
11677         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11678         if (aWeight < 0.f || aWeight > 1.f)
11679         {
11680           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11681           return 1;
11682         }
11683
11684         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11685         aParams.OitDepthFactor     = aWeight;
11686       }
11687       else if (aParam == "off")
11688       {
11689         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11690       }
11691       else
11692       {
11693         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11694         return 1;
11695       }
11696     }
11697     else if (aFlag == "-depthprepass")
11698     {
11699       if (toPrint)
11700       {
11701         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11702         continue;
11703       }
11704       aParams.ToEnableDepthPrepass = Standard_True;
11705       if (anArgIter + 1 < theArgNb
11706        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11707       {
11708         ++anArgIter;
11709       }
11710     }
11711     else if (aFlag == "-samplealphatocoverage"
11712           || aFlag == "-alphatocoverage")
11713     {
11714       if (toPrint)
11715       {
11716         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11717         continue;
11718       }
11719       aParams.ToEnableAlphaToCoverage = Standard_True;
11720       if (anArgIter + 1 < theArgNb
11721        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11722       {
11723         ++anArgIter;
11724       }
11725     }
11726     else if (aFlag == "-rendscale"
11727           || aFlag == "-renderscale"
11728           || aFlag == "-renderresolutionscale")
11729     {
11730       if (toPrint)
11731       {
11732         theDI << aParams.RenderResolutionScale << " ";
11733         continue;
11734       }
11735       else if (++anArgIter >= theArgNb)
11736       {
11737         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11738         return 1;
11739       }
11740
11741       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11742       if (aScale < 0.01)
11743       {
11744         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11745         return 1;
11746       }
11747       else
11748       {
11749         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11750       }
11751     }
11752     else if (aFlag == "-raydepth"
11753           || aFlag == "-ray_depth")
11754     {
11755       if (toPrint)
11756       {
11757         theDI << aParams.RaytracingDepth << " ";
11758         continue;
11759       }
11760       else if (++anArgIter >= theArgNb)
11761       {
11762         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11763         return 1;
11764       }
11765
11766       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11767
11768       // We allow RaytracingDepth be more than 10 in case of GI enabled
11769       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11770       {
11771         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11772         return 1;
11773       }
11774       else
11775       {
11776         aParams.RaytracingDepth = aDepth;
11777       }
11778     }
11779     else if (aFlag == "-shad"
11780           || aFlag == "-shadows")
11781     {
11782       if (toPrint)
11783       {
11784         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11785         continue;
11786       }
11787
11788       Standard_Boolean toEnable = Standard_True;
11789       if (++anArgIter < theArgNb
11790       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11791       {
11792         --anArgIter;
11793       }
11794       aParams.IsShadowEnabled = toEnable;
11795     }
11796     else if (aFlag == "-refl"
11797           || aFlag == "-reflections")
11798     {
11799       if (toPrint)
11800       {
11801         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11802         continue;
11803       }
11804
11805       Standard_Boolean toEnable = Standard_True;
11806       if (++anArgIter < theArgNb
11807       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11808       {
11809         --anArgIter;
11810       }
11811       aParams.IsReflectionEnabled = toEnable;
11812     }
11813     else if (aFlag == "-fsaa")
11814     {
11815       if (toPrint)
11816       {
11817         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11818         continue;
11819       }
11820
11821       Standard_Boolean toEnable = Standard_True;
11822       if (++anArgIter < theArgNb
11823       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11824       {
11825         --anArgIter;
11826       }
11827       aParams.IsAntialiasingEnabled = toEnable;
11828     }
11829     else if (aFlag == "-gleam")
11830     {
11831       if (toPrint)
11832       {
11833         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11834         continue;
11835       }
11836
11837       Standard_Boolean toEnable = Standard_True;
11838       if (++anArgIter < theArgNb
11839       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11840       {
11841         --anArgIter;
11842       }
11843       aParams.IsTransparentShadowEnabled = toEnable;
11844     }
11845     else if (aFlag == "-gi")
11846     {
11847       if (toPrint)
11848       {
11849         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11850         continue;
11851       }
11852
11853       Standard_Boolean toEnable = Standard_True;
11854       if (++anArgIter < theArgNb
11855       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11856       {
11857         --anArgIter;
11858       }
11859       aParams.IsGlobalIlluminationEnabled = toEnable;
11860       if (!toEnable)
11861       {
11862         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11863       }
11864     }
11865     else if (aFlag == "-blockedrng"
11866           || aFlag == "-brng")
11867     {
11868       if (toPrint)
11869       {
11870         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11871         continue;
11872       }
11873
11874       Standard_Boolean toEnable = Standard_True;
11875       if (++anArgIter < theArgNb
11876         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11877       {
11878         --anArgIter;
11879       }
11880       aParams.CoherentPathTracingMode = toEnable;
11881     }
11882     else if (aFlag == "-maxrad")
11883     {
11884       if (toPrint)
11885       {
11886         theDI << aParams.RadianceClampingValue << " ";
11887         continue;
11888       }
11889       else if (++anArgIter >= theArgNb)
11890       {
11891         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11892         return 1;
11893       }
11894
11895       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11896       if (!aMaxRadStr.IsRealValue())
11897       {
11898         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11899         return 1;
11900       }
11901
11902       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11903       if (aMaxRadiance <= 0.0)
11904       {
11905         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11906         return 1;
11907       }
11908       else
11909       {
11910         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11911       }
11912     }
11913     else if (aFlag == "-iss")
11914     {
11915       if (toPrint)
11916       {
11917         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11918         continue;
11919       }
11920
11921       Standard_Boolean toEnable = Standard_True;
11922       if (++anArgIter < theArgNb
11923         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11924       {
11925         --anArgIter;
11926       }
11927       aParams.AdaptiveScreenSampling = toEnable;
11928     }
11929     else if (aFlag == "-issatomic")
11930     {
11931       if (toPrint)
11932       {
11933         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11934         continue;
11935       }
11936
11937       Standard_Boolean toEnable = Standard_True;
11938       if (++anArgIter < theArgNb
11939       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11940       {
11941         --anArgIter;
11942       }
11943       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11944     }
11945     else if (aFlag == "-issd")
11946     {
11947       if (toPrint)
11948       {
11949         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11950         continue;
11951       }
11952
11953       Standard_Boolean toEnable = Standard_True;
11954       if (++anArgIter < theArgNb
11955         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11956       {
11957         --anArgIter;
11958       }
11959       aParams.ShowSamplingTiles = toEnable;
11960     }
11961     else if (aFlag == "-tilesize")
11962     {
11963       if (toPrint)
11964       {
11965         theDI << aParams.RayTracingTileSize << " ";
11966         continue;
11967       }
11968       else if (++anArgIter >= theArgNb)
11969       {
11970         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11971         return 1;
11972       }
11973
11974       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11975       if (aTileSize < 1)
11976       {
11977         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11978         return 1;
11979       }
11980       aParams.RayTracingTileSize = aTileSize;
11981     }
11982     else if (aFlag == "-nbtiles")
11983     {
11984       if (toPrint)
11985       {
11986         theDI << aParams.NbRayTracingTiles << " ";
11987         continue;
11988       }
11989       else if (++anArgIter >= theArgNb)
11990       {
11991         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11992         return 1;
11993       }
11994
11995       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11996       if (aNbTiles < -1)
11997       {
11998         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11999         return 1;
12000       }
12001       else if (aNbTiles > 0
12002             && (aNbTiles < 64
12003              || aNbTiles > 1024))
12004       {
12005         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
12006       }
12007       aParams.NbRayTracingTiles = aNbTiles;
12008     }
12009     else if (aFlag == "-env")
12010     {
12011       if (toPrint)
12012       {
12013         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
12014         continue;
12015       }
12016
12017       Standard_Boolean toEnable = Standard_True;
12018       if (++anArgIter < theArgNb
12019         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12020       {
12021         --anArgIter;
12022       }
12023       aParams.UseEnvironmentMapBackground = toEnable;
12024     }
12025     else if (aFlag == "-ignorenormalmap")
12026     {
12027       if (toPrint)
12028       {
12029         theDI << (aParams.ToIgnoreNormalMapInRayTracing ? "on" : "off") << " ";
12030         continue;
12031       }
12032
12033       Standard_Boolean toEnable = Standard_True;
12034       if (++anArgIter < theArgNb
12035         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12036       {
12037         --anArgIter;
12038       }
12039       aParams.ToIgnoreNormalMapInRayTracing = toEnable;
12040     }
12041     else if (aFlag == "-twoside")
12042     {
12043       if (toPrint)
12044       {
12045         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
12046         continue;
12047       }
12048
12049       Standard_Boolean toEnable = Standard_True;
12050       if (++anArgIter < theArgNb
12051         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12052       {
12053         --anArgIter;
12054       }
12055       aParams.TwoSidedBsdfModels = toEnable;
12056     }
12057     else if (aFlag == "-shademodel"
12058           || aFlag == "-shadingmodel"
12059           || aFlag == "-shading")
12060     {
12061       if (toPrint)
12062       {
12063         switch (aView->ShadingModel())
12064         {
12065           case Graphic3d_TOSM_DEFAULT:   theDI << "default";   break;
12066           case Graphic3d_TOSM_UNLIT:     theDI << "unlit ";    break;
12067           case Graphic3d_TOSM_FACET:     theDI << "flat ";     break;
12068           case Graphic3d_TOSM_VERTEX:    theDI << "gouraud ";  break;
12069           case Graphic3d_TOSM_FRAGMENT:  theDI << "phong ";    break;
12070           case Graphic3d_TOSM_PBR:       theDI << "pbr";       break;
12071           case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
12072         }
12073         continue;
12074       }
12075
12076       if (++anArgIter >= theArgNb)
12077       {
12078         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12079       }
12080
12081       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
12082       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
12083        && aModel != Graphic3d_TOSM_DEFAULT)
12084       {
12085         aView->SetShadingModel (aModel);
12086       }
12087       else
12088       {
12089         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
12090         return 1;
12091       }
12092     }
12093     else if (aFlag == "-pbrenvpow2size"
12094           || aFlag == "-pbrenvp2s"
12095           || aFlag == "-pep2s")
12096     {
12097       if (++anArgIter >= theArgNb)
12098       {
12099         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12100         return 1;
12101       }
12102
12103       const Standard_Integer aPbrEnvPow2Size = Draw::Atoi (theArgVec[anArgIter]);
12104       if (aPbrEnvPow2Size < 1)
12105       {
12106         std::cout << "Error: 'Pow2Size' of PBR Environment has to be greater or equal 1\n";
12107         return 1;
12108       }
12109       aParams.PbrEnvPow2Size = aPbrEnvPow2Size;
12110     }
12111     else if (aFlag == "-pbrenvspecmaplevelsnumber"
12112           || aFlag == "-pbrenvspecmapnblevels"
12113           || aFlag == "-pbrenvspecmaplevels"
12114           || aFlag == "-pbrenvsmln"
12115           || aFlag == "-pesmln")
12116     {
12117       if (++anArgIter >= theArgNb)
12118       {
12119         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12120         return 1;
12121       }
12122
12123       const Standard_Integer aPbrEnvSpecMapNbLevels = Draw::Atoi (theArgVec[anArgIter]);
12124       if (aPbrEnvSpecMapNbLevels < 2)
12125       {
12126         std::cout << "Error: 'SpecMapLevelsNumber' of PBR Environment has to be greater or equal 2\n";
12127         return 1;
12128       }
12129       aParams.PbrEnvSpecMapNbLevels = aPbrEnvSpecMapNbLevels;
12130     }
12131     else if (aFlag == "-pbrenvbakngdiffsamplesnumber"
12132           || aFlag == "-pbrenvbakingdiffsamples"
12133           || aFlag == "-pbrenvbdsn")
12134     {
12135       if (++anArgIter >= theArgNb)
12136       {
12137         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12138         return 1;
12139       }
12140
12141       const Standard_Integer aPbrEnvBakingDiffNbSamples = Draw::Atoi (theArgVec[anArgIter]);
12142       if (aPbrEnvBakingDiffNbSamples < 1)
12143       {
12144         std::cout << "Error: 'BakingDiffSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
12145         return 1;
12146       }
12147       aParams.PbrEnvBakingDiffNbSamples = aPbrEnvBakingDiffNbSamples;
12148     }
12149     else if (aFlag == "-pbrenvbakngspecsamplesnumber"
12150           || aFlag == "-pbrenvbakingspecsamples"
12151           || aFlag == "-pbrenvbssn")
12152     {
12153     if (++anArgIter >= theArgNb)
12154     {
12155       std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12156       return 1;
12157     }
12158
12159     const Standard_Integer aPbrEnvBakingSpecNbSamples = Draw::Atoi(theArgVec[anArgIter]);
12160     if (aPbrEnvBakingSpecNbSamples < 1)
12161     {
12162       std::cout << "Error: 'BakingSpecSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
12163       return 1;
12164     }
12165     aParams.PbrEnvBakingSpecNbSamples = aPbrEnvBakingSpecNbSamples;
12166     }
12167     else if (aFlag == "-pbrenvbakingprobability"
12168           || aFlag == "-pbrenvbp")
12169     {
12170       if (++anArgIter >= theArgNb)
12171       {
12172         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12173         return 1;
12174       }
12175       const Standard_ShortReal aPbrEnvBakingProbability = static_cast<Standard_ShortReal>(Draw::Atof (theArgVec[anArgIter]));
12176       if (aPbrEnvBakingProbability < 0.f
12177        || aPbrEnvBakingProbability > 1.f)
12178       {
12179         std::cout << "Error: 'BakingProbability' of PBR Environtment has to be in range of [0, 1]\n";
12180         return 1;
12181       }
12182       aParams.PbrEnvBakingProbability = aPbrEnvBakingProbability;
12183     }
12184     else if (aFlag == "-resolution")
12185     {
12186       if (++anArgIter >= theArgNb)
12187       {
12188         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
12189         return 1;
12190       }
12191
12192       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
12193       if (aResolution.IsIntegerValue())
12194       {
12195         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
12196       }
12197       else
12198       {
12199         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12200         return 1;
12201       }
12202     }
12203     else if (aFlag == "-rebuildglsl"
12204           || aFlag == "-rebuild")
12205     {
12206       if (toPrint)
12207       {
12208         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
12209         continue;
12210       }
12211
12212       Standard_Boolean toEnable = Standard_True;
12213       if (++anArgIter < theArgNb
12214           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12215       {
12216         --anArgIter;
12217       }
12218       aParams.RebuildRayTracingShaders = toEnable;
12219     }
12220     else if (aFlag == "-focal")
12221     {
12222       if (++anArgIter >= theArgNb)
12223       {
12224         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12225         return 1;
12226       }
12227
12228       TCollection_AsciiString aParam (theArgVec[anArgIter]);
12229       if (aParam.IsRealValue())
12230       {
12231         float aFocalDist = static_cast<float> (aParam.RealValue());
12232         if (aFocalDist < 0)
12233         {
12234           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12235           return 1;
12236         }
12237         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
12238       }
12239       else
12240       {
12241         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12242         return 1;
12243       }
12244     }
12245     else if (aFlag == "-aperture")
12246     {
12247       if (++anArgIter >= theArgNb)
12248       {
12249         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12250         return 1;
12251       }
12252
12253       TCollection_AsciiString aParam(theArgVec[anArgIter]);
12254       if (aParam.IsRealValue())
12255       {
12256         float aApertureSize = static_cast<float> (aParam.RealValue());
12257         if (aApertureSize < 0)
12258         {
12259           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12260           return 1;
12261         }
12262         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
12263       }
12264       else
12265       {
12266         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12267         return 1;
12268       }
12269     }
12270     else if (aFlag == "-exposure")
12271     {
12272       if (++anArgIter >= theArgNb)
12273       {
12274         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12275         return 1;
12276       }
12277
12278       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
12279       if (anExposure.IsRealValue())
12280       {
12281         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
12282       }
12283       else
12284       {
12285         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12286         return 1;
12287       }
12288     }
12289     else if (aFlag == "-whitepoint")
12290     {
12291       if (++anArgIter >= theArgNb)
12292       {
12293         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12294         return 1;
12295       }
12296
12297       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
12298       if (aWhitePoint.IsRealValue())
12299       {
12300         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
12301       }
12302       else
12303       {
12304         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12305         return 1;
12306       }
12307     }
12308     else if (aFlag == "-tonemapping")
12309     {
12310       if (++anArgIter >= theArgNb)
12311       {
12312         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12313         return 1;
12314       }
12315
12316       TCollection_AsciiString aMode (theArgVec[anArgIter]);
12317       aMode.LowerCase();
12318
12319       if (aMode == "disabled")
12320       {
12321         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
12322       }
12323       else if (aMode == "filmic")
12324       {
12325         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
12326       }
12327       else
12328       {
12329         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12330         return 1;
12331       }
12332     }
12333     else if (aFlag == "-performancestats"
12334           || aFlag == "-performancecounters"
12335           || aFlag == "-perfstats"
12336           || aFlag == "-perfcounters"
12337           || aFlag == "-stats")
12338     {
12339       if (++anArgIter >= theArgNb)
12340       {
12341         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12342         return 1;
12343       }
12344
12345       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
12346       aFlagsStr.LowerCase();
12347       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
12348       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
12349       {
12350         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12351         return 1;
12352       }
12353       aView->ChangeRenderingParams().CollectedStats = aFlags;
12354       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
12355     }
12356     else if (aFlag == "-perfupdateinterval"
12357           || aFlag == "-statsupdateinterval")
12358     {
12359       if (++anArgIter >= theArgNb)
12360       {
12361         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12362         return 1;
12363       }
12364       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12365     }
12366     else if (aFlag == "-perfchart"
12367           || aFlag == "-statschart")
12368     {
12369       if (++anArgIter >= theArgNb)
12370       {
12371         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12372         return 1;
12373       }
12374       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
12375     }
12376     else if (aFlag == "-perfchartmax"
12377           || aFlag == "-statschartmax")
12378     {
12379       if (++anArgIter >= theArgNb)
12380       {
12381         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12382         return 1;
12383       }
12384       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12385     }
12386     else if (aFlag == "-frustumculling"
12387           || aFlag == "-culling")
12388     {
12389       if (toPrint)
12390       {
12391         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
12392                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
12393                                                                                                    "noUpdate") << " ";
12394         continue;
12395       }
12396
12397       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
12398       if (++anArgIter < theArgNb)
12399       {
12400         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
12401         aStateStr.LowerCase();
12402         bool toEnable = true;
12403         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
12404         {
12405           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
12406         }
12407         else if (aStateStr == "noupdate"
12408               || aStateStr == "freeze")
12409         {
12410           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
12411         }
12412         else
12413         {
12414           --anArgIter;
12415         }
12416       }
12417       aParams.FrustumCullingState = aState;
12418     }
12419     else
12420     {
12421       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
12422       return 1;
12423     }
12424   }
12425
12426   return 0;
12427 }
12428
12429 //=======================================================================
12430 //function : searchInfo
12431 //purpose  :
12432 //=======================================================================
12433 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12434                                            const TCollection_AsciiString&              theKey)
12435 {
12436   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12437   {
12438     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12439     {
12440       return anIter.Value();
12441     }
12442   }
12443   return TCollection_AsciiString();
12444 }
12445
12446 //=======================================================================
12447 //function : VStatProfiler
12448 //purpose  :
12449 //=======================================================================
12450 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12451                                        Standard_Integer  theArgNb,
12452                                        const char**      theArgVec)
12453 {
12454   Handle(V3d_View) aView = ViewerTest::CurrentView();
12455   if (aView.IsNull())
12456   {
12457     std::cerr << "Error: no active viewer!\n";
12458     return 1;
12459   }
12460
12461   Standard_Boolean toRedraw = Standard_True;
12462   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12463   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12464   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12465   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12466   {
12467     Standard_CString        anArg (theArgVec[anArgIter]);
12468     TCollection_AsciiString aFlag (anArg);
12469     aFlag.LowerCase();
12470     if (aFlag == "-noredraw")
12471     {
12472       toRedraw = Standard_False;
12473     }
12474     else
12475     {
12476       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12477       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12478       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12479       else if (aFlag == "alllayers"
12480             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12481       else if (aFlag == "allstructs"
12482             || aFlag == "allstructures"
12483             || aFlag == "structs"
12484             || aFlag == "structures") aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12485       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12486       else if (aFlag == "allarrays"
12487             || aFlag == "fillarrays"
12488             || aFlag == "linearrays"
12489             || aFlag == "pointarrays"
12490             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12491       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12492       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12493       else if (aFlag == "geommem"
12494             || aFlag == "texturemem"
12495             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12496       else if (aFlag == "elapsedframe"
12497             || aFlag == "cpuframeaverage"
12498             || aFlag == "cpupickingaverage"
12499             || aFlag == "cpucullingaverage"
12500             || aFlag == "cpudynaverage"
12501             || aFlag == "cpuframemax"
12502             || aFlag == "cpupickingmax"
12503             || aFlag == "cpucullingmax"
12504             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12505       else
12506       {
12507         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12508         continue;
12509       }
12510
12511       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12512     }
12513   }
12514
12515   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12516   {
12517     aView->ChangeRenderingParams().CollectedStats =
12518       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12519
12520     if (toRedraw)
12521     {
12522       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12523       aView->Redraw();
12524       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12525     }
12526
12527     TColStd_IndexedDataMapOfStringString aDict;
12528     aView->StatisticInformation (aDict);
12529
12530     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12531
12532     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12533     {
12534       Standard_CString        anArg(theArgVec[anArgIter]);
12535       TCollection_AsciiString aFlag(anArg);
12536       aFlag.LowerCase();
12537       if (aFlag == "fps")
12538       {
12539         theDI << searchInfo (aDict, "FPS") << " ";
12540       }
12541       else if (aFlag == "cpu")
12542       {
12543         theDI << searchInfo (aDict, "CPU FPS") << " ";
12544       }
12545       else if (aFlag == "alllayers")
12546       {
12547         theDI << searchInfo (aDict, "Layers") << " ";
12548       }
12549       else if (aFlag == "layers")
12550       {
12551         theDI << searchInfo (aDict, "Rendered layers") << " ";
12552       }
12553       else if (aFlag == "allstructs"
12554             || aFlag == "allstructures")
12555       {
12556         theDI << searchInfo (aDict, "Structs") << " ";
12557       }
12558       else if (aFlag == "structs"
12559             || aFlag == "structures")
12560       {
12561         TCollection_AsciiString aRend = searchInfo (aDict, "Rendered structs");
12562         if (aRend.IsEmpty()) // all structures rendered
12563         {
12564           aRend = searchInfo (aDict, "Structs");
12565         }
12566         theDI << aRend << " ";
12567       }
12568       else if (aFlag == "groups")
12569       {
12570         theDI << searchInfo (aDict, "Rendered groups") << " ";
12571       }
12572       else if (aFlag == "allarrays")
12573       {
12574         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12575       }
12576       else if (aFlag == "fillarrays")
12577       {
12578         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12579       }
12580       else if (aFlag == "linearrays")
12581       {
12582         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12583       }
12584       else if (aFlag == "pointarrays")
12585       {
12586         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12587       }
12588       else if (aFlag == "textarrays")
12589       {
12590         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12591       }
12592       else if (aFlag == "triangles")
12593       {
12594         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12595       }
12596       else if (aFlag == "points")
12597       {
12598         theDI << searchInfo (aDict, "Rendered points") << " ";
12599       }
12600       else if (aFlag == "geommem")
12601       {
12602         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12603       }
12604       else if (aFlag == "texturemem")
12605       {
12606         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12607       }
12608       else if (aFlag == "framemem")
12609       {
12610         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12611       }
12612       else if (aFlag == "elapsedframe")
12613       {
12614         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12615       }
12616       else if (aFlag == "cpuframe_average")
12617       {
12618         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12619       }
12620       else if (aFlag == "cpupicking_average")
12621       {
12622         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12623       }
12624       else if (aFlag == "cpuculling_average")
12625       {
12626         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12627       }
12628       else if (aFlag == "cpudyn_average")
12629       {
12630         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12631       }
12632       else if (aFlag == "cpuframe_max")
12633       {
12634         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12635       }
12636       else if (aFlag == "cpupicking_max")
12637       {
12638         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12639       }
12640       else if (aFlag == "cpuculling_max")
12641       {
12642         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12643       }
12644       else if (aFlag == "cpudyn_max")
12645       {
12646         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12647       }
12648     }
12649   }
12650   else
12651   {
12652     if (toRedraw)
12653     {
12654       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12655       aView->Redraw();
12656       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12657     }
12658     theDI << "Statistic info:\n" << aView->StatisticInformation();
12659   }
12660   return 0;
12661 }
12662
12663 //=======================================================================
12664 //function : VXRotate
12665 //purpose  :
12666 //=======================================================================
12667 static Standard_Integer VXRotate (Draw_Interpretor& di,
12668                                    Standard_Integer argc,
12669                                    const char ** argv)
12670 {
12671   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12672   if (aContext.IsNull())
12673   {
12674     di << argv[0] << "ERROR : use 'vinit' command before \n";
12675     return 1;
12676   }
12677
12678   if (argc != 3)
12679   {
12680     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12681     return 1;
12682   }
12683
12684   TCollection_AsciiString aName (argv[1]);
12685   Standard_Real anAngle = Draw::Atof (argv[2]);
12686
12687   // find object
12688   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12689   Handle(AIS_InteractiveObject) anIObj;
12690   if (!aMap.Find2 (aName, anIObj))
12691   {
12692     di << "Use 'vdisplay' before\n";
12693     return 1;
12694   }
12695
12696   gp_Trsf aTransform;
12697   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12698   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12699
12700   aContext->SetLocation (anIObj, aTransform);
12701   aContext->UpdateCurrentViewer();
12702   return 0;
12703 }
12704
12705 //===============================================================================================
12706 //function : VManipulator
12707 //purpose  :
12708 //===============================================================================================
12709 static int VManipulator (Draw_Interpretor& theDi,
12710                          Standard_Integer  theArgsNb,
12711                          const char**      theArgVec)
12712 {
12713   Handle(V3d_View)   aCurrentView   = ViewerTest::CurrentView();
12714   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12715   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12716   if (aCurrentView.IsNull()
12717    || aViewer.IsNull())
12718   {
12719     std::cerr << "No active viewer!\n";
12720     return 1;
12721   }
12722
12723   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12724   Standard_Integer anArgIter = 1;
12725   for (; anArgIter < theArgsNb; ++anArgIter)
12726   {
12727     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12728   }
12729
12730   ViewerTest_CmdParser aCmd;
12731   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12732   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12733   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12734   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12735   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12736   aCmd.AddOption ("view",           "... {active | [view name]} - define view in which manipulator will be displayed, 'all' by default");
12737   aCmd.AddOption ("detach",         "...       - detach manipulator");
12738
12739   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12740   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12741   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12742
12743   aCmd.AddOption ("move",   "... x y z - move object");
12744   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
12745   aCmd.AddOption ("scale",  "... factor - scale object");
12746
12747   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12748   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12749   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12750   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12751   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12752   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12753   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
12754   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12755   aCmd.AddOption ("size",              "... size - set size of manipulator");
12756   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12757
12758   aCmd.Parse (theArgsNb, theArgVec);
12759
12760   if (aCmd.HasOption ("help"))
12761   {
12762     theDi.PrintHelp (theArgVec[0]);
12763     return 0;
12764   }
12765
12766   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12767
12768   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
12769
12770   if (aName.IsEmpty())
12771   {
12772     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12773     return 1;
12774   }
12775
12776   // ----------------------------------
12777   // detach existing manipulator object
12778   // ----------------------------------
12779
12780   if (aCmd.HasOption ("detach"))
12781   {
12782     if (!aMapAIS.IsBound2 (aName))
12783     {
12784       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12785       return 1;
12786     }
12787
12788     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12789     if (aManipulator.IsNull())
12790     {
12791       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12792       return 1;
12793     }
12794
12795     aManipulator->Detach();
12796     aMapAIS.UnBind2 (aName);
12797     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12798
12799     return 0;
12800   }
12801
12802   // -----------------------------------------------
12803   // find or create manipulator if it does not exist
12804   // -----------------------------------------------
12805
12806   Handle(AIS_Manipulator) aManipulator;
12807   if (!aMapAIS.IsBound2 (aName))
12808   {
12809     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12810
12811     aManipulator = new AIS_Manipulator();
12812     aManipulator->SetModeActivationOnDetection (true);
12813     aMapAIS.Bind (aManipulator, aName);
12814   }
12815   else
12816   {
12817     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12818     if (aManipulator.IsNull())
12819     {
12820       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12821       return 1;
12822     }
12823   }
12824
12825   // -----------------------------------------
12826   // change properties of manipulator instance
12827   // -----------------------------------------
12828
12829   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12830   {
12831     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12832   }
12833   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12834   {
12835     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12836   }
12837   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12838   {
12839     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12840   }
12841   if (aCmd.HasOption("followDragging", 1, Standard_True))
12842   {
12843     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12844   }
12845   if (aCmd.HasOption ("gap", 1, Standard_True))
12846   {
12847     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12848   }
12849   if (aCmd.HasOption ("part", 3, Standard_True))
12850   {
12851     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12852     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12853     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12854     if (aMode < 1 || aMode > 4)
12855     {
12856       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12857       return 1;
12858     }
12859
12860     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12861   }
12862   if (aCmd.HasOption("parts", 2, Standard_True))
12863   {
12864     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
12865     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
12866     if (aMode < 1 || aMode > 4)
12867     {
12868       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12869       return 1;
12870     }
12871
12872     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
12873   }
12874   if (aCmd.HasOption ("pos", 3, Standard_True))
12875   {
12876     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12877     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12878     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12879
12880     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12881   }
12882   if (aCmd.HasOption ("size", 1, Standard_True))
12883   {
12884     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12885   }
12886   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12887   {
12888     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12889
12890     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12891     {
12892       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12893       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12894     }
12895   }
12896
12897   // ---------------------------------------------------
12898   // attach, detach or access manipulator from an object
12899   // ---------------------------------------------------
12900
12901   if (aCmd.HasOption ("attach"))
12902   {
12903     // Find an object and attach manipulator to it
12904     if (!aCmd.HasOption ("attach", 1, Standard_True))
12905     {
12906       return 1;
12907     }
12908
12909     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12910     Handle(AIS_InteractiveObject) anObject;
12911     if (!aMapAIS.Find2 (anObjName, anObject))
12912     {
12913       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12914       return 1;
12915     }
12916
12917     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (aMapAIS);
12918          anIter.More(); anIter.Next())
12919     {
12920       Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (anIter.Key1());
12921       if (!aManip.IsNull()
12922        && aManip->IsAttached()
12923        && aManip->Object() == anObject)
12924       {
12925         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12926         return 1;
12927       }
12928     }
12929
12930     AIS_Manipulator::OptionsForAttach anOptions;
12931     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12932     {
12933       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12934     }
12935     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12936     {
12937       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12938     }
12939     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12940     {
12941       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12942     }
12943
12944     aManipulator->Attach (anObject, anOptions);
12945
12946     // Check view option
12947     if (aCmd.HasOption ("view"))
12948     {
12949       if (!aCmd.HasOption ("view", 1, Standard_True))
12950       {
12951         return 1;
12952       }
12953       TCollection_AsciiString aViewString (aCmd.Arg ("view", 0).c_str());
12954       Handle(V3d_View) aView;
12955       if (aViewString.IsEqual ("active"))
12956       {
12957         aView = ViewerTest::CurrentView();
12958       }
12959       else // Check view name
12960       {
12961         ViewerTest_Names aViewNames (aViewString);
12962         if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
12963         {
12964           std::cerr << theArgVec[0] << " error: wrong view name '" << aViewString << "'\n";
12965           return 1;
12966         }
12967         aView = ViewerTest_myViews.Find1 (aViewNames.GetViewName());
12968         if (aView.IsNull())
12969         {
12970           std::cerr << theArgVec[0] << " error: cannot find view with name '" << aViewString << "'\n";
12971           return 1;
12972         }
12973       }
12974       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
12975         anIter (ViewerTest_myViews); anIter.More(); anIter.Next())
12976       {
12977         ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, anIter.Value(), Standard_False);
12978       }
12979       ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, aView, Standard_True);
12980     }
12981   }
12982
12983   // --------------------------------------
12984   // apply transformation using manipulator
12985   // --------------------------------------
12986
12987   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12988   {
12989     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12990   }
12991   if (aCmd.HasOption ("transform", 2, Standard_True))
12992   {
12993     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
12994   }
12995   if (aCmd.HasOption ("stopTransform"))
12996   {
12997     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
12998
12999     aManipulator->StopTransform (toApply);
13000   }
13001
13002   gp_Trsf aT;
13003   if (aCmd.HasOption ("move", 3, Standard_True))
13004   {
13005     aT.SetTranslationPart (aCmd.ArgVec ("move"));
13006   }
13007   if (aCmd.HasOption ("rotate", 7, Standard_True))
13008   {
13009     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
13010   }
13011   if (aCmd.HasOption ("scale", 1))
13012   {
13013     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
13014   }
13015
13016   if (aT.Form() != gp_Identity)
13017   {
13018     aManipulator->Transform (aT);
13019   }
13020
13021   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
13022
13023   return 0;
13024 }
13025
13026 //===============================================================================================
13027 //function : VSelectionProperties
13028 //purpose  :
13029 //===============================================================================================
13030 static int VSelectionProperties (Draw_Interpretor& theDi,
13031                                  Standard_Integer  theArgsNb,
13032                                  const char**      theArgVec)
13033 {
13034   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
13035   if (aCtx.IsNull())
13036   {
13037     std::cerr << "No active viewer!\n";
13038     return 1;
13039   }
13040
13041   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
13042   {
13043     // handle obsolete alias
13044     bool toEnable = true;
13045     if (theArgsNb < 2)
13046     {
13047       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
13048       return 0;
13049     }
13050     else if (theArgsNb != 2
13051          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
13052     {
13053       std::cout << "Syntax error: wrong number of parameters.";
13054       return 1;
13055     }
13056     if (toEnable != aCtx->ToHilightSelected())
13057     {
13058       aCtx->ClearDetected();
13059       aCtx->SetToHilightSelected (toEnable);
13060     }
13061     return 0;
13062   }
13063
13064   Standard_Boolean toPrint  = theArgsNb == 1;
13065   Standard_Boolean toRedraw = Standard_False;
13066   Standard_Integer anArgIter = 1;
13067   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
13068   if (anArgIter < theArgsNb)
13069   {
13070     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
13071     anArgFirst.LowerCase();
13072     ++anArgIter;
13073     if (anArgFirst == "dynhighlight"
13074      || anArgFirst == "dynhilight"
13075      || anArgFirst == "dynamichighlight"
13076      || anArgFirst == "dynamichilight")
13077     {
13078       aType = Prs3d_TypeOfHighlight_Dynamic;
13079     }
13080     else if (anArgFirst == "localdynhighlight"
13081           || anArgFirst == "localdynhilight"
13082           || anArgFirst == "localdynamichighlight"
13083           || anArgFirst == "localdynamichilight")
13084     {
13085       aType = Prs3d_TypeOfHighlight_LocalDynamic;
13086     }
13087     else if (anArgFirst == "selhighlight"
13088           || anArgFirst == "selhilight"
13089           || anArgFirst == "selectedhighlight"
13090           || anArgFirst == "selectedhilight")
13091     {
13092       aType = Prs3d_TypeOfHighlight_Selected;
13093     }
13094     else if (anArgFirst == "localselhighlight"
13095           || anArgFirst == "localselhilight"
13096           || anArgFirst == "localselectedhighlight"
13097           || anArgFirst == "localselectedhilight")
13098     {
13099       aType = Prs3d_TypeOfHighlight_LocalSelected;
13100     }
13101     else
13102     {
13103       --anArgIter;
13104     }
13105   }
13106   for (; anArgIter < theArgsNb; ++anArgIter)
13107   {
13108     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13109     anArg.LowerCase();
13110     if (anArg == "-help")
13111     {
13112       theDi.PrintHelp (theArgVec[0]);
13113       return 0;
13114     }
13115     else if (anArg == "-print")
13116     {
13117       toPrint = Standard_True;
13118     }
13119     else if (anArg == "-autoactivate")
13120     {
13121       Standard_Boolean toEnable = Standard_True;
13122       if (anArgIter + 1 < theArgsNb
13123        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13124       {
13125         ++anArgIter;
13126       }
13127       aCtx->SetAutoActivateSelection (toEnable);
13128     }
13129     else if (anArg == "-automatichighlight"
13130           || anArg == "-automatichilight"
13131           || anArg == "-autohighlight"
13132           || anArg == "-autohilight")
13133     {
13134       Standard_Boolean toEnable = Standard_True;
13135       if (anArgIter + 1 < theArgsNb
13136        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13137       {
13138         ++anArgIter;
13139       }
13140       aCtx->ClearSelected (false);
13141       aCtx->ClearDetected();
13142       aCtx->SetAutomaticHilight (toEnable);
13143       toRedraw = true;
13144     }
13145     else if (anArg == "-highlightselected"
13146           || anArg == "-hilightselected")
13147     {
13148       Standard_Boolean toEnable = Standard_True;
13149       if (anArgIter + 1 < theArgsNb
13150        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
13151       {
13152         ++anArgIter;
13153       }
13154       aCtx->ClearDetected();
13155       aCtx->SetToHilightSelected (toEnable);
13156       toRedraw = true;
13157     }
13158     else if (anArg == "-pickstrategy"
13159           || anArg == "-pickingstrategy")
13160     {
13161       if (++anArgIter >= theArgsNb)
13162       {
13163         std::cout << "Syntax error: type of highlighting is undefined\n";
13164         return 1;
13165       }
13166
13167       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13168       TCollection_AsciiString aVal (theArgVec[anArgIter]);
13169       aVal.LowerCase();
13170       if (aVal == "first"
13171        || aVal == "firstaccepted"
13172        || aVal == "firstacceptable")
13173       {
13174         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13175       }
13176       else if (aVal == "topmost"
13177             || aVal == "onlyTopmost")
13178       {
13179         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
13180       }
13181       else
13182       {
13183         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
13184         return 1;
13185       }
13186
13187       aCtx->SetPickingStrategy (aStrategy);
13188     }
13189     else if (anArg == "-pixtol"
13190           && anArgIter + 1 < theArgsNb)
13191     {
13192       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
13193     }
13194     else if ((anArg == "-mode"
13195            || anArg == "-dispmode")
13196           && anArgIter + 1 < theArgsNb)
13197     {
13198       if (aType == Prs3d_TypeOfHighlight_None)
13199       {
13200         std::cout << "Syntax error: type of highlighting is undefined\n";
13201         return 1;
13202       }
13203
13204       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
13205       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13206       aStyle->SetDisplayMode (aDispMode);
13207       toRedraw = Standard_True;
13208     }
13209     else if (anArg == "-layer"
13210           && anArgIter + 1 < theArgsNb)
13211     {
13212       if (aType == Prs3d_TypeOfHighlight_None)
13213       {
13214         std::cout << "Syntax error: type of highlighting is undefined\n";
13215         return 1;
13216       }
13217
13218       ++anArgIter;
13219       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
13220       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
13221       {
13222         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
13223         return 1;
13224       }
13225
13226       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13227       aStyle->SetZLayer (aNewLayer);
13228       toRedraw = Standard_True;
13229     }
13230     else if (anArg == "-hicolor"
13231           || anArg == "-selcolor"
13232           || anArg == "-color")
13233     {
13234       if (anArg.StartsWith ("-hi"))
13235       {
13236         aType = Prs3d_TypeOfHighlight_Dynamic;
13237       }
13238       else if (anArg.StartsWith ("-sel"))
13239       {
13240         aType = Prs3d_TypeOfHighlight_Selected;
13241       }
13242       else if (aType == Prs3d_TypeOfHighlight_None)
13243       {
13244         std::cout << "Syntax error: type of highlighting is undefined\n";
13245         return 1;
13246       }
13247
13248       Quantity_Color aColor;
13249       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
13250                                                            theArgVec + anArgIter + 1,
13251                                                            aColor);
13252       if (aNbParsed == 0)
13253       {
13254         std::cout << "Syntax error: need more arguments.\n";
13255         return 1;
13256       }
13257       anArgIter += aNbParsed;
13258
13259       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13260       aStyle->SetColor (aColor);
13261       toRedraw = Standard_True;
13262     }
13263     else if ((anArg == "-transp"
13264            || anArg == "-transparency"
13265            || anArg == "-hitransp"
13266            || anArg == "-seltransp"
13267            || anArg == "-hitransplocal"
13268            || anArg == "-seltransplocal")
13269           && anArgIter + 1 < theArgsNb)
13270     {
13271       if (anArg.StartsWith ("-hi"))
13272       {
13273         aType = Prs3d_TypeOfHighlight_Dynamic;
13274       }
13275       else if (anArg.StartsWith ("-sel"))
13276       {
13277         aType = Prs3d_TypeOfHighlight_Selected;
13278       }
13279       else if (aType == Prs3d_TypeOfHighlight_None)
13280       {
13281         std::cout << "Syntax error: type of highlighting is undefined\n";
13282         return 1;
13283       }
13284
13285       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
13286       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13287       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
13288       toRedraw = Standard_True;
13289     }
13290     else if ((anArg == "-mat"
13291            || anArg == "-material")
13292           && anArgIter + 1 < theArgsNb)
13293     {
13294       if (aType == Prs3d_TypeOfHighlight_None)
13295       {
13296         std::cout << "Syntax error: type of highlighting is undefined\n";
13297         return 1;
13298       }
13299
13300       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13301       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
13302       if (aMatName != Graphic3d_NOM_DEFAULT)
13303       {
13304         ++anArgIter;
13305         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
13306         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
13307         Graphic3d_MaterialAspect aMat (aMatName);
13308         aMat.SetColor (aStyle->Color());
13309         aMat.SetTransparency (aStyle->Transparency());
13310         anAspect->SetFrontMaterial (aMat);
13311         anAspect->SetInteriorColor (aStyle->Color());
13312         aStyle->SetBasicFillAreaAspect (anAspect);
13313       }
13314       else
13315       {
13316         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
13317       }
13318       toRedraw = Standard_True;
13319     }
13320     else
13321     {
13322       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
13323     }
13324   }
13325
13326   if (toPrint)
13327   {
13328     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
13329     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
13330     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
13331     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
13332     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
13333     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
13334     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
13335     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
13336     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
13337     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
13338     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
13339     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
13340     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
13341     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
13342   }
13343
13344   if (aCtx->NbSelected() != 0 && toRedraw)
13345   {
13346     aCtx->HilightSelected (Standard_True);
13347   }
13348
13349   return 0;
13350 }
13351
13352 //===============================================================================================
13353 //function : VDumpSelectionImage
13354 //purpose  :
13355 //===============================================================================================
13356 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
13357                                 Standard_Integer  theArgsNb,
13358                                 const char**      theArgVec)
13359 {
13360   if (theArgsNb < 2)
13361   {
13362     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
13363     return 1;
13364   }
13365
13366   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13367   if (aContext.IsNull())
13368   {
13369     std::cout << "Error: no active view.\n";
13370     return 1;
13371   }
13372
13373   TCollection_AsciiString aFile;
13374   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13375   Image_Format anImgFormat = Image_Format_BGR;
13376   Standard_Integer aPickedIndex = 1;
13377   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13378   {
13379     TCollection_AsciiString aParam (theArgVec[anArgIter]);
13380     aParam.LowerCase();
13381     if (aParam == "-type")
13382     {
13383       if (++anArgIter >= theArgsNb)
13384       {
13385         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
13386         return 1;
13387       }
13388
13389       TCollection_AsciiString aValue (theArgVec[anArgIter]);
13390       aValue.LowerCase();
13391       if (aValue == "depth"
13392        || aValue == "normdepth"
13393        || aValue == "normalizeddepth")
13394       {
13395         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13396         anImgFormat = Image_Format_GrayF;
13397       }
13398       if (aValue == "depthinverted"
13399        || aValue == "normdepthinverted"
13400        || aValue == "normalizeddepthinverted"
13401        || aValue == "inverted")
13402       {
13403         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
13404         anImgFormat = Image_Format_GrayF;
13405       }
13406       else if (aValue == "unnormdepth"
13407             || aValue == "unnormalizeddepth")
13408       {
13409         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
13410         anImgFormat = Image_Format_GrayF;
13411       }
13412       else if (aValue == "objectcolor"
13413             || aValue == "object"
13414             || aValue == "color")
13415       {
13416         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13417       }
13418       else if (aValue == "entitycolor"
13419             || aValue == "entity")
13420       {
13421         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13422       }
13423       else if (aValue == "ownercolor"
13424             || aValue == "owner")
13425       {
13426         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13427       }
13428       else if (aValue == "selectionmodecolor"
13429             || aValue == "selectionmode"
13430             || aValue == "selmodecolor"
13431             || aValue == "selmode")
13432       {
13433         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13434       }
13435     }
13436     else if (aParam == "-picked"
13437           || aParam == "-pickeddepth"
13438           || aParam == "-pickedindex")
13439     {
13440       if (++anArgIter >= theArgsNb)
13441       {
13442         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13443         return 1;
13444       }
13445
13446       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13447     }
13448     else if (aFile.IsEmpty())
13449     {
13450       aFile = theArgVec[anArgIter];
13451     }
13452     else
13453     {
13454       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13455       return 1;
13456     }
13457   }
13458   if (aFile.IsEmpty())
13459   {
13460     std::cout << "Syntax error: image file name is missing.\n";
13461     return 1;
13462   }
13463
13464   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13465   Standard_Integer aWidth = 0, aHeight = 0;
13466   aView->Window()->Size (aWidth, aHeight);
13467
13468   Image_AlienPixMap aPixMap;
13469   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13470   {
13471     std::cout << "Error: can't allocate image.\n";
13472     return 1;
13473   }
13474   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13475   {
13476     std::cout << "Error: can't generate selection image.\n";
13477     return 1;
13478   }
13479   if (!aPixMap.Save (aFile))
13480   {
13481     std::cout << "Error: can't save selection image.\n";
13482     return 0;
13483   }
13484   return 0;
13485 }
13486
13487 //===============================================================================================
13488 //function : VViewCube
13489 //purpose  :
13490 //===============================================================================================
13491 static int VViewCube (Draw_Interpretor& ,
13492                       Standard_Integer  theNbArgs,
13493                       const char**      theArgVec)
13494 {
13495   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13496   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13497   if (aContext.IsNull() || aView.IsNull())
13498   {
13499     std::cout << "Error: no active view.\n";
13500     return 1;
13501   }
13502   else if (theNbArgs < 2)
13503   {
13504     std::cout << "Syntax error: wrong number arguments\n";
13505     return 1;
13506   }
13507
13508   Handle(AIS_ViewCube) aViewCube;
13509   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
13510   Quantity_Color aColorRgb;
13511   TCollection_AsciiString aName;
13512   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
13513   {
13514     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13515     anArg.LowerCase();
13516     if (anUpdateTool.parseRedrawMode (anArg))
13517     {
13518       //
13519     }
13520     else if (aViewCube.IsNull())
13521     {
13522       aName = theArgVec[anArgIter];
13523       if (aName.StartsWith ("-"))
13524       {
13525         std::cout << "Syntax error: object name should be specified.\n";
13526         return 1;
13527       }
13528       Handle(AIS_InteractiveObject) aPrs;
13529       GetMapOfAIS().Find2 (aName, aPrs);
13530       aViewCube = Handle(AIS_ViewCube)::DownCast (aPrs);
13531       if (aViewCube.IsNull())
13532       {
13533         aViewCube = new AIS_ViewCube();
13534         aViewCube->SetBoxColor (Quantity_NOC_GRAY50);
13535         aViewCube->SetViewAnimation (ViewerTest::CurrentEventManager()->ViewAnimation());
13536         aViewCube->SetFixedAnimationLoop (false);
13537       }
13538     }
13539     else if (anArg == "-reset")
13540     {
13541       aViewCube->ResetStyles();
13542     }
13543     else if (anArg == "-color"
13544           || anArg == "-boxcolor"
13545           || anArg == "-boxsidecolor"
13546           || anArg == "-sidecolor"
13547           || anArg == "-boxedgecolor"
13548           || anArg == "-edgecolor"
13549           || anArg == "-boxcornercolor"
13550           || anArg == "-cornercolor"
13551           || anArg == "-innercolor"
13552           || anArg == "-textcolor")
13553     {
13554       Standard_Integer aNbParsed = ViewerTest::ParseColor (theNbArgs - anArgIter - 1,
13555                                                            theArgVec + anArgIter + 1,
13556                                                            aColorRgb);
13557       if (aNbParsed == 0)
13558       {
13559         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
13560         return 1;
13561       }
13562       anArgIter += aNbParsed;
13563       if (anArg == "-boxcolor")
13564       {
13565         aViewCube->SetBoxColor (aColorRgb);
13566       }
13567       else if (anArg == "-boxsidecolor"
13568             || anArg == "-sidecolor")
13569       {
13570         aViewCube->BoxSideStyle()->SetColor (aColorRgb);
13571         aViewCube->SynchronizeAspects();
13572       }
13573       else if (anArg == "-boxedgecolor"
13574             || anArg == "-edgecolor")
13575       {
13576         aViewCube->BoxEdgeStyle()->SetColor (aColorRgb);
13577         aViewCube->SynchronizeAspects();
13578       }
13579       else if (anArg == "-boxcornercolor"
13580             || anArg == "-cornercolor")
13581       {
13582         aViewCube->BoxCornerStyle()->SetColor (aColorRgb);
13583         aViewCube->SynchronizeAspects();
13584       }
13585       else if (anArg == "-innercolor")
13586       {
13587         aViewCube->SetInnerColor (aColorRgb);
13588       }
13589       else if (anArg == "-textcolor")
13590       {
13591         aViewCube->SetTextColor (aColorRgb);
13592       }
13593       else
13594       {
13595         aViewCube->SetColor (aColorRgb);
13596       }
13597     }
13598     else if (anArgIter + 1 < theNbArgs
13599           && (anArg == "-transparency"
13600            || anArg == "-boxtransparency"))
13601     {
13602       const Standard_Real aValue = Draw::Atof (theArgVec[++anArgIter]);
13603       if (aValue < 0.0 || aValue > 1.0)
13604       {
13605         std::cout << "Syntax error: invalid transparency value " << theArgVec[anArgIter] << "\n";
13606         return 1;
13607       }
13608
13609       if (anArg == "-boxtransparency")
13610       {
13611         aViewCube->SetBoxTransparency (aValue);
13612       }
13613       else
13614       {
13615         aViewCube->SetTransparency (aValue);
13616       }
13617     }
13618     else if (anArg == "-axes"
13619           || anArg == "-edges"
13620           || anArg == "-vertices"
13621           || anArg == "-vertexes"
13622           || anArg == "-fixedanimation")
13623     {
13624       bool toShow = true;
13625       if (anArgIter + 1 < theNbArgs
13626        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toShow))
13627       {
13628         ++anArgIter;
13629       }
13630       if (anArg == "-fixedanimation")
13631       {
13632         aViewCube->SetFixedAnimationLoop (toShow);
13633       }
13634       else if (anArg == "-axes")
13635       {
13636         aViewCube->SetDrawAxes (toShow);
13637       }
13638       else if (anArg == "-edges")
13639       {
13640         aViewCube->SetDrawEdges (toShow);
13641       }
13642       else
13643       {
13644         aViewCube->SetDrawVertices (toShow);
13645       }
13646     }
13647     else if (anArg == "-yup"
13648           || anArg == "-zup")
13649     {
13650       bool isOn = true;
13651       if (anArgIter + 1 < theNbArgs
13652        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isOn))
13653       {
13654         ++anArgIter;
13655       }
13656       if (anArg == "-yup")
13657       {
13658         aViewCube->SetYup (isOn);
13659       }
13660       else
13661       {
13662         aViewCube->SetYup (!isOn);
13663       }
13664     }
13665     else if (anArgIter + 1 < theNbArgs
13666           && anArg == "-font")
13667     {
13668       aViewCube->SetFont (theArgVec[++anArgIter]);
13669     }
13670     else if (anArgIter + 1 < theNbArgs
13671           && anArg == "-fontheight")
13672     {
13673       aViewCube->SetFontHeight (Draw::Atof (theArgVec[++anArgIter]));
13674     }
13675     else if (anArgIter + 1 < theNbArgs
13676           && (anArg == "-size"
13677            || anArg == "-boxsize"))
13678     {
13679       aViewCube->SetSize (Draw::Atof (theArgVec[++anArgIter]),
13680                           anArg != "-boxsize");
13681     }
13682     else if (anArgIter + 1 < theNbArgs
13683           && (anArg == "-boxfacet"
13684            || anArg == "-boxfacetextension"
13685            || anArg == "-facetextension"
13686            || anArg == "-extension"))
13687     {
13688       aViewCube->SetBoxFacetExtension (Draw::Atof (theArgVec[++anArgIter]));
13689     }
13690     else if (anArgIter + 1 < theNbArgs
13691           && (anArg == "-boxedgegap"
13692            || anArg == "-edgegap"))
13693     {
13694       aViewCube->SetBoxEdgeGap (Draw::Atof (theArgVec[++anArgIter]));
13695     }
13696     else if (anArgIter + 1 < theNbArgs
13697           && (anArg == "-boxedgeminsize"
13698            || anArg == "-edgeminsize"))
13699     {
13700       aViewCube->SetBoxEdgeMinSize (Draw::Atof (theArgVec[++anArgIter]));
13701     }
13702     else if (anArgIter + 1 < theNbArgs
13703           && (anArg == "-boxcornerminsize"
13704            || anArg == "-cornerminsize"))
13705     {
13706       aViewCube->SetBoxCornerMinSize (Draw::Atof (theArgVec[++anArgIter]));
13707     }
13708     else if (anArgIter + 1 < theNbArgs
13709           && anArg == "-axespadding")
13710     {
13711       aViewCube->SetAxesPadding (Draw::Atof (theArgVec[++anArgIter]));
13712     }
13713     else if (anArgIter + 1 < theNbArgs
13714           && anArg == "-roundradius")
13715     {
13716       aViewCube->SetRoundRadius (Draw::Atof (theArgVec[++anArgIter]));
13717     }
13718     else if (anArgIter + 1 < theNbArgs
13719           && anArg == "-duration")
13720     {
13721       aViewCube->SetDuration (Draw::Atof (theArgVec[++anArgIter]));
13722     }
13723     else if (anArgIter + 1 < theNbArgs
13724           && anArg == "-axesradius")
13725     {
13726       aViewCube->SetAxesRadius (Draw::Atof (theArgVec[++anArgIter]));
13727     }
13728     else if (anArgIter + 1 < theNbArgs
13729           && anArg == "-axesconeradius")
13730     {
13731       aViewCube->SetAxesConeRadius (Draw::Atof (theArgVec[++anArgIter]));
13732     }
13733     else if (anArgIter + 1 < theNbArgs
13734           && anArg == "-axessphereradius")
13735     {
13736       aViewCube->SetAxesSphereRadius (Draw::Atof (theArgVec[++anArgIter]));
13737     }
13738     else
13739     {
13740       std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
13741       return 1;
13742     }
13743   }
13744   if (aViewCube.IsNull())
13745   {
13746     std::cout << "Syntax error: wrong number of arguments\n";
13747     return 1;
13748   }
13749
13750   ViewerTest::Display (aName, aViewCube, false);
13751   return 0;
13752 }
13753
13754 //=======================================================================
13755 //function : ViewerCommands
13756 //purpose  :
13757 //=======================================================================
13758
13759 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13760 {
13761
13762   const char *group = "ZeViewer";
13763   theCommands.Add("vinit",
13764           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13765     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13766   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13767     "\n\t\t:     [-display displayName]"
13768   #endif
13769     "\n\t\t: Creates new View window with specified name viewName."
13770     "\n\t\t: By default the new view is created in the viewer and in"
13771     "\n\t\t: graphic driver shared with active view."
13772     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13773     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13774     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13775 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13776     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13777     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13778 #endif
13779     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13780     "\n\t\t:  -width, -height width and heigth of window respectively."
13781     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13782     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13783     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13784     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13785     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13786     __FILE__,VInit,group);
13787   theCommands.Add("vclose" ,
13788     "[view_id [keep_context=0|1]]\n"
13789     "or vclose ALL - to remove all created views\n"
13790     " - removes view(viewer window) defined by its view_id.\n"
13791     " - keep_context: by default 0; if 1 and the last view is deleted"
13792     " the current context is not removed.",
13793     __FILE__,VClose,group);
13794   theCommands.Add("vactivate" ,
13795     "vactivate view_id [-noUpdate]"
13796     " - activates view(viewer window) defined by its view_id",
13797     __FILE__,VActivate,group);
13798   theCommands.Add("vviewlist",
13799     "vviewlist [format={tree, long}]"
13800     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13801     " - format: format of result output, if tree the output is a tree view;"
13802     "otherwise it's a list of full view names. By default format = tree",
13803     __FILE__,VViewList,group);
13804   theCommands.Add("vhelp" ,
13805     "vhelp            : display help on the viewer commands",
13806     __FILE__,VHelp,group);
13807   theCommands.Add("vviewproj",
13808           "vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]"
13809     "\n\t\t:         [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]"
13810     "\n\t\t: Setup view direction"
13811     "\n\t\t:   -Yup      use Y-up convention instead of Zup (which is default)."
13812     "\n\t\t:   +-X+-Y+-Z define direction as combination of DX, DY and DZ;"
13813     "\n\t\t:             for example '+Z' will show front of the model,"
13814     "\n\t\t:             '-X-Y+Z' will define left axonometrical view."
13815     "\n\t\t:   -frame    define camera Up and Right directions (regardless Up convention);"
13816     "\n\t\t:             for example '+X+Z' will show front of the model with Z-up."
13817     __FILE__,VViewProj,group);
13818   theCommands.Add("vtop" ,
13819     "vtop or <T>      : Top view. Orientation +X+Y" ,
13820     __FILE__,VViewProj,group);
13821   theCommands.Add("vbottom" ,
13822     "vbottom          : Bottom view. Orientation +X-Y" ,
13823     __FILE__,VViewProj,group);
13824   theCommands.Add("vleft" ,
13825     "vleft            : Left view. Orientation -Y+Z" ,
13826     __FILE__,VViewProj,group);
13827   theCommands.Add("vright" ,
13828     "vright           : Right view. Orientation +Y+Z" ,
13829     __FILE__,VViewProj,group);
13830   theCommands.Add("vaxo" ,
13831     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13832     __FILE__,VViewProj,group);
13833   theCommands.Add("vfront" ,
13834     "vfront           : Front view. Orientation +X+Z" ,
13835     __FILE__,VViewProj,group);
13836   theCommands.Add("vback" ,
13837     "vback            : Back view. Orientation -X+Z" ,
13838     __FILE__,VViewProj,group);
13839   theCommands.Add("vpick" ,
13840     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13841     VPick,group);
13842   theCommands.Add("vfit",
13843     "vfit or <F> [-selected] [-noupdate]"
13844     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13845     __FILE__,VFit,group);
13846   theCommands.Add ("vfitarea",
13847     "vfitarea x1 y1 x2 y2"
13848     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13849     "\n\t\t: Fit view to show area located between two points"
13850     "\n\t\t: given in world 2D or 3D corrdinates.",
13851     __FILE__, VFitArea, group);
13852   theCommands.Add ("vzfit", "vzfit [scale]\n"
13853     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13854     "   \"scale\" - specifies factor to scale computed z range.\n",
13855     __FILE__, VZFit, group);
13856   theCommands.Add("vrepaint",
13857             "vrepaint [-immediate] [-continuous FPS]"
13858     "\n\t\t: force redraw of active View"
13859     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13860     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13861     "\n\t\t:                0 means no continuous rendering,"
13862     "\n\t\t:               -1 means non-stop redraws,"
13863     "\n\t\t:               >0 specifies target framerate,",
13864     __FILE__,VRepaint,group);
13865   theCommands.Add("vclear",
13866     "vclear          : vclear"
13867     "\n\t\t: remove all the object from the viewer",
13868     __FILE__,VClear,group);
13869   theCommands.Add (
13870     "vbackground",
13871     "Changes background or some background settings.\n"
13872     "\n"
13873     "Usage:\n"
13874     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13875     "  vbackground -imageMode FillType\n"
13876     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13877     "  vbackground -gradientMode FillMethod\n"
13878     "  vbackground -cubemap CubemapFile1 [CubeMapFiles2-5] [-order TilesIndexes1-6] [-invertedz]\n"
13879     "  vbackground -color Color\n"
13880     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13881     "  vbackground -default -color Color\n"
13882     "  vbackground -help\n"
13883     "\n"
13884     "Options:\n"
13885     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13886     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13887     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13888     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13889     "  -cubemap      (-cmap, -cm):                         sets environmet cubemap as background\n"
13890     "  -invertedz    (-invz, -iz):                         sets inversion of Z axis for background cubemap rendering\n"
13891     "  -order        (-o):                                 defines order of tiles in one image cubemap\n"
13892     "                                                      (has no effect in case of multi image cubemaps)\n"
13893     "  -color        (-col):                               sets background color\n"
13894     "  -default      (-def):                               sets background default gradient or color\n"
13895     "  -help         (-h):                                 outputs short help message\n"
13896     "\n"
13897     "Arguments:\n"
13898     "  Color:        Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13899     "                                  or reals within the range [0.0, 1.0]\n"
13900     "                ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13901     "                #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13902     "  FillMethod:   one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13903     "CORNER4\n"
13904     "  FillType:     one of CENTERED, TILED, STRETCH, NONE\n"
13905     "  ImageFile:    a name of the file with the image used as a background\n"
13906     "  CubemapFilei: a name of the file with one image packed cubemap or names of separate files with every cubemap side\n"
13907     "  TileIndexi:   a cubemap side index in range [0, 5] for i tile of one image packed cubemap\n",
13908     __FILE__,
13909     vbackground,
13910     group);
13911   theCommands.Add ("vsetbg",
13912                    "Loads image as background."
13913                    "\n\t\t: vsetbg ImageFile [FillType]"
13914                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13915                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13916                    __FILE__,
13917                    vbackground,
13918                    group);
13919   theCommands.Add ("vsetbgmode",
13920                    "Changes background image fill type."
13921                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13922                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13923                    __FILE__,
13924                    vbackground,
13925                    group);
13926   theCommands.Add ("vsetgradientbg",
13927                    "Mounts gradient background."
13928                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13929                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13930                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13931                    __FILE__,
13932                    vbackground,
13933                    group);
13934   theCommands.Add ("vsetgrbgmode",
13935                    "Changes gradient background fill method."
13936                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13937                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13938                    __FILE__,
13939                    vbackground,
13940                    group);
13941   theCommands.Add ("vsetcolorbg",
13942                    "Sets background color."
13943                    "\n\t\t: vsetcolorbg [-color] Color."
13944                    "\n\t\t: Alias for 'vbackground -color Color'.",
13945                    __FILE__,
13946                    vbackground,
13947                    group);
13948   theCommands.Add ("vsetdefaultbg",
13949                    "Sets default viewer background fill color (flat/gradient)."
13950                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13951                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13952                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13953                    "\n\t\t: vsetdefaultbg [-color] Color"
13954                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13955                    __FILE__,
13956                    vbackground,
13957                    group);
13958   theCommands.Add("vscale",
13959     "vscale          : vscale X Y Z",
13960     __FILE__,VScale,group);
13961   theCommands.Add("vzbufftrihedron",
13962             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13963     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13964     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13965     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13966     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13967     "\n\t\t: Displays a trihedron",
13968     __FILE__,VZBuffTrihedron,group);
13969   theCommands.Add("vrotate",
13970     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13971     "\n                : Option -mouseStart starts rotation according to the mouse position"
13972     "\n                : Option -mouseMove continues rotation with angle computed"
13973     "\n                : from last and new mouse position."
13974     "\n                : vrotate AX AY AZ [X Y Z]",
13975     __FILE__,VRotate,group);
13976   theCommands.Add("vzoom",
13977     "vzoom           : vzoom coef",
13978     __FILE__,VZoom,group);
13979   theCommands.Add("vpan",
13980     "vpan            : vpan dx dy",
13981     __FILE__,VPan,group);
13982   theCommands.Add("vcolorscale",
13983     "vcolorscale name [-noupdate|-update] [-demo]"
13984     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13985     "\n\t\t:       [-font HeightFont=20]"
13986     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13987     "\n\t\t:       [-smoothTransition {on|off}=off]"
13988     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13989     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13990     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13991     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13992     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13993     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13994     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13995     "\n\t\t:       [-xy Left=0 Bottom=0]"
13996     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13997     "\n\t\t:  -colors   - set colors for all intervals"
13998     "\n\t\t:  -color    - set color for specific interval"
13999     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
14000     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
14001     "\n\t\t:              at border means the value inbetween neighbor intervals,"
14002     "\n\t\t:              at center means the center value within current interval"
14003     "\n\t\t:  -labels   - set labels for all intervals"
14004     "\n\t\t:  -freeLabels - same as -labels but does not require"
14005     "\n\t\t:              matching the number of intervals"
14006     "\n\t\t:  -label    - set label for specific interval"
14007     "\n\t\t:  -title    - set title"
14008     "\n\t\t:  -reversed - setup smooth color transition between intervals"
14009     "\n\t\t:  -smoothTransition - swap colorscale direction"
14010     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
14011     __FILE__, VColorScale, group);
14012   theCommands.Add("vgraduatedtrihedron",
14013     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
14014     "\t[-namefont Name] [-valuesfont Name]\n"
14015     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
14016     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
14017     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
14018     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
14019     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
14020     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
14021     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
14022     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
14023     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
14024     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
14025     " - Displays or erases graduated trihedron"
14026     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
14027     " - namefont - font of axes names. Default: Arial\n"
14028     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
14029     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
14030     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
14031     " - valuesfont - font of axes values. Default: Arial\n"
14032     " - xcolor, ycolor, zcolor - color of axis and values\n"
14033     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
14034     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
14035     __FILE__,VGraduatedTrihedron,group);
14036   theCommands.Add("vtile" ,
14037             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
14038     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
14039     "\n\t\t:  -totalSize the size of virtual bigger viewport"
14040     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
14041     "\n\t\t:  -lowerLeft tile offset as lower left corner"
14042     "\n\t\t:  -upperLeft tile offset as upper left corner",
14043     __FILE__, VTile, group);
14044   theCommands.Add("vzlayer",
14045               "vzlayer [layerId]"
14046       "\n\t\t:         [-add|-delete|-get|-settings] [-insertBefore AnotherLayer] [-insertAfter AnotherLayer]"
14047       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
14048       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
14049       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv|rayTracing}]"
14050       "\n\t\t: ZLayer list management:"
14051       "\n\t\t:   -add      add new z layer to viewer and print its id"
14052       "\n\t\t:   -insertBefore add new z layer and insert it before existing one"
14053       "\n\t\t:   -insertAfter  add new z layer and insert it after  existing one"
14054       "\n\t\t:   -delete   delete z layer"
14055       "\n\t\t:   -get      print sequence of z layers"
14056       "\n\t\t:   -settings print status of z layer settings"
14057       "\n\t\t:   -disable  disables given setting"
14058       "\n\t\t:   -enable   enables  given setting",
14059     __FILE__,VZLayer,group);
14060   theCommands.Add("vlayerline",
14061     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
14062     __FILE__,VLayerLine,group);
14063   theCommands.Add("vgrid",
14064               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
14065       "\n\t\t:       [-step X Y] [-size DX DY]"
14066       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
14067     __FILE__, VGrid, group);
14068   theCommands.Add ("vpriviledgedplane",
14069     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
14070     "\n\t\t:   Ox, Oy, Oz - plane origin"
14071     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
14072     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
14073     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
14074     __FILE__, VPriviledgedPlane, group);
14075   theCommands.Add ("vconvert",
14076     "vconvert v [Mode={window|view}]"
14077     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
14078     "\n\t\t: vconvert x y z [Mode={window|grid}]"
14079     "\n\t\t:   window - convert to window coordinates, pixels"
14080     "\n\t\t:   view   - convert to view projection plane"
14081     "\n\t\t:   grid   - convert to model coordinates, given on grid"
14082     "\n\t\t:   ray    - convert projection ray to model coordiantes"
14083     "\n\t\t: - vconvert v window : convert view to window;"
14084     "\n\t\t: - vconvert v view   : convert window to view;"
14085     "\n\t\t: - vconvert x y window : convert view to window;"
14086     "\n\t\t: - vconvert x y view : convert window to view;"
14087     "\n\t\t: - vconvert x y : convert window to model;"
14088     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
14089     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
14090     "\n\t\t: - vconvert x y z window : convert model to window;"
14091     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
14092     "\n\t\t: Converts the given coordinates to window/view/model space.",
14093     __FILE__, VConvert, group);
14094   theCommands.Add ("vfps",
14095     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
14096     __FILE__, VFps, group);
14097   theCommands.Add ("vgldebug",
14098             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
14099     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
14100     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
14101     "\n\t\t: Debug context can be requested only on Windows"
14102     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
14103     "\n\t\t:  -sync     - request synchronized debug GL context"
14104     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
14105     "\n\t\t:              which are suppressed by default,"
14106     "\n\t\t:  -glslCode - log GLSL program source code,"
14107     "\n\t\t:              which are suppressed by default,"
14108     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
14109     "\n\t\t:              which are suppressed by default",
14110     __FILE__, VGlDebug, group);
14111   theCommands.Add ("vvbo",
14112     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
14113     __FILE__, VVbo, group);
14114   theCommands.Add ("vstereo",
14115             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
14116     "\n\t\t:         [-anaglyph Filter]"
14117     "\n\t\t: Control stereo output mode. Available modes for -mode:"
14118     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
14119     "\n\t\t:                     requires driver support."
14120     "\n\t\t:                     Should be called BEFORE vinit!"
14121     "\n\t\t:  anaglyph         - Anaglyph glasses"
14122     "\n\t\t:  rowInterlaced    - row-interlaced display"
14123     "\n\t\t:  columnInterlaced - column-interlaced display"
14124     "\n\t\t:  chessBoard       - chess-board output"
14125     "\n\t\t:  sideBySide       - horizontal pair"
14126     "\n\t\t:  overUnder        - vertical   pair"
14127     "\n\t\t: Available Anaglyph filters for -anaglyph:"
14128     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
14129     "\n\t\t:  greenMagentaSimple",
14130     __FILE__, VStereo, group);
14131   theCommands.Add ("vcaps",
14132             "vcaps [-sRGB {0|1}] [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
14133     "\n\t\t:       [-compatibleProfile {0|1}]"
14134     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
14135     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
14136     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
14137     "\n\t\t:       [-noExtensions {0|1}] [-maxVersion Major Minor]"
14138     "\n\t\t: Modify particular graphic driver options:"
14139     "\n\t\t:  sRGB     - enable/disable sRGB rendering"
14140     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
14141     "\n\t\t:             built-in GLSL programs"
14142     "\n\t\t:            (requires compatible profile)"
14143     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
14144     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
14145     "\n\t\t:             arrays to GPU memory)"
14146     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
14147     "\n\t\t:  vsync    - switch VSync on or off"
14148     "\n\t\t:  winBuffer - allow using window buffer for rendering"
14149     "\n\t\t: Context creation options:"
14150     "\n\t\t:  softMode          - software OpenGL implementation"
14151     "\n\t\t:  compatibleProfile - backward-compatible profile"
14152     "\n\t\t:  quadbuffer        - QuadBuffer"
14153     "\n\t\t:  noExtensions      - disallow usage of extensions"
14154     "\n\t\t:  maxVersion        - force upper OpenGL version to be used"
14155     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
14156     "\n\t\t: rendering paths producing the same visual result when"
14157     "\n\t\t: possible."
14158     "\n\t\t: Command is intended for testing old hardware compatibility.",
14159     __FILE__, VCaps, group);
14160   theCommands.Add ("vmemgpu",
14161     "vmemgpu [f]: print system-dependent GPU memory information if available;"
14162     " with f option returns free memory in bytes",
14163     __FILE__, VMemGpu, group);
14164   theCommands.Add ("vreadpixel",
14165     "vreadpixel xPixel yPixel [{rgb|rgba|sRGB|sRGBa|depth|hls|rgbf|rgbaf}=rgba] [-name|-hex]"
14166     " : Read pixel value for active view",
14167     __FILE__, VReadPixel, group);
14168   theCommands.Add("diffimage",
14169             "diffimage imageFile1 imageFile2 [diffImageFile]"
14170     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
14171     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
14172     "\n\t\t: Compare two images by content and generate difference image."
14173     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
14174     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
14175     __FILE__, VDiffImage, group);
14176   theCommands.Add ("vselect",
14177     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
14178     "- emulates different types of selection:\n"
14179     "- 1) single click selection\n"
14180     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
14181     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
14182     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
14183     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
14184     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
14185     " (partial inclusion - overlap - is not allowed by default)\n"
14186     "- 5) any of these selections with shift button pressed",
14187     __FILE__, VSelect, group);
14188   theCommands.Add ("vmoveto",
14189     "vmoveto [x y] [-reset]"
14190     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
14191     "\n\t\t:   -reset resets current highlighting",
14192     __FILE__, VMoveTo, group);
14193   theCommands.Add ("vviewparams",
14194               "vviewparams [-args] [-scale [s]]"
14195       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
14196       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
14197       "\n\t\t: Manage current view parameters or prints all"
14198       "\n\t\t: current values when called without argument."
14199       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
14200       "\n\t\t:   -eye  [x y z] prints or sets eye location"
14201       "\n\t\t:   -at   [x y z] prints or sets center of look"
14202       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
14203       "\n\t\t:   -proj [x y z] prints or sets direction of look"
14204       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
14205       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
14206       "\n\t\t:                 or changes the size of its maximum dimension"
14207       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
14208     __FILE__, VViewParams, group);
14209
14210   theCommands.Add("v2dmode",
14211     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
14212     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
14213     "\n\t\t:   mode   - switches On/Off rotation mode"
14214     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
14215     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
14216     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
14217     "\n\t\t: View camera position might be changed only by commands.",
14218     __FILE__, V2DMode, group);
14219
14220   theCommands.Add("vanimation", "Alias for vanim",
14221     __FILE__, VAnimation, group);
14222
14223   theCommands.Add("vanim",
14224             "List existing animations:"
14225     "\n\t\t:  vanim"
14226     "\n\t\t: Animation playback:"
14227     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
14228     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
14229     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
14230     "\n\t\t:   -freeLook skip camera animations"
14231     "\n\t\t:   -lockLoop disable any interactions"
14232     "\n\t\t:"
14233     "\n\t\t: Animation definition:"
14234     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
14235     "\n\t\t:        [start TimeSec] [duration TimeSec]"
14236     "\n\t\t:"
14237     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
14238     "\n\t\t: specifies nested animations."
14239     "\n\t\t: There is no syntax to explicitly add new animation,"
14240     "\n\t\t: and all non-existing animations within the name will be"
14241     "\n\t\t: implicitly created on first use (including parents)."
14242     "\n\t\t:"
14243     "\n\t\t: Each animation might define the SINGLE action (see below),"
14244     "\n\t\t: like camera transition, object transformation or custom callback."
14245     "\n\t\t: Child animations can be used for defining concurrent actions."
14246     "\n\t\t:"
14247     "\n\t\t: Camera animation:"
14248     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
14249     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
14250     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
14251     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
14252     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
14253     "\n\t\t:   -atX    camera Center positions pair"
14254     "\n\t\t:   -upX    camera Up directions pair"
14255     "\n\t\t:   -scaleX camera Scale factors pair"
14256     "\n\t\t: Object animation:"
14257     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
14258     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
14259     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
14260     "\n\t\t:   -locX   object Location points pair (translation)"
14261     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
14262     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
14263     "\n\t\t: Custom callback:"
14264     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
14265     "\n\t\t:   %Pts        overall animation presentation timestamp"
14266     "\n\t\t:   %LocalPts   local animation timestamp"
14267     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
14268     "\n\t\t:"
14269     "\n\t\t: Video recording:"
14270     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
14271     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
14272     "\n\t\t:             [-crf Value] [-preset Preset]"
14273     "\n\t\t:   -fps     video framerate"
14274     "\n\t\t:   -format  file format, container (matroska, etc.)"
14275     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
14276     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
14277     "\n\t\t:   -crf     constant rate factor (specific to codec)"
14278     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
14279     __FILE__, VAnimation, group);
14280
14281   theCommands.Add("vchangeselected",
14282     "vchangeselected shape"
14283     "- adds to shape to selection or remove one from it",
14284                 __FILE__, VChangeSelected, group);
14285   theCommands.Add ("vnbselected",
14286     "vnbselected"
14287     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
14288   theCommands.Add ("vcamera",
14289               "vcamera [PrsName] [-ortho] [-projtype]"
14290       "\n\t\t:         [-persp]"
14291       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
14292       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
14293       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
14294       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
14295       "\n\t\t: Manages camera parameters."
14296       "\n\t\t: Displays frustum when presntation name PrsName is specified."
14297       "\n\t\t: Prints current value when option called without argument."
14298       "\n\t\t: Orthographic camera:"
14299       "\n\t\t:   -ortho      activate orthographic projection"
14300       "\n\t\t: Perspective camera:"
14301       "\n\t\t:   -persp      activate perspective  projection (mono)"
14302       "\n\t\t:   -fovy       field of view in y axis, in degrees"
14303       "\n\t\t:   -distance   distance of eye from camera center"
14304       "\n\t\t: Stereoscopic camera:"
14305       "\n\t\t:   -stereo     perspective  projection (stereo)"
14306       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
14307       "\n\t\t:   -rightEye   perspective  projection (right eye)"
14308       "\n\t\t:   -iod        intraocular distance value"
14309       "\n\t\t:   -iodType    distance type, absolute or relative"
14310       "\n\t\t:   -zfocus     stereographic focus value"
14311       "\n\t\t:   -zfocusType focus type, absolute or relative",
14312     __FILE__, VCamera, group);
14313   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
14314     "- vautozfit [on={1|0}] [scale]\n"
14315     "    Prints or changes parameters of automatic z-fit mode:\n"
14316     "   \"on\" - turns automatic z-fit on or off\n"
14317     "   \"scale\" - specifies factor to scale computed z range.\n",
14318     __FILE__, VAutoZFit, group);
14319   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
14320     "   vzrange                - without parameters shows current values\n"
14321     "   vzrange [znear] [zfar] - applies provided values to view",
14322     __FILE__,VZRange, group);
14323   theCommands.Add ("vpurgedisplay",
14324     "vpurgedisplay"
14325     "- removes structures which don't belong to objects displayed in neutral point",
14326     __FILE__, VPurgeDisplay, group);
14327   theCommands.Add("vsetviewsize",
14328     "vsetviewsize size",
14329     __FILE__,VSetViewSize,group);
14330   theCommands.Add("vmoveview",
14331     "vmoveview Dx Dy Dz [Start = 1|0]",
14332     __FILE__,VMoveView,group);
14333   theCommands.Add("vtranslateview",
14334     "vtranslateview Dx Dy Dz [Start = 1|0)]",
14335     __FILE__,VTranslateView,group);
14336   theCommands.Add("vturnview",
14337     "vturnview Ax Ay Az [Start = 1|0]",
14338     __FILE__,VTurnView,group);
14339   theCommands.Add("vtextureenv",
14340     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
14341     "or user-defined file and optionally applying texture mapping parameters\n"
14342     "                  Usage:\n"
14343     "                  vtextureenv off - disables environment mapping\n"
14344     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
14345     "                              std_texture = (0..7)\n"
14346     "                              rep         = {clamp|repeat}\n"
14347     "                              mod         = {decal|modulate}\n"
14348     "                              flt         = {nearest|bilinear|trilinear}\n"
14349     "                              ss, st      - scale factors for s and t texture coordinates\n"
14350     "                              ts, tt      - translation for s and t texture coordinates\n"
14351     "                              rot         - texture rotation angle in degrees",
14352     __FILE__, VTextureEnv, group);
14353   theCommands.Add("vhlr",
14354             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
14355       "\n\t\t: Hidden Line Removal algorithm."
14356       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
14357       "\n\t\t:   -algoType   type of HLR algorithm.\n",
14358     __FILE__,VHLR,group);
14359   theCommands.Add("vhlrtype",
14360               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
14361       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
14362       "\n\t\t:   'algo' - exact HLR algorithm is applied"
14363       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
14364       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
14365     __FILE__,VHLRType,group);
14366   theCommands.Add("vclipplane",
14367               "vclipplane planeName [{0|1}]"
14368       "\n\t\t:   [-equation1 A B C D]"
14369       "\n\t\t:   [-equation2 A B C D]"
14370       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
14371       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
14372       "\n\t\t:   [-maxPlanes]"
14373       "\n\t\t:   [-capping {0|1}]"
14374       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
14375       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
14376       "\n\t\t:       [-texRotate Angle]"
14377       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
14378       "\n\t\t:       [-useObjShader {0|1}]"
14379       "\n\t\t: Clipping planes management:"
14380       "\n\t\t:   -maxPlanes   print plane limit for view"
14381       "\n\t\t:   -delete      delete plane with given name"
14382       "\n\t\t:   {off|on|0|1} turn clipping on/off"
14383       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
14384       "\n\t\t:                applied to active View when list is omitted"
14385       "\n\t\t:   -equation A B C D change plane equation"
14386       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
14387       "\n\t\t: Capping options:"
14388       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
14389       "\n\t\t:   -color R G B          set capping color"
14390       "\n\t\t:   -transparency Value   set capping transparency 0..1"
14391       "\n\t\t:   -texName Texture      set capping texture"
14392       "\n\t\t:   -texScale SX SY       set capping tex scale"
14393       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
14394       "\n\t\t:   -texRotate Angle      set capping tex rotation"
14395       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
14396       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
14397       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
14398       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
14399       __FILE__, VClipPlane, group);
14400   theCommands.Add("vdefaults",
14401                "vdefaults [-absDefl value]"
14402        "\n\t\t:           [-devCoeff value]"
14403        "\n\t\t:           [-angDefl value]"
14404        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
14405     , __FILE__, VDefaults, group);
14406   theCommands.Add("vlight",
14407     "tool to manage light sources, without arguments shows list of lights."
14408     "\n    Main commands: "
14409     "\n      '-clear' to clear lights"
14410     "\n      '-{def}aults' to load deafault lights"
14411     "\n      '-add' <type> to add any light source"
14412     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
14413     "\n      'change' <lightId> to edit light source with specified lightId"
14414     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
14415     "\n        -layer Id"
14416     "\n        -{pos}ition X Y Z"
14417     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
14418     "\n        -color colorName"
14419     "\n        -{head}light 0|1"
14420     "\n        -{sm}oothness value"
14421     "\n        -{int}ensity value"
14422     "\n        -{constAtten}uation value"
14423     "\n        -{linearAtten}uation value"
14424     "\n        -angle angleDeg"
14425     "\n        -{spotexp}onent value"
14426     "\n        -range value"
14427     "\n        -local|-global"
14428     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
14429     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
14430     __FILE__, VLight, group);
14431   theCommands.Add("vpbrenv",
14432     "vpbrenv -clear|-generate"
14433     "\n\t\t: Clears or generates PBR environment map of active view."
14434     "\n\t\t:  -clear clears PBR environment (fills by white color)"
14435     "\n\t\t:  -generate generates PBR environment from current background cubemap",
14436     __FILE__, VPBREnvironment, group);
14437   theCommands.Add("vraytrace",
14438             "vraytrace [0|1]"
14439     "\n\t\t: Turns on/off ray-tracing renderer."
14440     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
14441     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
14442     __FILE__, VRenderParams, group);
14443   theCommands.Add("vrenderparams",
14444     "\n    Manages rendering parameters: "
14445     "\n      '-raster'                   Disables GPU ray-tracing"
14446     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
14447     "\n      '-lineFeather  > 0'         Sets line feather factor"
14448     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
14449     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
14450     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
14451     "\n      '-rendScale    value        Rendering resolution scale factor"
14452     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
14453     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
14454     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
14455     "\n      '-reflections  on|off'      Enables/disables specular reflections"
14456     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
14457     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
14458     "\n      '-gi           on|off'      Enables/disables global illumination effects"
14459     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
14460     "\n      '-env          on|off'      Enables/disables environment map background"
14461     "\n      '-ignoreNormalMap on|off'   Enables/disables normal map ignoring during path tracing"
14462     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
14463     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
14464     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
14465     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
14466     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
14467     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
14468     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
14469     "\n      '-shadingModel model'       Controls shading model from enumeration"
14470     "\n                                  unlit, flat, gouraud, phong"
14471     "\n      '-pbrEnvPow2size > 0'       Controls size of IBL maps (real size can be calculates as 2^pbrenvpow2size)"
14472     "\n      '-pbrEnvSMLN > 1'           Controls number of mipmap levels used in specular IBL map"
14473     "\n      '-pbrEnvBDSN > 0'           Controls number of samples in Monte-Carlo integration during diffuse IBL map's sherical harmonics calculation"
14474     "\n      '-pbrEnvBSSN > 0'           Controls maximum number of samples per mipmap level in Monte-Carlo integration during specular IBL maps generation"
14475     "\n      '-pbrEnvBP [0, 1]'          Controls strength of samples number reducing during specular IBL maps generation (1 disables reducing)"
14476     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
14477     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
14478     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
14479     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
14480     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
14481     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
14482     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triangles|points"
14483     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
14484     "\n                                  Show/hide performance counters (flags can be combined)"
14485     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
14486     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
14487     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
14488     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
14489     "\n                                        set state to check structures culled previously."
14490     "\n    Unlike vcaps, these parameters dramatically change visual properties."
14491     "\n    Command is intended to control presentation quality depending on"
14492     "\n    hardware capabilities and performance.",
14493     __FILE__, VRenderParams, group);
14494   theCommands.Add("vstatprofiler",
14495     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
14496     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
14497     "\n                |triangles|points|geomMem|textureMem|frameMem"
14498     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
14499     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
14500     "\n                [-noredraw]"
14501     "\n\t\t: Prints rendering statistics."
14502     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
14503     "\n\t\t:   else - print all performance counters set previously."
14504     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
14505     __FILE__, VStatProfiler, group);
14506   theCommands.Add ("vplace",
14507             "vplace dx dy"
14508     "\n\t\t: Places the point (in pixels) at the center of the window",
14509     __FILE__, VPlace, group);
14510   theCommands.Add("vxrotate",
14511     "vxrotate",
14512     __FILE__,VXRotate,group);
14513
14514     theCommands.Add("vmanipulator",
14515       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
14516       "\n    tool to create and manage AIS manipulators."
14517       "\n    Options: "
14518       "\n      '-attach AISObject'                 attach manipulator to AISObject"
14519       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
14520       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
14521       "\n      '-enableModes    {0|1}'             enable modes when attaching"
14522       "\n      '-view  {active | [name of view]}'  display manipulator only in defined view,"
14523       "\n                                          by default it is displayed in all views of the current viewer"
14524       "\n      '-detach'                           detach manipulator"
14525       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
14526       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
14527       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
14528       "\n      '-move x y z'                     - move attached object"
14529       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
14530       "\n      '-scale factor'                   - scale attached object"
14531       "\n      '-autoActivate      {0|1}'        - set activation on detection"
14532       "\n      '-followTranslation {0|1}'        - set following translation transform"
14533       "\n      '-followRotation    {0|1}'        - set following rotation transform"
14534       "\n      '-followDragging    {0|1}'        - set following dragging transform"
14535       "\n      '-gap value'                      - set gap between sub-parts"
14536       "\n      '-part axis mode    {0|1}'        - set visual part"
14537       "\n      '-parts axis mode   {0|1}'        - set visual part"
14538       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
14539       "\n      '-size value'                     - set size of manipulator"
14540       "\n      '-zoomable {0|1}'                 - set zoom persistence",
14541     __FILE__, VManipulator, group);
14542
14543   theCommands.Add("vselprops",
14544     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
14545     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
14546     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
14547     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
14548     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
14549     "\n    -pickStrategy {first|topmost} : defines picking strategy"
14550     "\n                            'first'   to pick first acceptable (default)"
14551     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
14552     "\n    -pixTol    value        : sets up pixel tolerance"
14553     "\n    -dispMode  dispMode     : sets display mode for highlighting"
14554     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
14555     "\n    -color     {name|r g b} : sets highlight color"
14556     "\n    -transp    value        : sets transparency coefficient for highlight"
14557     "\n    -material  material     : sets highlight material"
14558     "\n    -print                  : prints current state of all mentioned parameters",
14559     __FILE__, VSelectionProperties, group);
14560   theCommands.Add ("vhighlightselected",
14561                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
14562                    __FILE__, VSelectionProperties, group);
14563
14564   theCommands.Add ("vseldump",
14565                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
14566                    "\n\t\t: Generate an image based on detection results:"
14567                    "\n\t\t:   depth       normalized depth values"
14568                    "\n\t\t:   unnormDepth unnormalized depth values"
14569                    "\n\t\t:   object      color of detected object"
14570                    "\n\t\t:   owner       color of detected owner"
14571                    "\n\t\t:   selMode     color of selection mode"
14572                    "\n\t\t:   entity      color of etected entity",
14573                    __FILE__, VDumpSelectionImage, group);
14574
14575   theCommands.Add ("vviewcube",
14576                    "vviewcube name"
14577                    "\n\t\t: Displays interactive view manipualtion object."
14578                    "\n\t\t: Options: "
14579                    "\n\t\t:   -reset                   reset geomertical and visual attributes'"
14580                    "\n\t\t:   -size Size               adapted size of View Cube"
14581                    "\n\t\t:   -boxSize Size            box size"
14582                    "\n\t\t:   -axes {0|1 }             show/hide axes (trihedron)"
14583                    "\n\t\t:   -edges {0|1}             show/hide edges of View Cube"
14584                    "\n\t\t:   -vertices {0|1}          show/hide vertices of View Cube"
14585                    "\n\t\t:   -Yup {0|1} -Zup {0|1}    set Y-up or Z-up view orientation"
14586                    "\n\t\t:   -color Color             color of View Cube"
14587                    "\n\t\t:   -boxColor Color          box color"
14588                    "\n\t\t:   -boxSideColor Color      box sides color"
14589                    "\n\t\t:   -boxEdgeColor Color      box edges color"
14590                    "\n\t\t:   -boxCornerColor Color    box corner color"
14591                    "\n\t\t:   -textColor Color         color of side text of view cube"
14592                    "\n\t\t:   -innerColor Color        inner box color"
14593                    "\n\t\t:   -transparency Value      transparency of object within [0, 1] range"
14594                    "\n\t\t:   -boxTransparency Value   transparency of box    within [0, 1] range"
14595                    "\n\t\t:   -font Name               font name"
14596                    "\n\t\t:   -fontHeight Value        font height"
14597                    "\n\t\t:   -boxFacetExtension Value box facet extension"
14598                    "\n\t\t:   -boxEdgeGap Value        gap between box edges and box sides"
14599                    "\n\t\t:   -boxEdgeMinSize Value    minimal box edge size"
14600                    "\n\t\t:   -boxCornerMinSize Value  minimal box corner size"
14601                    "\n\t\t:   -axesPadding Value       padding between box and arrows"
14602                    "\n\t\t:   -roundRadius Value       relative radius of corners of sides within [0.0, 0.5] range"
14603                    "\n\t\t:   -axesRadius Value        radius of axes of the trihedron"
14604                    "\n\t\t:   -axesConeRadius Value    radius of the cone (arrow) of the trihedron"
14605                    "\n\t\t:   -axesSphereRadius Value  radius of the sphere (central point) of trihedron"
14606                    "\n\t\t:   -fixedanimation {0|1}    uninterruptible animation loop"
14607                    "\n\t\t:   -duration Seconds        animation duration in seconds",
14608     __FILE__, VViewCube, group);
14609
14610 }